diff --git a/.editorconfig b/.editorconfig index 64ab1ec096..af1bd5ecf9 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,4 +1,4 @@ -[{*.ts,*.js,*jsx,*tsx,*.json,*.code-workspace}] +[{*.ts,*.js,*jsx,*tsx,*.json,,*.jsonc,*.code-workspace}] insert_final_newline = true indent_style = space indent_size = 2 diff --git a/.eslintrc.js b/.eslintrc.js index 5ed62fb4e7..db4ec866ec 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -11,10 +11,17 @@ module.exports = { plugins: ['@typescript-eslint', 'prettier', 'import'], rules: { 'import/newline-after-import': 1, - 'import/order': ["error", { "newlines-between": "always", "groups": ["builtin", ["external", "internal"], "parent", "sibling", "index"] }], + 'import/order': [ + "error", + { + "newlines-between": "always-and-inside-groups", + "groups": ["builtin", "external", "internal", "parent", "sibling", "index"] + } + ], 'prettier/prettier': ['error'], - 'sort-imports': 'off', // No auto-fix! + 'sort-imports': 'off', 'no-case-declarations': 'off', + 'no-constant-condition': 'error', '@typescript-eslint/adjacent-overload-signatures': 'error', '@typescript-eslint/array-type': [ 'error', @@ -23,13 +30,10 @@ module.exports = { } ], '@typescript-eslint/await-thenable': 'off', - '@typescript-eslint/ban-ts-ignore': 'error', '@typescript-eslint/ban-types': 'error', 'brace-style': 'off', '@typescript-eslint/brace-style': 'error', - camelcase: 'off', - '@typescript-eslint/camelcase': 'error', - '@typescript-eslint/class-name-casing': 'error', + camelcase: 'error', '@typescript-eslint/consistent-type-assertions': 'error', '@typescript-eslint/consistent-type-definitions': 'error', '@typescript-eslint/explicit-function-return-type': 'off', @@ -39,11 +43,10 @@ module.exports = { '@typescript-eslint/generic-type-naming': 'off', indent: 'off', '@typescript-eslint/indent': 'off', - '@typescript-eslint/interface-name-prefix': ['error', 'never'], '@typescript-eslint/member-delimiter-style': 'off', - '@typescript-eslint/member-naming': 'error', '@typescript-eslint/member-ordering': 'off', - 'no-array-constructor': 'off', + 'no-array-constructor': 'error', + 'no-duplicate-case': 'error', '@typescript-eslint/no-array-constructor': 'error', 'no-empty-function': 'off', '@typescript-eslint/no-empty-function': 'off', @@ -56,6 +59,7 @@ module.exports = { '@typescript-eslint/no-for-in-array': 'error', '@typescript-eslint/no-inferrable-types': 'off', 'no-magic-numbers': 'off', + 'no-fallthrough': 'off', '@typescript-eslint/no-magic-numbers': 'off', '@typescript-eslint/no-misused-new': 'error', '@typescript-eslint/no-misused-promises': 'off', diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 0c0a851406..5da35b1db3 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -15,11 +15,8 @@ assignees: '' -```js -module.exports = function(config){ - config.set({ - .... - }); +```json +{ } ``` diff --git a/.github/workflows/mutation-testing.yml b/.github/workflows/mutation-testing.yml index 5ca9c035cf..e9638ab0d1 100644 --- a/.github/workflows/mutation-testing.yml +++ b/.github/workflows/mutation-testing.yml @@ -1,75 +1,35 @@ name: mutation testing on: + workflow_dispatch: push: branches: - master - test/** - + jobs: core: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - - uses: actions/setup-node@v1 - with: - node-version: 12.x - - name: Install & Build - run: | - npm install - npm run build - - name: Run Stryker - run: npx lerna run --scope "@stryker-mutator/core" --concurrency 1 --stream stryker - env: - STRYKER_DASHBOARD_API_KEY: ${{ secrets.STRYKER_DASHBOARD_API_KEY }} - - plugins-1: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - uses: actions/setup-node@v1 - with: - node-version: 12.x - name: Install & Build run: | npm install npm run build - name: Run Stryker - run: npx lerna run --scope "@stryker-mutator/{api,babel-transpiler,jasmine-framework,javascript-mutator}" --concurrency 1 --stream stryker + run: npx lerna run --scope "@stryker-mutator/core" --concurrency 1 --stream stryker -- -- --concurrency 3 env: STRYKER_DASHBOARD_API_KEY: ${{ secrets.STRYKER_DASHBOARD_API_KEY }} - plugins-2: + dependencies_and_plugins: runs-on: ubuntu-latest - steps: - uses: actions/checkout@v1 - - uses: actions/setup-node@v1 - with: - node-version: 12.x - name: Install & Build run: | npm install npm run build - name: Run Stryker - run: npx lerna run --scope "@stryker-mutator/{jasmine-runner,jest-runner,karma-runner,mocha-framework,mocha-runner}" --concurrency 1 --stream stryker + run: npx lerna run --scope "@stryker-mutator/{api,instrumenter,util,typescript-checker,jest-runner,karma-runner,mocha-runner,jasmine-runner}" --concurrency 1 --stream stryker -- -- --concurrency 3 env: - STRYKER_DASHBOARD_API_KEY: ${{ secrets.STRYKER_DASHBOARD_API_KEY }} - - plugins-3: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v1 - - uses: actions/setup-node@v1 - with: - node-version: 12.x - - name: Install & Build - run: | - npm install - npm run build - - name: Run Stryker - run: npx lerna run --scope "@stryker-mutator/{typescript,vue-mutator,webpack-transpiler,wct-runner,util}" --concurrency 1 --stream stryker - env: - STRYKER_DASHBOARD_API_KEY: ${{ secrets.STRYKER_DASHBOARD_API_KEY }} + STRYKER_DASHBOARD_API_KEY: ${{ secrets.STRYKER_DASHBOARD_API_KEY }} \ No newline at end of file diff --git a/.github/workflows/performance.yml b/.github/workflows/performance.yml index a2738ee564..ea350adc65 100644 --- a/.github/workflows/performance.yml +++ b/.github/workflows/performance.yml @@ -13,7 +13,9 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 + with: + submodules: recursive - name: Install dependencies run: npm install - name: Build packages diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 010894cb64..75863792cc 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -18,4 +18,4 @@ jobs: - name: Build run: npm run build - name: Release - run: npx lerna publish from-git --yes + run: npx lerna publish from-git --yes --pre-dist-tag next diff --git a/.gitignore b/.gitignore index 9fbbcad0ac..99fe4738e7 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,9 @@ packages/*/src/**/*.js packages/*/test/**/*.js packages/*/src/**/*.d.ts packages/*/test/**/*.d.ts +packages/*/dist +e2e/test/*/dist +e2e/test/*/dist-test .idea *.iml *.tmp.txt diff --git a/.gitmodules b/.gitmodules index eacb1df41d..b5b1887337 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "perf/test/express"] path = perf/test/express - url = git@github.com:expressjs/express.git + url = https://github.com/expressjs/express.git diff --git a/.prettierrc b/.prettierrc index 14db9c73d9..82d4c405d4 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,4 +1,5 @@ { - "printWidth": 150, - "singleQuote": true -} + 'printWidth': 150, + 'singleQuote': true, + 'endOfLine': 'auto', +} \ No newline at end of file diff --git a/.travis/Stryker.db b/.travis/Stryker.db index 7736f7aff0..097dccf638 100644 Binary files a/.travis/Stryker.db and b/.travis/Stryker.db differ diff --git a/.vscode/launch.json b/.vscode/launch.json index 867396e489..53d2180992 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,6 +4,15 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Launch Program", + "program": "${file}", + "skipFiles": [ + "/**" + ] + }, { "type": "node", "request": "launch", @@ -60,12 +69,6 @@ ], "internalConsoleOptions": "openOnSessionStart" }, - { - "type": "node", - "request": "launch", - "name": "Launch Program", - "program": "${workspaceRoot}\\packages\\stryker-mocha-runner\"" - }, { "type": "node", "request": "attach", diff --git a/CHANGELOG.md b/CHANGELOG.md index cf6846f5c4..11a0691731 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,255 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [4.0.0-beta.10](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.9...v4.0.0-beta.10) (2020-10-05) + + +### Bug Fixes + +* **instrumenter:** switch case mutant placer ([#2518](https://github.com/stryker-mutator/stryker/issues/2518)) ([a560711](https://github.com/stryker-mutator/stryker/commit/a560711023990dca950700da18269e78249b5c49)) + + +### Features + +* **instrumenter:** add excludedMutations support ([#2513](https://github.com/stryker-mutator/stryker/issues/2513)) ([bfd714f](https://github.com/stryker-mutator/stryker/commit/bfd714fe1b4f9c3b2468164a95d0c5bd0cbc8fcf)) + + + + + +# [4.0.0-beta.9](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.8...v4.0.0-beta.9) (2020-09-30) + + +### Bug Fixes + +* **config:** deprecate function based config ([#2499](https://github.com/stryker-mutator/stryker/issues/2499)) ([8ea3c18](https://github.com/stryker-mutator/stryker/commit/8ea3c18421929a0724ff99e5bf02ce0f174266cd)) +* **core:** fix "too many open files" ([#2498](https://github.com/stryker-mutator/stryker/issues/2498)) ([5b7c242](https://github.com/stryker-mutator/stryker/commit/5b7c2424dc57b32d390112bcbf8b79bf41c05a11)) +* **instrumenter:** only add header when there are mutats ([#2503](https://github.com/stryker-mutator/stryker/issues/2503)) ([8f989cc](https://github.com/stryker-mutator/stryker/commit/8f989cceb8fea5e66e3055a623f238ce85ef1025)) +* **mutate config:** don't warn about files not existing at the default mutate location ([#2509](https://github.com/stryker-mutator/stryker/issues/2509)) ([66c2444](https://github.com/stryker-mutator/stryker/commit/66c24447e28c4218d3e58b945b1bcc5891855097)), closes [#2455](https://github.com/stryker-mutator/stryker/issues/2455) +* **shebang:** support shebang in in files ([#2510](https://github.com/stryker-mutator/stryker/issues/2510)) ([7d2dd80](https://github.com/stryker-mutator/stryker/commit/7d2dd80f2c7a89f31c8f96c2e911a6f9beaf7cbc)) + + +### Features + +* **core:** add `appendPlugins` command-line option ([#2385](https://github.com/stryker-mutator/stryker/issues/2385)) ([0dec9b8](https://github.com/stryker-mutator/stryker/commit/0dec9b84b07391752af5514f90a2120c4f01d260)) +* **core:** correct initial test run timing ([#2496](https://github.com/stryker-mutator/stryker/issues/2496)) ([4f5a37e](https://github.com/stryker-mutator/stryker/commit/4f5a37eb63a4e9532022821dac85d68f8939ceab)) +* **jest-runner:** deprecate "create-react-app-ts" ([#2497](https://github.com/stryker-mutator/stryker/issues/2497)) ([0aacc7b](https://github.com/stryker-mutator/stryker/commit/0aacc7be5bb045887e96f0a8115b7e3e46e1a1ff)) +* **test-runner:** Add `--maxTestRunnerReuse` support ([5919484](https://github.com/stryker-mutator/stryker/commit/59194841505e520ddc382ea4affc78ef16978e1b)) + + +### BREAKING CHANGES + +* **config:** exporting a function from stryker.conf.js is deprecated. Please export your config as an object instead, or use a stryker.conf.json file. + +Co-authored-by: Nico Jansen + + + + + +# [4.0.0-beta.8](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.7...v4.0.0-beta.8) (2020-09-22) + + +### Bug Fixes + +* **instrumenter:** ignore `declare` syntax ([b1faa16](https://github.com/stryker-mutator/stryker/commit/b1faa1603f68dded5d694cdb41b6e75b05ac9e1a)) + + +### Features + +* **core:** add `--cleanTempDir` cli option ([6ef792c](https://github.com/stryker-mutator/stryker/commit/6ef792c839c0464c7acbeb72560574dc94480eea)) +* **instrumenter:** improve placement error ([12e097e](https://github.com/stryker-mutator/stryker/commit/12e097e287d24e41656d2b3897335b3f93654e5d)) + + + + + +# [4.0.0-beta.7](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.6...v4.0.0-beta.7) (2020-09-17) + + +### Bug Fixes + +* **core:** allow skipped tests when matching mutants ([#2487](https://github.com/stryker-mutator/stryker/issues/2487)) ([09eacee](https://github.com/stryker-mutator/stryker/commit/09eaceece587e4e583348fbec7682ba77715bd8c)), closes [#2485](https://github.com/stryker-mutator/stryker/issues/2485) +* **instrumenter:** don't mutate constructor blocks with initialized class properties ([#2484](https://github.com/stryker-mutator/stryker/issues/2484)) ([ca464a3](https://github.com/stryker-mutator/stryker/commit/ca464a31e180aada677464591154c41295fbc50c)), closes [#2474](https://github.com/stryker-mutator/stryker/issues/2474) +* **instrumenter:** place mutants in if statements ([#2481](https://github.com/stryker-mutator/stryker/issues/2481)) ([4df4102](https://github.com/stryker-mutator/stryker/commit/4df410263be09468323d7f64d95a8a839432e52f)), closes [#2469](https://github.com/stryker-mutator/stryker/issues/2469) + + + + + +# [4.0.0-beta.6](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.5...v4.0.0-beta.6) (2020-09-10) + + +### Bug Fixes + +* **instrumenter:** skip `as` expressions ([#2471](https://github.com/stryker-mutator/stryker/issues/2471)) ([2432d84](https://github.com/stryker-mutator/stryker/commit/2432d8442bd783448568a92c57349ecab626def0)) + + + + + +# [4.0.0-beta.5](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.4...v4.0.0-beta.5) (2020-09-09) + + +### Bug Fixes + +* **jasmine-runner:** fix memory leaks ([457d807](https://github.com/stryker-mutator/stryker/commit/457d807989bd2a69a9e1b7bc33c3971a37c19737)) +* **mocha-runner:** don't allow custom timeout ([#2463](https://github.com/stryker-mutator/stryker/issues/2463)) ([e90b563](https://github.com/stryker-mutator/stryker/commit/e90b5635907dfcd36de98d73fa6c2da31f69fbed)) +* **mocha-runner:** fix memory leaks ([23eede2](https://github.com/stryker-mutator/stryker/commit/23eede22036c9efa502af8016e530af780a7cebb)) +* **reporters:** correctly report avg tests/mutants ([#2458](https://github.com/stryker-mutator/stryker/issues/2458)) ([582e01b](https://github.com/stryker-mutator/stryker/commit/582e01befe7ce2effdcde86f2c3123ccaff89c18)) + + +### Features + +* **mutate:** a new default for `mutate` ([#2452](https://github.com/stryker-mutator/stryker/issues/2452)) ([673516d](https://github.com/stryker-mutator/stryker/commit/673516d3fb92534fc3aad62d17243b558fae3ba4)), closes [#2384](https://github.com/stryker-mutator/stryker/issues/2384) +* **typescript:** Disable type checking ([#2446](https://github.com/stryker-mutator/stryker/issues/2446)) ([3ff996b](https://github.com/stryker-mutator/stryker/commit/3ff996b7516b7782434d86aa9aecbee334978a7f)), closes [#2438](https://github.com/stryker-mutator/stryker/issues/2438) + + + + + +# [4.0.0-beta.4](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.3...v4.0.0-beta.4) (2020-08-29) + + +### Bug Fixes + +* **input files:** support emojis in file names ([#2430](https://github.com/stryker-mutator/stryker/issues/2430)) ([139f9f3](https://github.com/stryker-mutator/stryker/commit/139f9f3ea9aa2349198cb824ceb444f7c6b013b6)) +* **input files:** support emojis in file names ([#2433](https://github.com/stryker-mutator/stryker/issues/2433)) ([b5feae2](https://github.com/stryker-mutator/stryker/commit/b5feae2558ade9a1f2d947f7fd046033e4c9d996)) + + +### Features + +* **api:** rename test_runner2 -> test_runner ([#2442](https://github.com/stryker-mutator/stryker/issues/2442)) ([4d3ae97](https://github.com/stryker-mutator/stryker/commit/4d3ae9764dbd689c895b76e44f2eea76c82fabc8)) +* **jest-runner:** switch mutants using env ([#2416](https://github.com/stryker-mutator/stryker/issues/2416)) ([cad01ba](https://github.com/stryker-mutator/stryker/commit/cad01baf9f4fc3bab2ae5244627586133fb618be)) +* **karma-runner:** force bail = true in all cases ([ba928a1](https://github.com/stryker-mutator/stryker/commit/ba928a10d9e4c67ade9648927fb6b281ad2e3d55)) +* **options:** deprecate old stryker options ([#2395](https://github.com/stryker-mutator/stryker/issues/2395)) ([7c637c8](https://github.com/stryker-mutator/stryker/commit/7c637c8714169a03facd42a7521f7670b7606a32)) +* **reporter-api:** support mutation switching ([67f1ed5](https://github.com/stryker-mutator/stryker/commit/67f1ed52f4d17df4306362064180d267ed5445c7)) +* **test-runner:** add `nrOfTests` metric ([0eea448](https://github.com/stryker-mutator/stryker/commit/0eea44892e2383e8b0a34c6267e2f455d604f55a)) +* **wct-runner:** drop support for wct ([#2440](https://github.com/stryker-mutator/stryker/issues/2440)) ([7c55424](https://github.com/stryker-mutator/stryker/commit/7c55424a6deca5301af50206ea93905faaa0056b)) + + +### Performance Improvements + +* **express:** add benchmark express ([#2431](https://github.com/stryker-mutator/stryker/issues/2431)) ([7cfb8f1](https://github.com/stryker-mutator/stryker/commit/7cfb8f1568530439d8bbf40c87b9ce1ab1fa7e96)) + + +### BREAKING CHANGES + +* **api:** Plugin creators should now use `'test_runner'` instead of `'test_runner2'`. +* **wct-runner:** The @stryker-mutator/wct-runner package is dropped in Stryker 4.0. Please see https://github.com/stryker-mutator/stryker/issues/2386 for more details. Feel free to keep using @stryker-mutator/wct-runner@3 or start a community fork. Note that [support for the web-component-tester itself is minimal](https://github.com/Polymer/tools/issues/3398), you might want to consider switching to a different test runner. Stryker still supports Mocha, Jest, Jasmine and Karma. +* **reporter-api:** The `onMutantTested` and `onAllMutantsTested` methods on the `Reporter` api have changed + + + + + +# [4.0.0-beta.3](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.2...v4.0.0-beta.3) (2020-08-19) + + +### Bug Fixes + +* **core:** exit process on error ([#2378](https://github.com/stryker-mutator/stryker/issues/2378)) ([af18a59](https://github.com/stryker-mutator/stryker/commit/af18a590fc916d75d54bcfaf2dda1d6a90bd4df8)), closes [#2315](https://github.com/stryker-mutator/stryker/issues/2315) +* **exit prematurely:** exit when no tests were executed ([#2380](https://github.com/stryker-mutator/stryker/issues/2380)) ([6885e16](https://github.com/stryker-mutator/stryker/commit/6885e16fad7699ba93e6ebbbf0755c7d98c50c5a)) +* **instrumenter:** support anonymous function names ([#2388](https://github.com/stryker-mutator/stryker/issues/2388)) ([c7d150a](https://github.com/stryker-mutator/stryker/commit/c7d150ab1af4341bb59381ef55fa54eff0113a11)), closes [#2362](https://github.com/stryker-mutator/stryker/issues/2362) + + +### Features + +* **core:** add ability to override file headers ([#2363](https://github.com/stryker-mutator/stryker/issues/2363)) ([430d6d3](https://github.com/stryker-mutator/stryker/commit/430d6d3d17fe2ad8e2cef3b858afa7efb86c2342)) +* **core:** strip comments in sandbox ([#2365](https://github.com/stryker-mutator/stryker/issues/2365)) ([55f27f2](https://github.com/stryker-mutator/stryker/commit/55f27f29b6994096c9aad038958ee93e9fa0f035)), closes [#2364](https://github.com/stryker-mutator/stryker/issues/2364) +* **instrumenter:** add support for `.mjs` and `.cjs` file formats ([#2391](https://github.com/stryker-mutator/stryker/issues/2391)) ([5ba4c5c](https://github.com/stryker-mutator/stryker/commit/5ba4c5c93a721982019aa7e124e491decec2e9f0)) +* **jest-runner:** remove deprecated project types ([#2361](https://github.com/stryker-mutator/stryker/issues/2361)) ([d0aa5c3](https://github.com/stryker-mutator/stryker/commit/d0aa5c3c2f676176d3fbceb24ab2cd17011c9ecf)) +* **mocha:** deprecate mocha < v6 ([#2379](https://github.com/stryker-mutator/stryker/issues/2379)) ([fee0754](https://github.com/stryker-mutator/stryker/commit/fee0754c395ade4ee92d434963034e59ea5d180d)) +* **test runner api:** remove `sandboxFileNames` injectable values ([#2369](https://github.com/stryker-mutator/stryker/issues/2369)) ([92f3bf5](https://github.com/stryker-mutator/stryker/commit/92f3bf528d0b01be1f6c219b37a5f90da0431686)), closes [#2351](https://github.com/stryker-mutator/stryker/issues/2351) + + +### BREAKING CHANGES + +* **exit prematurely:** Stryker will now exit with exit code 1 when no tests were executed in the initial test run. +* **mocha:** Mocha@<6 is deprecated and support for it will be removed in Stryker v5 +* **jest-runner:** Project types `react` and `react-ts` has been removed. Please use `create-react-app` and `create-react-app-ts` respectively + + + + + +# [4.0.0-beta.2](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.1...v4.0.0-beta.2) (2020-08-07) + + +### Bug Fixes + +* **ArrowFunction mutator:** don't mutate () => undefined ([#2313](https://github.com/stryker-mutator/stryker/issues/2313)) ([310145e](https://github.com/stryker-mutator/stryker/commit/310145ec853a56b6520e0358861ba492b5dff0a6)) +* **instrumenter:** don't mutate string literals in object properties ([#2354](https://github.com/stryker-mutator/stryker/issues/2354)) ([cd43952](https://github.com/stryker-mutator/stryker/commit/cd439522650fe59c1607d00d58d331b5dc45fe39)) +* **mutator:** issue with block statement mutator ([#2342](https://github.com/stryker-mutator/stryker/issues/2342)) ([aaa4ff6](https://github.com/stryker-mutator/stryker/commit/aaa4ff6cd5bdfadef5047ec2c405ad0f385249ef)), closes [#2314](https://github.com/stryker-mutator/stryker/issues/2314) + + +### Features + +* **command:** Support command test runner with mutation switching ([#2345](https://github.com/stryker-mutator/stryker/issues/2345)) ([59b1cfc](https://github.com/stryker-mutator/stryker/commit/59b1cfc06c4f8f5ec1e55dce4823e0f9c384b16c)) +* **jest-runner:** support mutation switching ([#2350](https://github.com/stryker-mutator/stryker/issues/2350)) ([9e6e6e0](https://github.com/stryker-mutator/stryker/commit/9e6e6e077731344ed0588d64b5c8ba2f19c8492e)) + + + + + +# [4.0.0-beta.1](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.0...v4.0.0-beta.1) (2020-07-17) + + +### Bug Fixes + +* **Jest:** Notify users of lacking Jest support ([#2322](https://github.com/stryker-mutator/stryker/issues/2322)) ([0bbc0c1](https://github.com/stryker-mutator/stryker/commit/0bbc0c119ba5d661ba9751d241ba548293738aa8)) + + + + + +# [4.0.0-beta.0](https://github.com/stryker-mutator/stryker/compare/v3.3.1...v4.0.0-beta.0) (2020-07-10) + + +### Bug Fixes + +* **buildCommand:** allow for a single command string in posix ([77b6a20](https://github.com/stryker-mutator/stryker/commit/77b6a209955bb71fffee61919cec6b3a14db2eff)) +* **instrumenter:** don't mutate `require` ([963e289](https://github.com/stryker-mutator/stryker/commit/963e28921c48ec2d4113ded0eefde7049fff3263)) +* **jasmine-runner:** update deprecated api calls ([#2250](https://github.com/stryker-mutator/stryker/issues/2250)) ([b6d6dfd](https://github.com/stryker-mutator/stryker/commit/b6d6dfdabf8db748660b9818415864de27d55a7f)) +* **karma-runner:** mocha filtering with `/` ([#2290](https://github.com/stryker-mutator/stryker/issues/2290)) ([3918633](https://github.com/stryker-mutator/stryker/commit/3918633b21ff37d2e950df2cc14b8557ee7eb6b3)) +* **reporter:** report event order ([#2311](https://github.com/stryker-mutator/stryker/issues/2311)) ([ceb73a8](https://github.com/stryker-mutator/stryker/commit/ceb73a83dddce0df1bd1c6b9f7e7e8e75fe77e31)) +* **sandbox:** exec build command before symlink ([bd25cd6](https://github.com/stryker-mutator/stryker/commit/bd25cd6ce2f28fe4b1b1b3ac792d99a9742e438b)) +* **typescript-checker:** support empty files ([#2310](https://github.com/stryker-mutator/stryker/issues/2310)) ([284a28c](https://github.com/stryker-mutator/stryker/commit/284a28cbe831ad4c4ed161f2d700fa88663120ca)) + + +### Features + +* **api:** add id to Mutant interface ([#2255](https://github.com/stryker-mutator/stryker/issues/2255)) ([cfc9053](https://github.com/stryker-mutator/stryker/commit/cfc90537d0b9815cba2b44b9681d171ca602766e)) +* **api:** add new test runner api ([#2249](https://github.com/stryker-mutator/stryker/issues/2249)) ([bbbc308](https://github.com/stryker-mutator/stryker/commit/bbbc308806f46260ed0777ea2a33342ec12d105e)) +* **api:** remove support for options editors ([5e56d0e](https://github.com/stryker-mutator/stryker/commit/5e56d0ea6982faf11048c8ca4bbb912ee17e88eb)) +* **checker:** add checker api ([#2240](https://github.com/stryker-mutator/stryker/issues/2240)) ([d463f86](https://github.com/stryker-mutator/stryker/commit/d463f8639437c114da4fe30115652e8a470dd179)), closes [#1514](https://github.com/stryker-mutator/stryker/issues/1514) [#1980](https://github.com/stryker-mutator/stryker/issues/1980) +* **core:** add support for checker plugins ([#2285](https://github.com/stryker-mutator/stryker/issues/2285)) ([69358e1](https://github.com/stryker-mutator/stryker/commit/69358e1423701c730e29d303119a08d74081f340)) +* **core:** support build command ([f71ba87](https://github.com/stryker-mutator/stryker/commit/f71ba87a7adfd85131e1dea5fb1d6f3d8bba76df)) +* **html-parser:** add `// [@ts-nocheck](https://github.com/ts-nocheck)` to scripts ([8ceff31](https://github.com/stryker-mutator/stryker/commit/8ceff31aabda981551a5f5997e820fc9af76565d)) +* **instrumenter:** add mutant placers ([#2224](https://github.com/stryker-mutator/stryker/issues/2224)) ([0e05025](https://github.com/stryker-mutator/stryker/commit/0e0502523a32ffbe836e93da9ade479b01393c5a)) +* **instrumenter:** add parsers ([#2222](https://github.com/stryker-mutator/stryker/issues/2222)) ([3b57ef2](https://github.com/stryker-mutator/stryker/commit/3b57ef23dd5b348dcdff205600989aea2c7fbcf0)) +* **instrumenter:** add the mutation testing instrumenter ([#2212](https://github.com/stryker-mutator/stryker/issues/2212)) ([197e177](https://github.com/stryker-mutator/stryker/commit/197e177cb730952b22d3e5929f4799c2bae476d7)) +* **instrumenter:** add transformers ([#2234](https://github.com/stryker-mutator/stryker/issues/2234)) ([61c8fe6](https://github.com/stryker-mutator/stryker/commit/61c8fe65e35bb95b786a0e2bebbe57166ffbc480)) +* **instrumenter:** allow override of babel plugins ([8758cfd](https://github.com/stryker-mutator/stryker/commit/8758cfdda8ac2bfa761568f55ddee48c2a23f0e0)) +* **instrumenter:** implement `Instrumenter` class ([8df9172](https://github.com/stryker-mutator/stryker/commit/8df9172b95b6e277f44302469edb3c00324a02bd)) +* **jasmine-runner:** implement new test runner api ([#2256](https://github.com/stryker-mutator/stryker/issues/2256)) ([871db8c](https://github.com/stryker-mutator/stryker/commit/871db8c24c3389133d9b4476acd33b0ddd956a36)), closes [#2249](https://github.com/stryker-mutator/stryker/issues/2249) +* **mutator:** remove `Mutator` API ([3ca89cf](https://github.com/stryker-mutator/stryker/commit/3ca89cf7e23af70f83e0c0ac02ab5241fc0790ff)) +* **mutators:** add mutators to instrumenter package ([#2266](https://github.com/stryker-mutator/stryker/issues/2266)) ([3b87743](https://github.com/stryker-mutator/stryker/commit/3b87743645db9923d4c85146ea861aa1b7265447)) +* **sandbox:** add ignore header to js files ([#2291](https://github.com/stryker-mutator/stryker/issues/2291)) ([3adde83](https://github.com/stryker-mutator/stryker/commit/3adde830deb8d4b471ae6fceafd603c9750419d7)), closes [#2276](https://github.com/stryker-mutator/stryker/issues/2276) +* **test-framework:** remove `TestFramework` API ([fe5e200](https://github.com/stryker-mutator/stryker/commit/fe5e200e1f7ad7a24ebceacb2a62c2be58ce6a4f)) +* **transpiler:** remove `Transpiler` API ([06f668b](https://github.com/stryker-mutator/stryker/commit/06f668bf8660f78b12916b2236f3fd9bf86bf23b)) +* **tsconfig:** rewrite tsconfig references ([#2292](https://github.com/stryker-mutator/stryker/issues/2292)) ([4ee4950](https://github.com/stryker-mutator/stryker/commit/4ee4950bebd8db9c2f5a514edee57de55c040526)), closes [#2276](https://github.com/stryker-mutator/stryker/issues/2276) +* **typescript-checker:** a typescript type checker plugin ([#2241](https://github.com/stryker-mutator/stryker/issues/2241)) ([42adb95](https://github.com/stryker-mutator/stryker/commit/42adb9561cdd10172f955fda044854bcc1b7b515)), closes [/github.com/stryker-mutator/stryker/blob/f44008993a543dc3f38ca99516f56d315fdcb735/packages/typescript/src/transpiler/TranspilingLanguageService.ts#L23](https://github.com//github.com/stryker-mutator/stryker/blob/f44008993a543dc3f38ca99516f56d315fdcb735/packages/typescript/src/transpiler/TranspilingLanguageService.ts/issues/L23) [#391](https://github.com/stryker-mutator/stryker/issues/391) + + +### BREAKING CHANGES + +* **core:** * `--maxConcurrentTestRunners` is now deprecated. Please use `--concurrency` instead. + + + + + ## [3.3.1](https://github.com/stryker-mutator/stryker/compare/v3.3.0...v3.3.1) (2020-07-04) diff --git a/e2e/helpers.ts b/e2e/helpers.ts index 50c62407d7..de11c6b19a 100644 --- a/e2e/helpers.ts +++ b/e2e/helpers.ts @@ -2,7 +2,7 @@ import { promises as fs } from 'fs'; import { mutationTestReportSchema } from '@stryker-mutator/api/report'; import { expect } from 'chai'; -import * as path from 'path'; +import path from 'path'; import { calculateMetrics, MetricsResult, Metrics } from 'mutation-testing-metrics'; export async function readMutationTestResult(eventResultDirectory = path.resolve('reports', 'mutation', 'events')) { diff --git a/e2e/package-lock.json b/e2e/package-lock.json index aaff35ac95..0879e455a6 100644 --- a/e2e/package-lock.json +++ b/e2e/package-lock.json @@ -490,12 +490,20 @@ } }, "@babel/plugin-syntax-class-properties": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.1.tgz", - "integrity": "sha512-Gf2Yx/iRs1JREDtVZ56OrjjgFHCaldpTnuy9BHla10qyVT3YkIIGEtoDWhyop0ksu1GvNjHIoYRBqm3zoR1jyQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz", + "integrity": "sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.1" + "@babel/helper-plugin-utils": "^7.10.4" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", + "dev": true + } } }, "@babel/plugin-syntax-dynamic-import": { @@ -507,6 +515,23 @@ "@babel/helper-plugin-utils": "^7.8.0" } }, + "@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", + "dev": true + } + } + }, "@babel/plugin-syntax-json-strings": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", @@ -517,12 +542,20 @@ } }, "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.1.tgz", - "integrity": "sha512-XyHIFa9kdrgJS91CUH+ccPVTnJShr8nLGc5bG2IhGXv5p1Rd+8BleGE5yzIg2Nc1QZAdHDa0Qp4m6066OL96Iw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.1" + "@babel/helper-plugin-utils": "^7.10.4" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", + "dev": true + } } }, "@babel/plugin-syntax-nullish-coalescing-operator": { @@ -535,12 +568,20 @@ } }, "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.1.tgz", - "integrity": "sha512-uTd0OsHrpe3tH5gRPTxG8Voh99/WCU78vIm5NMRYPAqC8lR4vajt6KkCAknCHrx24vkPdd/05yfdGSB4EIY2mg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.1" + "@babel/helper-plugin-utils": "^7.10.4" + }, + "dependencies": { + "@babel/helper-plugin-utils": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", + "dev": true + } } }, "@babel/plugin-syntax-object-rest-spread": { @@ -1125,15 +1166,16 @@ "dev": true }, "@jest/console": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-26.0.1.tgz", - "integrity": "sha512-9t1KUe/93coV1rBSxMmBAOIK3/HVpwxArCA1CxskKyRiv6o8J70V8C/V3OJminVCTa2M0hQI9AWRd5wxu2dAHw==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-26.3.0.tgz", + "integrity": "sha512-/5Pn6sJev0nPUcAdpJHMVIsA8sKizL2ZkcKPE5+dJrCccks7tcM7c9wbgHudBJbxXLoTbqsHkG1Dofoem4F09w==", "dev": true, "requires": { - "@jest/types": "^26.0.1", + "@jest/types": "^26.3.0", + "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^26.0.1", - "jest-util": "^26.0.1", + "jest-message-util": "^26.3.0", + "jest-util": "^26.3.0", "slash": "^3.0.0" }, "dependencies": { @@ -1185,9 +1227,9 @@ "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -1196,33 +1238,34 @@ } }, "@jest/core": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-26.0.1.tgz", - "integrity": "sha512-Xq3eqYnxsG9SjDC+WLeIgf7/8KU6rddBxH+SCt18gEpOhAGYC/Mq+YbtlNcIdwjnnT+wDseXSbU0e5X84Y4jTQ==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-26.4.2.tgz", + "integrity": "sha512-sDva7YkeNprxJfepOctzS8cAk9TOekldh+5FhVuXS40+94SHbiicRO1VV2tSoRtgIo+POs/Cdyf8p76vPTd6dg==", "dev": true, "requires": { - "@jest/console": "^26.0.1", - "@jest/reporters": "^26.0.1", - "@jest/test-result": "^26.0.1", - "@jest/transform": "^26.0.1", - "@jest/types": "^26.0.1", + "@jest/console": "^26.3.0", + "@jest/reporters": "^26.4.1", + "@jest/test-result": "^26.3.0", + "@jest/transform": "^26.3.0", + "@jest/types": "^26.3.0", + "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.4", - "jest-changed-files": "^26.0.1", - "jest-config": "^26.0.1", - "jest-haste-map": "^26.0.1", - "jest-message-util": "^26.0.1", + "jest-changed-files": "^26.3.0", + "jest-config": "^26.4.2", + "jest-haste-map": "^26.3.0", + "jest-message-util": "^26.3.0", "jest-regex-util": "^26.0.0", - "jest-resolve": "^26.0.1", - "jest-resolve-dependencies": "^26.0.1", - "jest-runner": "^26.0.1", - "jest-runtime": "^26.0.1", - "jest-snapshot": "^26.0.1", - "jest-util": "^26.0.1", - "jest-validate": "^26.0.1", - "jest-watcher": "^26.0.1", + "jest-resolve": "^26.4.0", + "jest-resolve-dependencies": "^26.4.2", + "jest-runner": "^26.4.2", + "jest-runtime": "^26.4.2", + "jest-snapshot": "^26.4.2", + "jest-util": "^26.3.0", + "jest-validate": "^26.4.2", + "jest-watcher": "^26.3.0", "micromatch": "^4.0.2", "p-each-series": "^2.1.0", "rimraf": "^3.0.0", @@ -1321,9 +1364,9 @@ "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -1341,71 +1384,73 @@ } }, "@jest/environment": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-26.0.1.tgz", - "integrity": "sha512-xBDxPe8/nx251u0VJ2dFAFz2H23Y98qdIaNwnMK6dFQr05jc+Ne/2np73lOAx+5mSBO/yuQldRrQOf6hP1h92g==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-26.3.0.tgz", + "integrity": "sha512-EW+MFEo0DGHahf83RAaiqQx688qpXgl99wdb8Fy67ybyzHwR1a58LHcO376xQJHfmoXTu89M09dH3J509cx2AA==", "dev": true, "requires": { - "@jest/fake-timers": "^26.0.1", - "@jest/types": "^26.0.1", - "jest-mock": "^26.0.1" + "@jest/fake-timers": "^26.3.0", + "@jest/types": "^26.3.0", + "@types/node": "*", + "jest-mock": "^26.3.0" } }, "@jest/fake-timers": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-26.0.1.tgz", - "integrity": "sha512-Oj/kCBnTKhm7CR+OJSjZty6N1bRDr9pgiYQr4wY221azLz5PHi08x/U+9+QpceAYOWheauLP8MhtSVFrqXQfhg==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-26.3.0.tgz", + "integrity": "sha512-ZL9ytUiRwVP8ujfRepffokBvD2KbxbqMhrXSBhSdAhISCw3gOkuntisiSFv+A6HN0n0fF4cxzICEKZENLmW+1A==", "dev": true, "requires": { - "@jest/types": "^26.0.1", + "@jest/types": "^26.3.0", "@sinonjs/fake-timers": "^6.0.1", - "jest-message-util": "^26.0.1", - "jest-mock": "^26.0.1", - "jest-util": "^26.0.1" + "@types/node": "*", + "jest-message-util": "^26.3.0", + "jest-mock": "^26.3.0", + "jest-util": "^26.3.0" } }, "@jest/globals": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-26.0.1.tgz", - "integrity": "sha512-iuucxOYB7BRCvT+TYBzUqUNuxFX1hqaR6G6IcGgEqkJ5x4htNKo1r7jk1ji9Zj8ZMiMw0oB5NaA7k5Tx6MVssA==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-26.4.2.tgz", + "integrity": "sha512-Ot5ouAlehhHLRhc+sDz2/9bmNv9p5ZWZ9LE1pXGGTCXBasmi5jnYjlgYcYt03FBwLmZXCZ7GrL29c33/XRQiow==", "dev": true, "requires": { - "@jest/environment": "^26.0.1", - "@jest/types": "^26.0.1", - "expect": "^26.0.1" + "@jest/environment": "^26.3.0", + "@jest/types": "^26.3.0", + "expect": "^26.4.2" } }, "@jest/reporters": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-26.0.1.tgz", - "integrity": "sha512-NWWy9KwRtE1iyG/m7huiFVF9YsYv/e+mbflKRV84WDoJfBqUrNRyDbL/vFxQcYLl8IRqI4P3MgPn386x76Gf2g==", + "version": "26.4.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-26.4.1.tgz", + "integrity": "sha512-aROTkCLU8++yiRGVxLsuDmZsQEKO6LprlrxtAuzvtpbIFl3eIjgIf3EUxDKgomkS25R9ZzwGEdB5weCcBZlrpQ==", "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^26.0.1", - "@jest/test-result": "^26.0.1", - "@jest/transform": "^26.0.1", - "@jest/types": "^26.0.1", + "@jest/console": "^26.3.0", + "@jest/test-result": "^26.3.0", + "@jest/transform": "^26.3.0", + "@jest/types": "^26.3.0", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", "glob": "^7.1.2", "graceful-fs": "^4.2.4", "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-instrument": "^4.0.3", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.0.2", - "jest-haste-map": "^26.0.1", - "jest-resolve": "^26.0.1", - "jest-util": "^26.0.1", - "jest-worker": "^26.0.0", - "node-notifier": "^7.0.0", + "jest-haste-map": "^26.3.0", + "jest-resolve": "^26.4.0", + "jest-util": "^26.3.0", + "jest-worker": "^26.3.0", + "node-notifier": "^8.0.0", "slash": "^3.0.0", "source-map": "^0.6.0", "string-length": "^4.0.1", "terminal-link": "^2.0.0", - "v8-to-istanbul": "^4.1.3" + "v8-to-istanbul": "^5.0.1" }, "dependencies": { "ansi-styles": { @@ -1462,9 +1507,9 @@ "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -1473,9 +1518,9 @@ } }, "@jest/source-map": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-26.0.0.tgz", - "integrity": "sha512-S2Z+Aj/7KOSU2TfW0dyzBze7xr95bkm5YXNUqqCek+HE0VbNNSNzrRwfIi5lf7wvzDTSS0/ib8XQ1krFNyYgbQ==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-26.3.0.tgz", + "integrity": "sha512-hWX5IHmMDWe1kyrKl7IhFwqOuAreIwHhbe44+XH2ZRHjrKIh0LO5eLQ/vxHFeAfRwJapmxuqlGAEYLadDq6ZGQ==", "dev": true, "requires": { "callsites": "^3.0.0", @@ -1492,46 +1537,46 @@ } }, "@jest/test-result": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-26.0.1.tgz", - "integrity": "sha512-oKwHvOI73ICSYRPe8WwyYPTtiuOAkLSbY8/MfWF3qDEd/sa8EDyZzin3BaXTqufir/O/Gzea4E8Zl14XU4Mlyg==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-26.3.0.tgz", + "integrity": "sha512-a8rbLqzW/q7HWheFVMtghXV79Xk+GWwOK1FrtimpI5n1la2SY0qHri3/b0/1F0Ve0/yJmV8pEhxDfVwiUBGtgg==", "dev": true, "requires": { - "@jest/console": "^26.0.1", - "@jest/types": "^26.0.1", + "@jest/console": "^26.3.0", + "@jest/types": "^26.3.0", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" } }, "@jest/test-sequencer": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-26.0.1.tgz", - "integrity": "sha512-ssga8XlwfP8YjbDcmVhwNlrmblddMfgUeAkWIXts1V22equp2GMIHxm7cyeD5Q/B0ZgKPK/tngt45sH99yLLGg==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-26.4.2.tgz", + "integrity": "sha512-83DRD8N3M0tOhz9h0bn6Kl6dSp+US6DazuVF8J9m21WAp5x7CqSMaNycMP0aemC/SH/pDQQddbsfHRTBXVUgog==", "dev": true, "requires": { - "@jest/test-result": "^26.0.1", + "@jest/test-result": "^26.3.0", "graceful-fs": "^4.2.4", - "jest-haste-map": "^26.0.1", - "jest-runner": "^26.0.1", - "jest-runtime": "^26.0.1" + "jest-haste-map": "^26.3.0", + "jest-runner": "^26.4.2", + "jest-runtime": "^26.4.2" } }, "@jest/transform": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-26.0.1.tgz", - "integrity": "sha512-pPRkVkAQ91drKGbzCfDOoHN838+FSbYaEAvBXvKuWeeRRUD8FjwXkqfUNUZL6Ke48aA/1cqq/Ni7kVMCoqagWA==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-26.3.0.tgz", + "integrity": "sha512-Isj6NB68QorGoFWvcOjlUhpkT56PqNIsXKR7XfvoDlCANn/IANlh8DrKAA2l2JKC3yWSMH5wS0GwuQM20w3b2A==", "dev": true, "requires": { "@babel/core": "^7.1.0", - "@jest/types": "^26.0.1", + "@jest/types": "^26.3.0", "babel-plugin-istanbul": "^6.0.0", "chalk": "^4.0.0", "convert-source-map": "^1.4.0", "fast-json-stable-stringify": "^2.0.0", "graceful-fs": "^4.2.4", - "jest-haste-map": "^26.0.1", + "jest-haste-map": "^26.3.0", "jest-regex-util": "^26.0.0", - "jest-util": "^26.0.1", + "jest-util": "^26.3.0", "micromatch": "^4.0.2", "pirates": "^4.0.1", "slash": "^3.0.0", @@ -1627,9 +1672,9 @@ "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -1647,13 +1692,14 @@ } }, "@jest/types": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.0.1.tgz", - "integrity": "sha512-IbtjvqI9+eS1qFnOIEL7ggWmT+iK/U+Vde9cGWtYb/b6XgKb3X44ZAe/z9YZzoAAZ/E92m0DqrilF934IGNnQA==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.3.0.tgz", + "integrity": "sha512-BDPG23U0qDeAvU4f99haztXwdAg3hz4El95LkAM+tHAqqhiVzRpEGHHU8EDxT/AnxOrA65YjLBwDahdJ9pTLJQ==", "dev": true, "requires": { "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", "@types/yargs": "^15.0.0", "chalk": "^4.0.0" }, @@ -1700,9 +1746,9 @@ "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -1710,10 +1756,26 @@ } } }, + "@mrmlnc/readdir-enhanced": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", + "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", + "dev": true, + "requires": { + "call-me-maybe": "^1.0.1", + "glob-to-regexp": "^0.3.0" + } + }, + "@nodelib/fs.stat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", + "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", + "dev": true + }, "@sinonjs/commons": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.0.tgz", - "integrity": "sha512-wEj54PfsZ5jGSwMX68G8ZXFawcSglQSXqCftWX3ec8MDUzQdHgcKvw97awHbY0efQEL5iKUOAmmVtoYgmrSG4Q==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz", + "integrity": "sha512-892K+kWUUi3cl+LlqEWIDrhvLgdL79tECi8JZUyq6IviKy/DNhuzCRlbHUjxK89f4ypPMMaFnFuR9Ie6DoIMsw==", "dev": true, "requires": { "type-detect": "4.0.8" @@ -1729,9 +1791,9 @@ } }, "@types/babel__core": { - "version": "7.1.8", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.8.tgz", - "integrity": "sha512-KXBiQG2OXvaPWFPDS1rD8yV9vO0OuWIqAEqLsbfX0oU2REN5KuoMnZ1gClWcBhO5I3n6oTVAmrMufOvRqdmFTQ==", + "version": "7.1.9", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.9.tgz", + "integrity": "sha512-sY2RsIJ5rpER1u3/aQ8OFSI7qGIy8o1NEEbgb2UaJcvOtXOMpd39ko723NBpjQFg9SIX7TXtjejZVGeIMLhoOw==", "dev": true, "requires": { "@babel/parser": "^7.1.0", @@ -1761,9 +1823,9 @@ } }, "@types/babel__traverse": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.12.tgz", - "integrity": "sha512-t4CoEokHTfcyfb4hUaF9oOHu9RmmNWnm1CP0YmMqOOfClKascOmvlEM736vlqeScuGvBDsHkf8R2INd4DWreQA==", + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.13.tgz", + "integrity": "sha512-i+zS7t6/s9cdQvbqKDARrcbrPvtJGlbYsMkazo03nTAK3RX9FNrLllXys22uiTGJapPOTZTQ35nHh4ISph4SLQ==", "dev": true, "requires": { "@babel/types": "^7.3.0" @@ -1800,15 +1862,134 @@ } }, "@types/istanbul-reports": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz", - "integrity": "sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz", + "integrity": "sha512-nwKNbvnwJ2/mndE9ItP/zc2TCzw6uuodnF4EHYWD+gCQDVBuRQL5UzbZD0/ezy1iKsFU2ZQiDqg4M9dN4+wZgA==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "*", "@types/istanbul-lib-report": "*" } }, + "@types/jest": { + "version": "26.0.10", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.10.tgz", + "integrity": "sha512-i2m0oyh8w/Lum7wWK/YOZJakYF8Mx08UaKA1CtbmFeDquVhAEdA7znacsVSf2hJ1OQ/OfVMGN90pw/AtzF8s/Q==", + "dev": true, + "requires": { + "jest-diff": "^25.2.1", + "pretty-format": "^25.2.1" + }, + "dependencies": { + "@jest/types": { + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.5.0.tgz", + "integrity": "sha512-OXD0RgQ86Tu3MazKo8bnrkDRaDXXMGUqd+kTtLtK1Zb7CRzQcaSRPPPV37SvYTdevXEBVxe0HXylEjs8ibkmCw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^15.0.0", + "chalk": "^3.0.0" + } + }, + "@types/istanbul-reports": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz", + "integrity": "sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*", + "@types/istanbul-lib-report": "*" + } + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "diff-sequences": { + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-25.2.6.tgz", + "integrity": "sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jest-diff": { + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-25.5.0.tgz", + "integrity": "sha512-z1kygetuPiREYdNIumRpAHY6RXiGmp70YHptjdaxTWGmA085W3iCnXNx0DhflK3vwrKmrRWyY1wUpkPMVxMK7A==", + "dev": true, + "requires": { + "chalk": "^3.0.0", + "diff-sequences": "^25.2.6", + "jest-get-type": "^25.2.6", + "pretty-format": "^25.5.0" + } + }, + "jest-get-type": { + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz", + "integrity": "sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig==", + "dev": true + }, + "pretty-format": { + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.5.0.tgz", + "integrity": "sha512-kbo/kq2LQ/A/is0PQwsEHM7Ca6//bGPPvU6UnsdDRSKTWxT/ru/xb88v4BJf6a69H+uTytOEsTusT9ksd/1iWQ==", + "dev": true, + "requires": { + "@jest/types": "^25.5.0", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^16.12.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "@types/minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", @@ -1828,9 +2009,9 @@ "dev": true }, "@types/prettier": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.0.1.tgz", - "integrity": "sha512-boy4xPNEtiw6N3abRhBi/e7hNvy3Tt8E9ZRAQrwAGzoCGZS/1wjo9KY7JHhnfnEsG5wSjDbymCozUM9a3ea7OQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.1.0.tgz", + "integrity": "sha512-hiYA88aHiEIgDmeKlsyVsuQdcFn3Z2VuFd/Xm/HCnGnPD8UFU5BM128uzzRVVGEzKDKYUrRsRH9S2o+NUy/3IA==", "dev": true }, "@types/semver": { @@ -2049,9 +2230,9 @@ "dev": true }, "abab": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.3.tgz", - "integrity": "sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.4.tgz", + "integrity": "sha512-Eu9ELJWCz/c1e9gTiCY+FceWxcqzjYEbqMgtndnuSqZSUCOL73TWNK2mHfIj4Cw2E/ongOp+JISVNCmovt2KYQ==", "dev": true }, "abbrev": { @@ -2071,9 +2252,9 @@ } }, "acorn": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.3.1.tgz", - "integrity": "sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz", + "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==", "dev": true }, "acorn-globals": { @@ -2087,9 +2268,9 @@ } }, "acorn-walk": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.1.1.tgz", - "integrity": "sha512-wdlPY2tm/9XBr7QkKlq0WQVgiuGTX6YWPyRyBviSoScBuLfTVQhvwg6wJ369GJ/1nPfTLMfnrFIfjqVg6d+jQQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", "dev": true }, "after": { @@ -2099,9 +2280,9 @@ "dev": true }, "ajv": { - "version": "6.12.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz", - "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==", + "version": "6.12.4", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", + "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -2387,31 +2568,31 @@ "dev": true }, "aws4": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.0.tgz", - "integrity": "sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz", + "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==", "dev": true }, "axios": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", - "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.20.0.tgz", + "integrity": "sha512-ANA4rr2BDcmmAQLOKft2fufrtuvlqR+cXNNinUmvfeSNCOF98PZL+7M/v1zIdGo7OLjEA9J2gXJL+j4zGsl0bA==", "dev": true, "requires": { - "follow-redirects": "1.5.10" + "follow-redirects": "^1.10.0" } }, "babel-jest": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.0.1.tgz", - "integrity": "sha512-Z4GGmSNQ8pX3WS1O+6v3fo41YItJJZsVxG5gIQ+HuB/iuAQBJxMTHTwz292vuYws1LnHfwSRgoqI+nxdy/pcvw==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.3.0.tgz", + "integrity": "sha512-sxPnQGEyHAOPF8NcUsD0g7hDCnvLL2XyblRBcgrzTWBB/mAIpWow3n1bEL+VghnnZfreLhFSBsFluRoK2tRK4g==", "dev": true, "requires": { - "@jest/transform": "^26.0.1", - "@jest/types": "^26.0.1", + "@jest/transform": "^26.3.0", + "@jest/types": "^26.3.0", "@types/babel__core": "^7.1.7", "babel-plugin-istanbul": "^6.0.0", - "babel-preset-jest": "^26.0.0", + "babel-preset-jest": "^26.3.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", "slash": "^3.0.0" @@ -2465,9 +2646,9 @@ "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -2498,25 +2679,27 @@ } }, "babel-plugin-jest-hoist": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.0.0.tgz", - "integrity": "sha512-+AuoehOrjt9irZL7DOt2+4ZaTM6dlu1s5TTS46JBa0/qem4dy7VNW3tMb96qeEqcIh20LD73TVNtmVEeymTG7w==", + "version": "26.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.2.0.tgz", + "integrity": "sha512-B/hVMRv8Nh1sQ1a3EY8I0n4Y1Wty3NrR5ebOyVT302op+DOAau+xNEImGMsUWOC3++ZlMooCytKz+NgN8aKGbA==", "dev": true, "requires": { "@babel/template": "^7.3.3", "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", "@types/babel__traverse": "^7.0.6" } }, "babel-preset-current-node-syntax": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-0.1.2.tgz", - "integrity": "sha512-u/8cS+dEiK1SFILbOC8/rUI3ml9lboKuuMvZ/4aQnQmhecQAgPw5ew066C1ObnEAUmlx7dv/s2z52psWEtLNiw==", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-0.1.3.tgz", + "integrity": "sha512-uyexu1sVwcdFnyq9o8UQYsXwXflIh8LvrF5+cKrYam93ned1CStffB3+BEcsxGSgagoA3GEyjDqO4a/58hyPYQ==", "dev": true, "requires": { "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-bigint": "^7.8.3", "@babel/plugin-syntax-class-properties": "^7.8.3", + "@babel/plugin-syntax-import-meta": "^7.8.3", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", @@ -2527,13 +2710,13 @@ } }, "babel-preset-jest": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-26.0.0.tgz", - "integrity": "sha512-9ce+DatAa31DpR4Uir8g4Ahxs5K4W4L8refzt+qHWQANb6LhGcAEfIFgLUwk67oya2cCUd6t4eUMtO/z64ocNw==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-26.3.0.tgz", + "integrity": "sha512-5WPdf7nyYi2/eRxCbVrE1kKCWxgWY4RsPEbdJWFm7QsesFGqjdkyLeu1zRkwM1cxK6EPIlNd6d2AxLk7J+t4pw==", "dev": true, "requires": { - "babel-plugin-jest-hoist": "^26.0.0", - "babel-preset-current-node-syntax": "^0.1.2" + "babel-plugin-jest-hoist": "^26.2.0", + "babel-preset-current-node-syntax": "^0.1.3" } }, "backo2": { @@ -2968,6 +3151,12 @@ "unset-value": "^1.0.0" } }, + "call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", + "dev": true + }, "callsite": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", @@ -3659,6 +3848,12 @@ "minimalistic-assert": "^1.0.0" } }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, "detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -3678,9 +3873,9 @@ "dev": true }, "diff-sequences": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.0.0.tgz", - "integrity": "sha512-JC/eHYEC3aSS0vZGjuoc4vHA0yAQTzhQQldXMeMF+JlxLGJlCO38Gma82NV9gk1jGFz8mDzUMeaKXvjRRdJ2dg==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.3.0.tgz", + "integrity": "sha512-5j5vdRcw3CNctePNYN0Wy2e/JbWT6cAYnXv5OuqPhDpyCGc0uLu2TK0zOCJWNB9kOIfYMSpIulRaDgIi4HJ6Ig==", "dev": true }, "diffie-hellman": { @@ -3794,6 +3989,12 @@ } } }, + "emittery": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.7.1.tgz", + "integrity": "sha512-d34LN4L6h18Bzz9xpoku2nPwKxCPlPMr3EEKTkoEBi+1/+b0lcRkRJ1UVyyZaKNeqGR3swcGl6s390DNO4YVgQ==", + "dev": true + }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -4029,9 +4230,9 @@ "dev": true }, "escodegen": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.2.tgz", - "integrity": "sha512-InuOIiKk8wwuOFg6x9BQXbzjrQhtyXh46K9bqVTPzSo2FnyMBaYGBMC6PhQy7yxxil9vIedFBweQBMK74/7o8A==", + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", "dev": true, "requires": { "esprima": "^4.0.1", @@ -4094,9 +4295,9 @@ "dev": true }, "eventemitter3": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz", - "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "dev": true }, "events": { @@ -4177,17 +4378,26 @@ } } }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, "expect": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-26.0.1.tgz", - "integrity": "sha512-QcCy4nygHeqmbw564YxNbHTJlXh47dVID2BUP52cZFpLU9zHViMFK6h07cC1wf7GYCTIigTdAXhVua8Yl1FkKg==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/expect/-/expect-26.4.2.tgz", + "integrity": "sha512-IlJ3X52Z0lDHm7gjEp+m76uX46ldH5VpqmU0006vqDju/285twh7zaWMRhs67VpQhBwjjMchk+p5aA0VkERCAA==", "dev": true, "requires": { - "@jest/types": "^26.0.1", + "@jest/types": "^26.3.0", "ansi-styles": "^4.0.0", - "jest-get-type": "^26.0.0", - "jest-matcher-utils": "^26.0.1", - "jest-message-util": "^26.0.1", + "jest-get-type": "^26.3.0", + "jest-matcher-utils": "^26.4.2", + "jest-message-util": "^26.3.0", "jest-regex-util": "^26.0.0" }, "dependencies": { @@ -4322,6 +4532,20 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, + "fast-glob": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", + "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", + "dev": true, + "requires": { + "@mrmlnc/readdir-enhanced": "^2.2.1", + "@nodelib/fs.stat": "^1.1.2", + "glob-parent": "^3.1.0", + "is-glob": "^4.0.0", + "merge2": "^1.2.3", + "micromatch": "^3.1.10" + } + }, "fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -4526,24 +4750,10 @@ } }, "follow-redirects": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", - "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", - "dev": true, - "requires": { - "debug": "=3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", + "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==", + "dev": true }, "for-in": { "version": "1.0.2", @@ -4718,7 +4928,6 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, - "optional": true, "requires": { "is-glob": "^3.1.0", "path-dirname": "^1.0.0" @@ -4729,13 +4938,53 @@ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "dev": true, - "optional": true, "requires": { "is-extglob": "^2.1.0" } } } }, + "glob-to-regexp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", + "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", + "dev": true + }, + "global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dev": true, + "requires": { + "global-prefix": "^3.0.0" + }, + "dependencies": { + "global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dev": true, + "requires": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + } + } + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -4870,12 +5119,12 @@ "dev": true }, "har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "dev": true, "requires": { - "ajv": "^6.5.5", + "ajv": "^6.12.3", "har-schema": "^2.0.0" } }, @@ -5012,6 +5261,15 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, "hooker": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/hooker/-/hooker-0.2.3.tgz", @@ -5168,6 +5426,18 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "dev": true + }, "invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", @@ -5292,9 +5562,9 @@ } }, "is-docker": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.0.0.tgz", - "integrity": "sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.1.1.tgz", + "integrity": "sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==", "dev": true, "optional": true }, @@ -5363,6 +5633,12 @@ } } }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", @@ -5379,9 +5655,9 @@ "dev": true }, "is-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz", - "integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", "dev": true, "requires": { "has-symbols": "^1.0.1" @@ -5517,9 +5793,9 @@ } }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -5587,21 +5863,31 @@ "iterate-iterator": "^1.0.1" } }, + "jasmine": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.6.1.tgz", + "integrity": "sha512-Jqp8P6ZWkTVFGmJwBK46p+kJNrZCdqkQ4GL+PGuBXZwK1fM4ST9BizkYgIwCFqYYqnTizAy6+XG2Ej5dFrej9Q==", + "dev": true, + "requires": { + "fast-glob": "^2.2.6", + "jasmine-core": "~3.6.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==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.6.0.tgz", + "integrity": "sha512-8uQYa7zJN8hq9z+g8z1bqCfdC8eoDAeVnM5sfqs7KHv9/ifoJ500m018fpFc7RDaO6SWCLCXwo/wPSNcdYTgcw==", "dev": true }, "jest": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-26.0.1.tgz", - "integrity": "sha512-29Q54kn5Bm7ZGKIuH2JRmnKl85YRigp0o0asTc6Sb6l2ch1DCXIeZTLLFy9ultJvhkTqbswF5DEx4+RlkmCxWg==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/jest/-/jest-26.4.2.tgz", + "integrity": "sha512-LLCjPrUh98Ik8CzW8LLVnSCfLaiY+wbK53U7VxnFSX7Q+kWC4noVeDvGWIFw0Amfq1lq2VfGm7YHWSLBV62MJw==", "dev": true, "requires": { - "@jest/core": "^26.0.1", + "@jest/core": "^26.4.2", "import-local": "^3.0.2", - "jest-cli": "^26.0.1" + "jest-cli": "^26.4.2" }, "dependencies": { "ansi-styles": { @@ -5646,30 +5932,30 @@ "dev": true }, "jest-cli": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-26.0.1.tgz", - "integrity": "sha512-pFLfSOBcbG9iOZWaMK4Een+tTxi/Wcm34geqZEqrst9cZDkTQ1LZ2CnBrTlHWuYAiTMFr0EQeK52ScyFU8wK+w==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-26.4.2.tgz", + "integrity": "sha512-zb+lGd/SfrPvoRSC/0LWdaWCnscXc1mGYW//NP4/tmBvRPT3VntZ2jtKUONsRi59zc5JqmsSajA9ewJKFYp8Cw==", "dev": true, "requires": { - "@jest/core": "^26.0.1", - "@jest/test-result": "^26.0.1", - "@jest/types": "^26.0.1", + "@jest/core": "^26.4.2", + "@jest/test-result": "^26.3.0", + "@jest/types": "^26.3.0", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.4", "import-local": "^3.0.2", "is-ci": "^2.0.0", - "jest-config": "^26.0.1", - "jest-util": "^26.0.1", - "jest-validate": "^26.0.1", + "jest-config": "^26.4.2", + "jest-util": "^26.3.0", + "jest-validate": "^26.4.2", "prompts": "^2.0.1", "yargs": "^15.3.1" } }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -5678,12 +5964,12 @@ } }, "jest-changed-files": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-26.0.1.tgz", - "integrity": "sha512-q8LP9Sint17HaE2LjxQXL+oYWW/WeeXMPE2+Op9X3mY8IEGFVc14xRxFjUuXUbcPAlDLhtWdIEt59GdQbn76Hw==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-26.3.0.tgz", + "integrity": "sha512-1C4R4nijgPltX6fugKxM4oQ18zimS7LqQ+zTTY8lMCMFPrxqBFb7KJH0Z2fRQJvw2Slbaipsqq7s1mgX5Iot+g==", "dev": true, "requires": { - "@jest/types": "^26.0.1", + "@jest/types": "^26.3.0", "execa": "^4.0.0", "throat": "^5.0.0" }, @@ -5700,9 +5986,9 @@ } }, "execa": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.2.tgz", - "integrity": "sha512-QI2zLa6CjGWdiQsmSkZoGtDx2N+cQIGb3yNolGTdjSQzydzLgYYf8LRuagp7S7fPimjcrzUDSUFd/MgzELMi4Q==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.3.tgz", + "integrity": "sha512-WFDXGHckXPWZX19t1kCsXzOpqX9LWYNqn4C+HqZlk/V0imTkzJZqf87ZBhvpHaftERYknpk0fjSylnXVlVgI0A==", "dev": true, "requires": { "cross-spawn": "^7.0.0", @@ -5717,9 +6003,9 @@ } }, "get-stream": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", - "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dev": true, "requires": { "pump": "^3.0.0" @@ -5773,29 +6059,29 @@ } }, "jest-config": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-26.0.1.tgz", - "integrity": "sha512-9mWKx2L1LFgOXlDsC4YSeavnblN6A4CPfXFiobq+YYLaBMymA/SczN7xYTSmLaEYHZOcB98UdoN4m5uNt6tztg==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-26.4.2.tgz", + "integrity": "sha512-QBf7YGLuToiM8PmTnJEdRxyYy3mHWLh24LJZKVdXZ2PNdizSe1B/E8bVm+HYcjbEzGuVXDv/di+EzdO/6Gq80A==", "dev": true, "requires": { "@babel/core": "^7.1.0", - "@jest/test-sequencer": "^26.0.1", - "@jest/types": "^26.0.1", - "babel-jest": "^26.0.1", + "@jest/test-sequencer": "^26.4.2", + "@jest/types": "^26.3.0", + "babel-jest": "^26.3.0", "chalk": "^4.0.0", "deepmerge": "^4.2.2", "glob": "^7.1.1", "graceful-fs": "^4.2.4", - "jest-environment-jsdom": "^26.0.1", - "jest-environment-node": "^26.0.1", - "jest-get-type": "^26.0.0", - "jest-jasmine2": "^26.0.1", + "jest-environment-jsdom": "^26.3.0", + "jest-environment-node": "^26.3.0", + "jest-get-type": "^26.3.0", + "jest-jasmine2": "^26.4.2", "jest-regex-util": "^26.0.0", - "jest-resolve": "^26.0.1", - "jest-util": "^26.0.1", - "jest-validate": "^26.0.1", + "jest-resolve": "^26.4.0", + "jest-util": "^26.3.0", + "jest-validate": "^26.4.2", "micromatch": "^4.0.2", - "pretty-format": "^26.0.1" + "pretty-format": "^26.4.2" }, "dependencies": { "ansi-styles": { @@ -5874,9 +6160,9 @@ } }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -5894,15 +6180,15 @@ } }, "jest-diff": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.0.1.tgz", - "integrity": "sha512-odTcHyl5X+U+QsczJmOjWw5tPvww+y9Yim5xzqxVl/R1j4z71+fHW4g8qu1ugMmKdFdxw+AtQgs5mupPnzcIBQ==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.4.2.tgz", + "integrity": "sha512-6T1XQY8U28WH0Z5rGpQ+VqZSZz8EN8rZcBtfvXaOkbwxIEeRre6qnuZQlbY1AJ4MKDxQF8EkrCvK+hL/VkyYLQ==", "dev": true, "requires": { "chalk": "^4.0.0", - "diff-sequences": "^26.0.0", - "jest-get-type": "^26.0.0", - "pretty-format": "^26.0.1" + "diff-sequences": "^26.3.0", + "jest-get-type": "^26.3.0", + "pretty-format": "^26.4.2" }, "dependencies": { "ansi-styles": { @@ -5947,9 +6233,9 @@ "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -5967,16 +6253,16 @@ } }, "jest-each": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-26.0.1.tgz", - "integrity": "sha512-OTgJlwXCAR8NIWaXFL5DBbeS4QIYPuNASkzSwMCJO+ywo9BEa6TqkaSWsfR7VdbMLdgYJqSfQcIyjJCNwl5n4Q==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-26.4.2.tgz", + "integrity": "sha512-p15rt8r8cUcRY0Mvo1fpkOGYm7iI8S6ySxgIdfh3oOIv+gHwrHTy5VWCGOecWUhDsit4Nz8avJWdT07WLpbwDA==", "dev": true, "requires": { - "@jest/types": "^26.0.1", + "@jest/types": "^26.3.0", "chalk": "^4.0.0", - "jest-get-type": "^26.0.0", - "jest-util": "^26.0.1", - "pretty-format": "^26.0.1" + "jest-get-type": "^26.3.0", + "jest-util": "^26.3.0", + "pretty-format": "^26.4.2" }, "dependencies": { "ansi-styles": { @@ -6021,9 +6307,9 @@ "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -6032,57 +6318,60 @@ } }, "jest-environment-jsdom": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-26.0.1.tgz", - "integrity": "sha512-u88NJa3aptz2Xix2pFhihRBAatwZHWwSiRLBDBQE1cdJvDjPvv7ZGA0NQBxWwDDn7D0g1uHqxM8aGgfA9Bx49g==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-26.3.0.tgz", + "integrity": "sha512-zra8He2btIMJkAzvLaiZ9QwEPGEetbxqmjEBQwhH3CA+Hhhu0jSiEJxnJMbX28TGUvPLxBt/zyaTLrOPF4yMJA==", "dev": true, "requires": { - "@jest/environment": "^26.0.1", - "@jest/fake-timers": "^26.0.1", - "@jest/types": "^26.0.1", - "jest-mock": "^26.0.1", - "jest-util": "^26.0.1", + "@jest/environment": "^26.3.0", + "@jest/fake-timers": "^26.3.0", + "@jest/types": "^26.3.0", + "@types/node": "*", + "jest-mock": "^26.3.0", + "jest-util": "^26.3.0", "jsdom": "^16.2.2" } }, "jest-environment-node": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-26.0.1.tgz", - "integrity": "sha512-4FRBWcSn5yVo0KtNav7+5NH5Z/tEgDLp7VRQVS5tCouWORxj+nI+1tOLutM07Zb2Qi7ja+HEDoOUkjBSWZg/IQ==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-26.3.0.tgz", + "integrity": "sha512-c9BvYoo+FGcMj5FunbBgtBnbR5qk3uky8PKyRVpSfe2/8+LrNQMiXX53z6q2kY+j15SkjQCOSL/6LHnCPLVHNw==", "dev": true, "requires": { - "@jest/environment": "^26.0.1", - "@jest/fake-timers": "^26.0.1", - "@jest/types": "^26.0.1", - "jest-mock": "^26.0.1", - "jest-util": "^26.0.1" + "@jest/environment": "^26.3.0", + "@jest/fake-timers": "^26.3.0", + "@jest/types": "^26.3.0", + "@types/node": "*", + "jest-mock": "^26.3.0", + "jest-util": "^26.3.0" } }, "jest-get-type": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.0.0.tgz", - "integrity": "sha512-zRc1OAPnnws1EVfykXOj19zo2EMw5Hi6HLbFCSjpuJiXtOWAYIjNsHVSbpQ8bDX7L5BGYGI8m+HmKdjHYFF0kg==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.3.0.tgz", + "integrity": "sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==", "dev": true }, "jest-haste-map": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.0.1.tgz", - "integrity": "sha512-J9kBl/EdjmDsvyv7CiyKY5+DsTvVOScenprz/fGqfLg/pm1gdjbwwQ98nW0t+OIt+f+5nAVaElvn/6wP5KO7KA==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.3.0.tgz", + "integrity": "sha512-DHWBpTJgJhLLGwE5Z1ZaqLTYqeODQIZpby0zMBsCU9iRFHYyhklYqP4EiG73j5dkbaAdSZhgB938mL51Q5LeZA==", "dev": true, "requires": { - "@jest/types": "^26.0.1", + "@jest/types": "^26.3.0", "@types/graceful-fs": "^4.1.2", + "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "fsevents": "^2.1.2", "graceful-fs": "^4.2.4", - "jest-serializer": "^26.0.0", - "jest-util": "^26.0.1", - "jest-worker": "^26.0.0", + "jest-regex-util": "^26.0.0", + "jest-serializer": "^26.3.0", + "jest-util": "^26.3.0", + "jest-worker": "^26.3.0", "micromatch": "^4.0.2", "sane": "^4.0.3", - "walker": "^1.0.7", - "which": "^2.0.2" + "walker": "^1.0.7" }, "dependencies": { "anymatch": { @@ -6144,40 +6433,32 @@ "requires": { "is-number": "^7.0.0" } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } } } }, "jest-jasmine2": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-26.0.1.tgz", - "integrity": "sha512-ILaRyiWxiXOJ+RWTKupzQWwnPaeXPIoLS5uW41h18varJzd9/7I0QJGqg69fhTT1ev9JpSSo9QtalriUN0oqOg==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-26.4.2.tgz", + "integrity": "sha512-z7H4EpCldHN1J8fNgsja58QftxBSL+JcwZmaXIvV9WKIM+x49F4GLHu/+BQh2kzRKHAgaN/E82od+8rTOBPyPA==", "dev": true, "requires": { "@babel/traverse": "^7.1.0", - "@jest/environment": "^26.0.1", - "@jest/source-map": "^26.0.0", - "@jest/test-result": "^26.0.1", - "@jest/types": "^26.0.1", + "@jest/environment": "^26.3.0", + "@jest/source-map": "^26.3.0", + "@jest/test-result": "^26.3.0", + "@jest/types": "^26.3.0", + "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", - "expect": "^26.0.1", + "expect": "^26.4.2", "is-generator-fn": "^2.0.0", - "jest-each": "^26.0.1", - "jest-matcher-utils": "^26.0.1", - "jest-message-util": "^26.0.1", - "jest-runtime": "^26.0.1", - "jest-snapshot": "^26.0.1", - "jest-util": "^26.0.1", - "pretty-format": "^26.0.1", + "jest-each": "^26.4.2", + "jest-matcher-utils": "^26.4.2", + "jest-message-util": "^26.3.0", + "jest-runtime": "^26.4.2", + "jest-snapshot": "^26.4.2", + "jest-util": "^26.3.0", + "pretty-format": "^26.4.2", "throat": "^5.0.0" }, "dependencies": { @@ -6223,9 +6504,9 @@ "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -6234,25 +6515,25 @@ } }, "jest-leak-detector": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-26.0.1.tgz", - "integrity": "sha512-93FR8tJhaYIWrWsbmVN1pQ9ZNlbgRpfvrnw5LmgLRX0ckOJ8ut/I35CL7awi2ecq6Ca4lL59bEK9hr7nqoHWPA==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-26.4.2.tgz", + "integrity": "sha512-akzGcxwxtE+9ZJZRW+M2o+nTNnmQZxrHJxX/HjgDaU5+PLmY1qnQPnMjgADPGCRPhB+Yawe1iij0REe+k/aHoA==", "dev": true, "requires": { - "jest-get-type": "^26.0.0", - "pretty-format": "^26.0.1" + "jest-get-type": "^26.3.0", + "pretty-format": "^26.4.2" } }, "jest-matcher-utils": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.0.1.tgz", - "integrity": "sha512-PUMlsLth0Azen8Q2WFTwnSkGh2JZ8FYuwijC8NR47vXKpsrKmA1wWvgcj1CquuVfcYiDEdj985u5Wmg7COEARw==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.4.2.tgz", + "integrity": "sha512-KcbNqWfWUG24R7tu9WcAOKKdiXiXCbMvQYT6iodZ9k1f7065k0keUOW6XpJMMvah+hTfqkhJhRXmA3r3zMAg0Q==", "dev": true, "requires": { "chalk": "^4.0.0", - "jest-diff": "^26.0.1", - "jest-get-type": "^26.0.0", - "pretty-format": "^26.0.1" + "jest-diff": "^26.4.2", + "jest-get-type": "^26.3.0", + "pretty-format": "^26.4.2" }, "dependencies": { "ansi-styles": { @@ -6297,9 +6578,9 @@ "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -6308,13 +6589,13 @@ } }, "jest-message-util": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.0.1.tgz", - "integrity": "sha512-CbK8uQREZ8umUfo8+zgIfEt+W7HAHjQCoRaNs4WxKGhAYBGwEyvxuK81FXa7VeB9pwDEXeeKOB2qcsNVCAvB7Q==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.3.0.tgz", + "integrity": "sha512-xIavRYqr4/otGOiLxLZGj3ieMmjcNE73Ui+LdSW/Y790j5acqCsAdDiLIbzHCZMpN07JOENRWX5DcU+OQ+TjTA==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@jest/types": "^26.0.1", + "@jest/types": "^26.3.0", "@types/stack-utils": "^1.0.1", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", @@ -6405,9 +6686,9 @@ "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -6425,18 +6706,19 @@ } }, "jest-mock": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.0.1.tgz", - "integrity": "sha512-MpYTBqycuPYSY6xKJognV7Ja46/TeRbAZept987Zp+tuJvMN0YBWyyhG9mXyYQaU3SBI0TUlSaO5L3p49agw7Q==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.3.0.tgz", + "integrity": "sha512-PeaRrg8Dc6mnS35gOo/CbZovoDPKAeB1FICZiuagAgGvbWdNNyjQjkOaGUa/3N3JtpQ/Mh9P4A2D4Fv51NnP8Q==", "dev": true, "requires": { - "@jest/types": "^26.0.1" + "@jest/types": "^26.3.0", + "@types/node": "*" } }, "jest-pnp-resolver": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz", - "integrity": "sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", + "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", "dev": true }, "jest-regex-util": { @@ -6446,16 +6728,16 @@ "dev": true }, "jest-resolve": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.0.1.tgz", - "integrity": "sha512-6jWxk0IKZkPIVTvq6s72RH735P8f9eCJW3IM5CX/SJFeKq1p2cZx0U49wf/SdMlhaB/anann5J2nCJj6HrbezQ==", + "version": "26.4.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.4.0.tgz", + "integrity": "sha512-bn/JoZTEXRSlEx3+SfgZcJAVuTMOksYq9xe9O6s4Ekg84aKBObEaVXKOEilULRqviSLAYJldnoWV9c07kwtiCg==", "dev": true, "requires": { - "@jest/types": "^26.0.1", + "@jest/types": "^26.3.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", - "jest-pnp-resolver": "^1.2.1", - "jest-util": "^26.0.1", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^26.3.0", "read-pkg-up": "^7.0.1", "resolve": "^1.17.0", "slash": "^3.0.0" @@ -6546,14 +6828,14 @@ "dev": true }, "parse-json": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz", - "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", + "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1", + "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, @@ -6601,9 +6883,9 @@ "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -6612,39 +6894,40 @@ } }, "jest-resolve-dependencies": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-26.0.1.tgz", - "integrity": "sha512-9d5/RS/ft0vB/qy7jct/qAhzJsr6fRQJyGAFigK3XD4hf9kIbEH5gks4t4Z7kyMRhowU6HWm/o8ILqhaHdSqLw==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-26.4.2.tgz", + "integrity": "sha512-ADHaOwqEcVc71uTfySzSowA/RdxUpCxhxa2FNLiin9vWLB1uLPad3we+JSSROq5+SrL9iYPdZZF8bdKM7XABTQ==", "dev": true, "requires": { - "@jest/types": "^26.0.1", + "@jest/types": "^26.3.0", "jest-regex-util": "^26.0.0", - "jest-snapshot": "^26.0.1" + "jest-snapshot": "^26.4.2" } }, "jest-runner": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-26.0.1.tgz", - "integrity": "sha512-CApm0g81b49Znm4cZekYQK67zY7kkB4umOlI2Dx5CwKAzdgw75EN+ozBHRvxBzwo1ZLYZ07TFxkaPm+1t4d8jA==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-26.4.2.tgz", + "integrity": "sha512-FgjDHeVknDjw1gRAYaoUoShe1K3XUuFMkIaXbdhEys+1O4bEJS8Avmn4lBwoMfL8O5oFTdWYKcf3tEJyyYyk8g==", "dev": true, "requires": { - "@jest/console": "^26.0.1", - "@jest/environment": "^26.0.1", - "@jest/test-result": "^26.0.1", - "@jest/types": "^26.0.1", + "@jest/console": "^26.3.0", + "@jest/environment": "^26.3.0", + "@jest/test-result": "^26.3.0", + "@jest/types": "^26.3.0", + "@types/node": "*", "chalk": "^4.0.0", + "emittery": "^0.7.1", "exit": "^0.1.2", "graceful-fs": "^4.2.4", - "jest-config": "^26.0.1", + "jest-config": "^26.4.2", "jest-docblock": "^26.0.0", - "jest-haste-map": "^26.0.1", - "jest-jasmine2": "^26.0.1", - "jest-leak-detector": "^26.0.1", - "jest-message-util": "^26.0.1", - "jest-resolve": "^26.0.1", - "jest-runtime": "^26.0.1", - "jest-util": "^26.0.1", - "jest-worker": "^26.0.0", + "jest-haste-map": "^26.3.0", + "jest-leak-detector": "^26.4.2", + "jest-message-util": "^26.3.0", + "jest-resolve": "^26.4.0", + "jest-runtime": "^26.4.2", + "jest-util": "^26.3.0", + "jest-worker": "^26.3.0", "source-map-support": "^0.5.6", "throat": "^5.0.0" }, @@ -6691,9 +6974,9 @@ "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -6702,34 +6985,34 @@ } }, "jest-runtime": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-26.0.1.tgz", - "integrity": "sha512-Ci2QhYFmANg5qaXWf78T2Pfo6GtmIBn2rRaLnklRyEucmPccmCKvS9JPljcmtVamsdMmkyNkVFb9pBTD6si9Lw==", - "dev": true, - "requires": { - "@jest/console": "^26.0.1", - "@jest/environment": "^26.0.1", - "@jest/fake-timers": "^26.0.1", - "@jest/globals": "^26.0.1", - "@jest/source-map": "^26.0.0", - "@jest/test-result": "^26.0.1", - "@jest/transform": "^26.0.1", - "@jest/types": "^26.0.1", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-26.4.2.tgz", + "integrity": "sha512-4Pe7Uk5a80FnbHwSOk7ojNCJvz3Ks2CNQWT5Z7MJo4tX0jb3V/LThKvD9tKPNVNyeMH98J/nzGlcwc00R2dSHQ==", + "dev": true, + "requires": { + "@jest/console": "^26.3.0", + "@jest/environment": "^26.3.0", + "@jest/fake-timers": "^26.3.0", + "@jest/globals": "^26.4.2", + "@jest/source-map": "^26.3.0", + "@jest/test-result": "^26.3.0", + "@jest/transform": "^26.3.0", + "@jest/types": "^26.3.0", "@types/yargs": "^15.0.0", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", "glob": "^7.1.3", "graceful-fs": "^4.2.4", - "jest-config": "^26.0.1", - "jest-haste-map": "^26.0.1", - "jest-message-util": "^26.0.1", - "jest-mock": "^26.0.1", + "jest-config": "^26.4.2", + "jest-haste-map": "^26.3.0", + "jest-message-util": "^26.3.0", + "jest-mock": "^26.3.0", "jest-regex-util": "^26.0.0", - "jest-resolve": "^26.0.1", - "jest-snapshot": "^26.0.1", - "jest-util": "^26.0.1", - "jest-validate": "^26.0.1", + "jest-resolve": "^26.4.0", + "jest-snapshot": "^26.4.2", + "jest-util": "^26.3.0", + "jest-validate": "^26.4.2", "slash": "^3.0.0", "strip-bom": "^4.0.0", "yargs": "^15.3.1" @@ -6789,9 +7072,9 @@ "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -6800,34 +7083,35 @@ } }, "jest-serializer": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.0.0.tgz", - "integrity": "sha512-sQGXLdEGWFAE4wIJ2ZaIDb+ikETlUirEOBsLXdoBbeLhTHkZUJwgk3+M8eyFizhM6le43PDCCKPA1hzkSDo4cQ==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.3.0.tgz", + "integrity": "sha512-IDRBQBLPlKa4flg77fqg0n/pH87tcRKwe8zxOVTWISxGpPHYkRZ1dXKyh04JOja7gppc60+soKVZ791mruVdow==", "dev": true, "requires": { + "@types/node": "*", "graceful-fs": "^4.2.4" } }, "jest-snapshot": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-26.0.1.tgz", - "integrity": "sha512-jxd+cF7+LL+a80qh6TAnTLUZHyQoWwEHSUFJjkw35u3Gx+BZUNuXhYvDqHXr62UQPnWo2P6fvQlLjsU93UKyxA==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-26.4.2.tgz", + "integrity": "sha512-N6Uub8FccKlf5SBFnL2Ri/xofbaA68Cc3MGjP/NuwgnsvWh+9hLIR/DhrxbSiKXMY9vUW5dI6EW1eHaDHqe9sg==", "dev": true, "requires": { "@babel/types": "^7.0.0", - "@jest/types": "^26.0.1", + "@jest/types": "^26.3.0", "@types/prettier": "^2.0.0", "chalk": "^4.0.0", - "expect": "^26.0.1", + "expect": "^26.4.2", "graceful-fs": "^4.2.4", - "jest-diff": "^26.0.1", - "jest-get-type": "^26.0.0", - "jest-matcher-utils": "^26.0.1", - "jest-message-util": "^26.0.1", - "jest-resolve": "^26.0.1", - "make-dir": "^3.0.0", + "jest-diff": "^26.4.2", + "jest-get-type": "^26.3.0", + "jest-haste-map": "^26.3.0", + "jest-matcher-utils": "^26.4.2", + "jest-message-util": "^26.3.0", + "jest-resolve": "^26.4.0", "natural-compare": "^1.4.0", - "pretty-format": "^26.0.1", + "pretty-format": "^26.4.2", "semver": "^7.3.2" }, "dependencies": { @@ -6872,23 +7156,6 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, "semver": { "version": "7.3.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", @@ -6896,9 +7163,9 @@ "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -6907,16 +7174,17 @@ } }, "jest-util": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.0.1.tgz", - "integrity": "sha512-byQ3n7ad1BO/WyFkYvlWQHTsomB6GIewBh8tlGtusiylAlaxQ1UpS0XYH0ngOyhZuHVLN79Qvl6/pMiDMSSG1g==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.3.0.tgz", + "integrity": "sha512-4zpn6bwV0+AMFN0IYhH/wnzIQzRaYVrz1A8sYnRnj4UXDXbOVtWmlaZkO9mipFqZ13okIfN87aDoJWB7VH6hcw==", "dev": true, "requires": { - "@jest/types": "^26.0.1", + "@jest/types": "^26.3.0", + "@types/node": "*", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", "is-ci": "^2.0.0", - "make-dir": "^3.0.0" + "micromatch": "^4.0.2" }, "dependencies": { "ansi-styles": { @@ -6929,6 +7197,15 @@ "color-convert": "^2.0.1" } }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, "chalk": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", @@ -6954,44 +7231,69 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", "dev": true, "requires": { - "semver": "^6.0.0" + "braces": "^3.0.1", + "picomatch": "^2.0.5" } }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } } } }, "jest-validate": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-26.0.1.tgz", - "integrity": "sha512-u0xRc+rbmov/VqXnX3DlkxD74rHI/CfS5xaV2VpeaVySjbb1JioNVOyly5b56q2l9ZKe7bVG5qWmjfctkQb0bA==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-26.4.2.tgz", + "integrity": "sha512-blft+xDX7XXghfhY0mrsBCYhX365n8K5wNDC4XAcNKqqjEzsRUSXP44m6PL0QJEW2crxQFLLztVnJ4j7oPlQrQ==", "dev": true, "requires": { - "@jest/types": "^26.0.1", + "@jest/types": "^26.3.0", "camelcase": "^6.0.0", "chalk": "^4.0.0", - "jest-get-type": "^26.0.0", + "jest-get-type": "^26.3.0", "leven": "^3.1.0", - "pretty-format": "^26.0.1" + "pretty-format": "^26.4.2" }, "dependencies": { "ansi-styles": { @@ -7042,9 +7344,9 @@ "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -7053,16 +7355,17 @@ } }, "jest-watcher": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-26.0.1.tgz", - "integrity": "sha512-pdZPydsS8475f89kGswaNsN3rhP6lnC3/QDCppP7bg1L9JQz7oU9Mb/5xPETk1RHDCWeqmVC47M4K5RR7ejxFw==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-26.3.0.tgz", + "integrity": "sha512-XnLdKmyCGJ3VoF6G/p5ohbJ04q/vv5aH9ENI+i6BL0uu9WWB6Z7Z2lhQQk0d2AVZcRGp1yW+/TsoToMhBFPRdQ==", "dev": true, "requires": { - "@jest/test-result": "^26.0.1", - "@jest/types": "^26.0.1", + "@jest/test-result": "^26.3.0", + "@jest/types": "^26.3.0", + "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", - "jest-util": "^26.0.1", + "jest-util": "^26.3.0", "string-length": "^4.0.1" }, "dependencies": { @@ -7108,9 +7411,9 @@ "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -7119,11 +7422,12 @@ } }, "jest-worker": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.0.0.tgz", - "integrity": "sha512-pPaYa2+JnwmiZjK9x7p9BoZht+47ecFCDFA/CJxspHzeDvQcfVBLWzCiWyo+EGrSiQMWZtCFo9iSvMZnAAo8vw==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.3.0.tgz", + "integrity": "sha512-Vmpn2F6IASefL+DVBhPzI2J9/GJUsqzomdeN+P+dK8/jKxbh8R3BtFnx3FIta7wYlPU62cpJMJQo4kuOowcMnw==", "dev": true, "requires": { + "@types/node": "*", "merge-stream": "^2.0.0", "supports-color": "^7.0.0" }, @@ -7135,9 +7439,9 @@ "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -7168,9 +7472,9 @@ "dev": true }, "jsdom": { - "version": "16.2.2", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.2.2.tgz", - "integrity": "sha512-pDFQbcYtKBHxRaP55zGXCJWgFHkDAYbKcsXEK/3Icu9nKYZkutUXfLBwbD+09XDutkYSHcgfQLZ0qvpAAm9mvg==", + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.4.0.tgz", + "integrity": "sha512-lYMm3wYdgPhrl7pDcRmvzPhhrGVBeVhPIqeHjzeiHN3DFmD1RBpbExbi8vU7BJdH8VAZYovR8DMt0PNNDM7k8w==", "dev": true, "requires": { "abab": "^2.0.3", @@ -7193,7 +7497,7 @@ "tough-cookie": "^3.0.1", "w3c-hr-time": "^1.0.2", "w3c-xmlserializer": "^2.0.0", - "webidl-conversions": "^6.0.0", + "webidl-conversions": "^6.1.0", "whatwg-encoding": "^1.0.5", "whatwg-mimetype": "^2.3.0", "whatwg-url": "^8.0.0", @@ -7213,6 +7517,12 @@ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, + "json-parse-even-better-errors": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.0.tgz", + "integrity": "sha512-o3aP+RsWDJZayj1SbHNQAI8x0v3T3SKiGoZlNYfbUP1S3omJQ6i9CnqADqkSPaOAxwua4/1YWx5CM7oiChJt2Q==", + "dev": true + }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", @@ -7262,9 +7572,9 @@ } }, "karma": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/karma/-/karma-5.1.0.tgz", - "integrity": "sha512-I3aPbkuIbwuBo6wSog97P5WnnhCgUTsWTu/bEw1vZVQFbXmKO3PK+cfFhZioOgVtJAuQxoyauGNjnwXNHMCxbw==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/karma/-/karma-5.1.1.tgz", + "integrity": "sha512-xAlOr5PMqUbiKXSv5PCniHWV3aiwj6wIZ0gUVcwpTCPVQm/qH2WAMFWxtnpM6KJqhkRWrIpovR4Rb0rn8GtJzQ==", "dev": true, "requires": { "body-parser": "^1.19.0", @@ -7304,9 +7614,9 @@ } }, "binary-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", - "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", "dev": true }, "braces": { @@ -7319,9 +7629,9 @@ } }, "chokidar": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz", - "integrity": "sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", + "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", "dev": true, "requires": { "anymatch": "~3.1.1", @@ -7449,9 +7759,9 @@ } }, "karma-sourcemap-loader": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz", - "integrity": "sha1-kTIsd/jxPUb+0GKwQuEAnUxFBdg=", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.8.tgz", + "integrity": "sha512-zorxyAakYZuBcHRJE+vbrK2o2JXLFWK8VVjiT/6P+ltLBUGUvqTEkUiQ119MGdOrK7mrmxXHZF1/pfT6GgIZ6g==", "dev": true, "requires": { "graceful-fs": "^4.1.2" @@ -7765,12 +8075,64 @@ "dev": true }, "log-symbols": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", - "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz", + "integrity": "sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==", "dev": true, "requires": { - "chalk": "^2.4.2" + "chalk": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "log4js": { @@ -7942,6 +8304,12 @@ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -8084,28 +8452,28 @@ } }, "mocha": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.0.1.tgz", - "integrity": "sha512-vefaXfdYI8+Yo8nPZQQi0QO2o+5q9UIMX1jZ1XMmK3+4+CQjc7+B0hPdUeglXiTlr8IHMVRo63IhO9Mzt6fxOg==", + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-8.1.3.tgz", + "integrity": "sha512-ZbaYib4hT4PpF4bdSO2DohooKXIn4lDeiYqB+vTmCdr6l2woW0b6H3pf5x4sM5nwQMru9RvjjHYWVGltR50ZBw==", "dev": true, "requires": { "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", - "chokidar": "3.3.1", - "debug": "3.2.6", + "chokidar": "3.4.2", + "debug": "4.1.1", "diff": "4.0.2", - "escape-string-regexp": "1.0.5", - "find-up": "4.1.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", "glob": "7.1.6", "growl": "1.10.5", "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "3.0.0", + "js-yaml": "3.14.0", + "log-symbols": "4.0.0", "minimatch": "3.0.4", "ms": "2.1.2", "object.assign": "4.1.0", "promise.allsettled": "1.0.2", - "serialize-javascript": "3.0.0", + "serialize-javascript": "4.0.0", "strip-json-comments": "3.0.1", "supports-color": "7.1.0", "which": "2.0.2", @@ -8113,7 +8481,7 @@ "workerpool": "6.0.0", "yargs": "13.3.2", "yargs-parser": "13.1.2", - "yargs-unparser": "1.6.0" + "yargs-unparser": "1.6.1" }, "dependencies": { "ansi-colors": { @@ -8139,9 +8507,9 @@ } }, "binary-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", - "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", "dev": true }, "braces": { @@ -8160,9 +8528,9 @@ "dev": true }, "chokidar": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.1.tgz", - "integrity": "sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", + "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", "dev": true, "requires": { "anymatch": "~3.1.1", @@ -8172,7 +8540,7 @@ "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.3.0" + "readdirp": "~3.4.0" } }, "cliui": { @@ -8187,9 +8555,9 @@ } }, "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { "ms": "^2.1.1" @@ -8201,6 +8569,12 @@ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -8211,12 +8585,12 @@ } }, "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, "requires": { - "locate-path": "^5.0.0", + "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, @@ -8263,13 +8637,23 @@ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, + "js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "requires": { - "p-locate": "^4.1.0" + "p-locate": "^5.0.0" } }, "ms": { @@ -8279,21 +8663,21 @@ "dev": true }, "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", + "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==", "dev": true, "requires": { "p-try": "^2.0.0" } }, "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "requires": { - "p-limit": "^2.2.0" + "p-limit": "^3.0.2" } }, "p-try": { @@ -8309,12 +8693,12 @@ "dev": true }, "readdirp": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.3.0.tgz", - "integrity": "sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", + "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", "dev": true, "requires": { - "picomatch": "^2.0.7" + "picomatch": "^2.2.1" } }, "string-width": { @@ -8412,6 +8796,15 @@ "path-exists": "^3.0.0" } }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, "p-locate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", @@ -8602,17 +8995,17 @@ "dev": true }, "node-notifier": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-7.0.1.tgz", - "integrity": "sha512-VkzhierE7DBmQEElhTGJIoiZa1oqRijOtgOlsXg32KrJRXsPy0NXFBqWGW/wTswnJlDCs5viRYaqWguqzsKcmg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-8.0.0.tgz", + "integrity": "sha512-46z7DUmcjoYdaWyXouuFNNfUo6eFa94t23c53c+lG/9Cvauk4a98rAUp9672X5dxGdQmLpPzTxzu8f/OeEPaFA==", "dev": true, "optional": true, "requires": { "growly": "^1.3.0", - "is-wsl": "^2.1.1", - "semver": "^7.2.1", + "is-wsl": "^2.2.0", + "semver": "^7.3.2", "shellwords": "^0.1.1", - "uuid": "^7.0.3", + "uuid": "^8.3.0", "which": "^2.0.2" }, "dependencies": { @@ -8741,9 +9134,9 @@ } }, "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==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", "dev": true }, "object-keys": { @@ -8801,9 +9194,9 @@ } }, "onetime": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", - "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, "requires": { "mimic-fn": "^2.1.0" @@ -8905,6 +9298,12 @@ "error-ex": "^1.2.0" } }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, "parse5": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", @@ -8951,8 +9350,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true, - "optional": true + "dev": true }, "path-exists": { "version": "3.0.0", @@ -9140,12 +9538,12 @@ "dev": true }, "pretty-format": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.0.1.tgz", - "integrity": "sha512-SWxz6MbupT3ZSlL0Po4WF/KujhQaVehijR2blyRDCzk9e45EaYMVhMBn49fnRuHxtkSpXTes1GxNpVmH86Bxfw==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.4.2.tgz", + "integrity": "sha512-zK6Gd8zDsEiVydOCGLkoBoZuqv8VTiHyAbKznXe/gaph/DAeZOmit9yMfgIz5adIgAMMs5XfoYSwAX3jcCO1tA==", "dev": true, "requires": { - "@jest/types": "^26.0.1", + "@jest/types": "^26.3.0", "ansi-regex": "^5.0.0", "ansi-styles": "^4.0.0", "react-is": "^16.12.0" @@ -9596,21 +9994,29 @@ } }, "request-promise-core": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.3.tgz", - "integrity": "sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", + "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", "dev": true, "requires": { - "lodash": "^4.17.15" + "lodash": "^4.17.19" + }, + "dependencies": { + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + } } }, "request-promise-native": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.8.tgz", - "integrity": "sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz", + "integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==", "dev": true, "requires": { - "request-promise-core": "1.1.3", + "request-promise-core": "1.1.4", "stealthy-require": "^1.1.1", "tough-cookie": "^2.3.3" }, @@ -9663,6 +10069,29 @@ "resolve-from": "^5.0.0" } }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "dependencies": { + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + } + } + }, "resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", @@ -9804,10 +10233,13 @@ "dev": true }, "serialize-javascript": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.0.0.tgz", - "integrity": "sha512-skZcHYw2vEX4bw90nAr2iTTsz6x2SrHEnfxgKYmZlvJYBEZrvbKtobJWlQ20zczKb3bsHHXXTYt48zBA7ni9cw==", - "dev": true + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } }, "set-blocking": { "version": "2.0.0", @@ -10538,9 +10970,9 @@ "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -10808,72 +11240,42 @@ "dev": true }, "ts-jest": { - "version": "25.5.1", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-25.5.1.tgz", - "integrity": "sha512-kHEUlZMK8fn8vkxDjwbHlxXRB9dHYpyzqKIGDNxbzs+Rz+ssNDSDNusEK8Fk/sDd4xE6iKoQLfFkFVaskmTJyw==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.3.0.tgz", + "integrity": "sha512-Jq2uKfx6bPd9+JDpZNMBJMdMQUC3sJ08acISj8NXlVgR2d5OqslEHOR2KHMgwymu8h50+lKIm0m0xj/ioYdW2Q==", "dev": true, "requires": { + "@types/jest": "26.x", "bs-logger": "0.x", "buffer-from": "1.x", "fast-json-stable-stringify": "2.x", + "jest-util": "26.x", "json5": "2.x", "lodash.memoize": "4.x", "make-error": "1.x", - "micromatch": "4.x", - "mkdirp": "0.x", - "semver": "6.x", + "mkdirp": "1.x", + "semver": "7.x", "yargs-parser": "18.x" }, "dependencies": { - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true }, - "micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", - "dev": true, - "requires": { - "braces": "^3.0.1", - "picomatch": "^2.0.5" - } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true } } }, "ts-loader": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-7.0.5.tgz", - "integrity": "sha512-zXypEIT6k3oTc+OZNx/cqElrsbBtYqDknf48OZos0NQ3RTt045fBIU8RRSu+suObBzYB355aIPGOe/3kj9h7Ig==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-8.0.3.tgz", + "integrity": "sha512-wsqfnVdB7xQiqhqbz2ZPLGHLPZbHVV5Qn/MNFZkCFxRU1miDyxKORucDGxKtsQJ63Rfza0udiUxWF5nHY6bpdQ==", "dev": true, "requires": { "chalk": "^2.3.0", @@ -11171,9 +11573,9 @@ "optional": true }, "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.3.0.tgz", + "integrity": "sha512-Q9Q9RlMM08eWfdPPmDDrXd8Ny3R1sY/DaRDR2zTPPneJ6GYiLx3++fPiZobv49ovkYAnHl/P72Ie3HWXIRVVYA==", "dev": true, "requires": { "punycode": "^2.1.0" @@ -11239,16 +11641,22 @@ "dev": true }, "uuid": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", - "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.0.tgz", + "integrity": "sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ==", "dev": true, "optional": true }, + "v8-compile-cache": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", + "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==", + "dev": true + }, "v8-to-istanbul": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-4.1.4.tgz", - "integrity": "sha512-Rw6vJHj1mbdK8edjR7+zuJrpDtKIgNdAvTSAcpYfgMIw+u2dPDntD3dgN4XQFLU2/fvFQdzj+EeSGfd/jnY5fQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-5.0.1.tgz", + "integrity": "sha512-mbDNjuDajqYe3TXFk5qxcQy8L1msXNE37WTlLoqqpBfRsimbNcrlhQlDPntmECEcUvdC+AQ8CyMMf6EUx1r74Q==", "dev": true, "requires": { "@types/istanbul-lib-coverage": "^2.0.1", @@ -11502,6 +11910,219 @@ } } }, + "webpack-cli": { + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.12.tgz", + "integrity": "sha512-NVWBaz9k839ZH/sinurM+HcDvJOTXwSjYp1ku+5XKeOC03z8v5QitnK/x+lAxGXFyhdayoIf/GOpv85z3/xPag==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "cross-spawn": "^6.0.5", + "enhanced-resolve": "^4.1.1", + "findup-sync": "^3.0.0", + "global-modules": "^2.0.0", + "import-local": "^2.0.0", + "interpret": "^1.4.0", + "loader-utils": "^1.4.0", + "supports-color": "^6.1.0", + "v8-compile-cache": "^2.1.1", + "yargs": "^13.3.2" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "findup-sync": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz", + "integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + } + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, "webpack-dev-middleware": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz", @@ -11567,22 +12188,14 @@ "dev": true }, "whatwg-url": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.1.0.tgz", - "integrity": "sha512-vEIkwNi9Hqt4TV9RdnaBPNt+E2Sgmo3gePebCRgZ1R7g6d23+53zCTnuB0amKI4AXq6VM8jj2DUAa0S1vjJxkw==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.2.1.tgz", + "integrity": "sha512-ZmVCr6nfBeaMxEHALLEGy0LszYjpJqf6PVNQUQ1qd9Et+q7Jpygd4rGGDXgHjD8e99yLFseD69msHDM4YwPZ4A==", "dev": true, "requires": { "lodash.sortby": "^4.7.0", "tr46": "^2.0.2", - "webidl-conversions": "^5.0.0" - }, - "dependencies": { - "webidl-conversions": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", - "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", - "dev": true - } + "webidl-conversions": "^6.1.0" } }, "which": { @@ -11720,9 +12333,9 @@ } }, "ws": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.0.tgz", - "integrity": "sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz", + "integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==", "dev": true }, "xml-name-validator": { @@ -11762,9 +12375,9 @@ "dev": true }, "yargs": { - "version": "15.3.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz", - "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==", + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, "requires": { "cliui": "^6.0.0", @@ -11777,7 +12390,7 @@ "string-width": "^4.2.0", "which-module": "^2.0.0", "y18n": "^4.0.0", - "yargs-parser": "^18.1.1" + "yargs-parser": "^18.1.2" }, "dependencies": { "find-up": { @@ -11850,14 +12463,16 @@ } }, "yargs-unparser": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", - "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.1.tgz", + "integrity": "sha512-qZV14lK9MWsGCmcr7u5oXGH0dbGqZAIxTDrWXZDo5zUr6b6iUmelNKO6x6R1dQT24AH3LgRxJpr8meWy2unolA==", "dev": true, "requires": { + "camelcase": "^5.3.1", + "decamelize": "^1.2.0", "flat": "^4.1.0", - "lodash": "^4.17.15", - "yargs": "^13.3.0" + "is-plain-obj": "^1.1.0", + "yargs": "^14.2.3" }, "dependencies": { "ansi-regex": { @@ -11970,12 +12585,13 @@ } }, "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-14.2.3.tgz", + "integrity": "sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg==", "dev": true, "requires": { "cliui": "^5.0.0", + "decamelize": "^1.2.0", "find-up": "^3.0.0", "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", @@ -11984,13 +12600,13 @@ "string-width": "^3.0.0", "which-module": "^2.0.0", "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" + "yargs-parser": "^15.0.1" } }, "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "version": "15.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-15.0.1.tgz", + "integrity": "sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw==", "dev": true, "requires": { "camelcase": "^5.0.0", diff --git a/e2e/package.json b/e2e/package.json index 58e67c5d8c..f926374c63 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -10,32 +10,34 @@ "@babel/preset-env": "~7.8.3", "@types/node": "^10.12.18", "@types/semver": "~6.2.0", - "ajv": "^6.12.2", - "axios": "^0.19.2", + "ajv": "~6.12.4", + "axios": "~0.20.0", "chai": "~4.2.0", "chai-as-promised": "~7.1.1", "cross-env": "~5.2.0", "grunt": "~1.0.4", - "jasmine-core": "~3.5.0", - "jest": "^26.0.1", - "karma": "^5.0.4", + "jasmine": "~3.6.1", + "jasmine-core": "~3.6.0", + "jest": "~26.4.2", + "karma": "~5.1.1", "karma-chai": "~0.1.0", "karma-chrome-launcher": "~3.1.0", "karma-jasmine": "~2.0.1", - "karma-mocha": "^2.0.1", - "karma-sourcemap-loader": "^0.3.7", - "karma-webpack": "^4.0.2", + "karma-mocha": "~2.0.1", + "karma-sourcemap-loader": "~0.3.8", + "karma-webpack": "~4.0.2", "link-parent-bin": "~1.0.0", "load-grunt-tasks": "~5.1.0", - "mocha": "^8.0.1", + "mocha": "~8.1.3", "mutation-testing-metrics": "~1.4.0", "rxjs": "~6.5.3", "semver": "~6.3.0", - "ts-jest": "^25.4.0", - "ts-loader": "^7.0.3", + "ts-jest": "~26.3.0", + "ts-loader": "~8.0.3", "ts-node": "~7.0.0", "typescript": "~3.9.2", - "webpack": "~4.41.2" + "webpack": "~4.41.2", + "webpack-cli": "~3.3.12" }, "scripts": { "postinstall": "node ../node_modules/lerna/cli.js bootstrap && npm run install-local-dependencies && link-parent-bin -c test --link-local-dependencies true", @@ -45,18 +47,13 @@ "localDependencies": { "grunt-stryker": "../packages/grunt-stryker", "@stryker-mutator/core": "../packages/core", + "@stryker-mutator/instrumenter": "../packages/instrumenter", "@stryker-mutator/api": "../packages/api", - "@stryker-mutator/babel-transpiler": "../packages/babel-transpiler", - "@stryker-mutator/jasmine-framework": "../packages/jasmine-framework", "@stryker-mutator/jasmine-runner": "../packages/jasmine-runner", - "@stryker-mutator/javascript-mutator": "../packages/javascript-mutator", "@stryker-mutator/jest-runner": "../packages/jest-runner", "@stryker-mutator/karma-runner": "../packages/karma-runner", - "@stryker-mutator/mocha-framework": "../packages/mocha-framework", "@stryker-mutator/mocha-runner": "../packages/mocha-runner", "@stryker-mutator/util": "../packages/util", - "@stryker-mutator/typescript": "../packages/typescript", - "@stryker-mutator/vue-mutator": "../packages/vue-mutator", - "@stryker-mutator/webpack-transpiler": "../packages/webpack-transpiler" + "@stryker-mutator/typescript-checker": "../packages/typescript-checker" } } diff --git a/e2e/tasks/run-e2e-tests.ts b/e2e/tasks/run-e2e-tests.ts index 5a8043d8fb..1501785980 100644 --- a/e2e/tasks/run-e2e-tests.ts +++ b/e2e/tasks/run-e2e-tests.ts @@ -1,25 +1,22 @@ import fs = require('fs'); -import * as path from 'path'; +import path from 'path'; import execa from 'execa'; -import * as semver from 'semver'; -import * as os from 'os'; +import semver from 'semver'; +import os from 'os'; import { from, defer } from 'rxjs'; -import { tap, mergeAll, map, filter } from 'rxjs/operators'; +import { tap, mergeAll, map } from 'rxjs/operators'; const testRootDir = path.resolve(__dirname, '..', 'test'); function runE2eTests() { - const testDirs = fs.readdirSync(testRootDir); + const testDirs = fs.readdirSync(testRootDir).filter(dir => fs.statSync(path.join(testRootDir, dir)).isDirectory()); // Create test$, an observable of test runs - const test$ = from(testDirs).pipe( - filter(dir => fs.statSync(path.join(testRootDir, dir)).isDirectory()), - map(testDir => defer(() => runTest(testDir))) - ); + const test$ = from(testDirs).pipe(map(testDir => defer(() => runTest(testDir)))); let testsRan = 0; return test$.pipe( - mergeAll(os.cpus().length), // use mergeAll to limit concurrent test runs + mergeAll(os.cpus().length && 2), // use mergeAll to limit concurrent test runs tap(testDir => console.log(`\u2714 ${testDir} tested (${++testsRan}/${testDirs.length})`)), ); } @@ -39,13 +36,13 @@ function execNpm(command: string, testDir: string, stream: boolean) { const testProcess = execa('npm', [command], { timeout: 500000, cwd: currentTestDir, stdio: 'pipe' }); let stderr = ''; let stdout = ''; - testProcess.stderr.on('data', chunk => { + testProcess.stderr!.on('data', chunk => { stderr += chunk.toString(); if (stream) { console.error(chunk.toString()); } }); - testProcess.stdout.on('data', chunk => { + testProcess.stdout!.on('data', chunk => { stdout += chunk.toString() if (stream) { console.log(chunk.toString()); diff --git a/e2e/tasks/ts-node-register.js b/e2e/tasks/ts-node-register.js index 6c46e075c9..3381024286 100644 --- a/e2e/tasks/ts-node-register.js +++ b/e2e/tasks/ts-node-register.js @@ -1,4 +1,7 @@ require('ts-node').register({ transpileOnly: true, - skipProject: true + skipProject: true, + compilerOptions: { + esModuleInterop: true + } }); diff --git a/e2e/test/angular-project/package.json b/e2e/test/angular-project/package.json index c00a0b4349..609a3e9435 100644 --- a/e2e/test/angular-project/package.json +++ b/e2e/test/angular-project/package.json @@ -19,7 +19,7 @@ "@angular/platform-browser": "~9.1.6", "@angular/platform-browser-dynamic": "~9.1.6", "rxjs": "~6.5.3", - "tslib": "^1.10.0", + "tslib": "~1.10.0", "zone.js": "~0.10.2" }, "devDependencies": { @@ -42,8 +42,9 @@ "localDependencies": { "@stryker-mutator/api": "../../../packages/api", "@stryker-mutator/core": "../../../packages/core", + "@stryker-mutator/instrumenter": "../../../packages/instrumenter", "@stryker-mutator/karma-runner": "../../../packages/karma-runner", - "@stryker-mutator/typescript": "../../../packages/typescript", + "@stryker-mutator/typescript-checker": "../../../packages/typescript-checker", "@stryker-mutator/util": "../../../packages/util" } } diff --git a/e2e/test/angular-project/src/app/app.component.ts b/e2e/test/angular-project/src/app/app.component.ts index 2943b1f916..325337ed9e 100644 --- a/e2e/test/angular-project/src/app/app.component.ts +++ b/e2e/test/angular-project/src/app/app.component.ts @@ -6,5 +6,5 @@ import { Component } from '@angular/core'; templateUrl: './app.component.html' }) export class AppComponent { - public title = 'angular-project'; + public title = 'angular' + '-project'; } diff --git a/e2e/test/angular-project/src/tsconfig.app.json b/e2e/test/angular-project/src/tsconfig.app.json index f3a1b80180..be294a58c4 100644 --- a/e2e/test/angular-project/src/tsconfig.app.json +++ b/e2e/test/angular-project/src/tsconfig.app.json @@ -4,11 +4,13 @@ "outDir": "../out-tsc/app", "types": [] }, - "files": [ - "main.ts", - "polyfills.ts" - ], "include": [ + "main.ts", + "polyfills.ts", + "app/**/*", "src/**/*.d.ts" + ], + "exclude": [ + "app/**/*.spec.ts" ] } diff --git a/e2e/test/angular-project/stryker.conf.js b/e2e/test/angular-project/stryker.conf.js deleted file mode 100644 index 625ac3434a..0000000000 --- a/e2e/test/angular-project/stryker.conf.js +++ /dev/null @@ -1,23 +0,0 @@ -module.exports = function (config) { - config.set({ - mutate: [ - 'src/**/*.ts', - '!src/**/*.spec.ts', - '!src/test.ts', - '!src/environments/*.ts' - ], - testRunner: 'karma', - mutator: 'typescript', - karma: { - configFile: 'src/karma.conf.js', - projectType: 'angular-cli', - config: { - browsers: ['ChromeHeadless'] - } - }, - reporters: ['event-recorder'], - coverageAnalysis: 'off', - maxConcurrentTestRunners: 1, - timeoutMS: 60000 - }); -}; diff --git a/e2e/test/angular-project/stryker.conf.json b/e2e/test/angular-project/stryker.conf.json new file mode 100644 index 0000000000..b87c7ca134 --- /dev/null +++ b/e2e/test/angular-project/stryker.conf.json @@ -0,0 +1,32 @@ +{ + "$schema": "../../node_modules/@stryker-mutator/core/schema/stryker-schema.json", + "mutate": [ + "src/**/*.ts", + "!src/**/*.spec.ts", + "!src/test.ts", + "!src/environments/*.ts" + ], + "testRunner": "karma", + "checkers": [ + "typescript" + ], + "karma": { + "configFile": "src/karma.conf.js", + "projectType": "angular-cli", + "config": { + "browsers": [ + "ChromeHeadless" + ] + } + }, + "tsconfigFile": "src/tsconfig.app.json", + "reporters": [ + "progress", + "clear-text", + "html", + "event-recorder" + ], + "coverageAnalysis": "off", + "concurrency": 1, + "timeoutMS": 60000 +} diff --git a/e2e/test/angular-project/verify/verify.ts b/e2e/test/angular-project/verify/verify.ts index af10905163..16134e333e 100644 --- a/e2e/test/angular-project/verify/verify.ts +++ b/e2e/test/angular-project/verify/verify.ts @@ -1,44 +1,17 @@ -import { expectMetricsResult, produceMetrics } from '../../../helpers'; +import { expectMetrics } from '../../../helpers'; describe('After running stryker on angular project', () => { - it('should report 15% or 7% mutation score', async () => { - - // Possible race condition: https://github.com/stryker-mutator/stryker/issues/1749 - try { - await expectMetricsResult({ - metrics: produceMetrics({ - killed: 2, - mutationScore: 15.38, - mutationScoreBasedOnCoveredCode: 15.38, - runtimeErrors: 2, - survived: 11, - totalCovered: 13, - totalDetected: 2, - totalInvalid: 2, - totalMutants: 15, - totalUndetected: 11, - totalValid: 13 - }) - }); - } catch { - await expectMetricsResult({ - metrics: produceMetrics({ - compileErrors: 0, - killed: 1, - mutationScore: 7.69, - mutationScoreBasedOnCoveredCode: 7.69, - noCoverage: 0, - runtimeErrors: 2, - survived: 12, - timeout: 0, - totalCovered: 13, - totalDetected: 1, - totalInvalid: 2, - totalMutants: 15, - totalUndetected: 12, - totalValid: 13 - }) - }); - } + it('should report 20% or 7% mutation score', async () => { + await expectMetrics({ + mutationScore: 33.33, + killed: 2, + survived: 4, + noCoverage: 0, + compileErrors: 1, + }) + // -------------------|---------|----------|-----------|------------|----------|---------| + // File | % score | # killed | # timeout | # survived | # no cov | # error | + // -------------------|---------|----------|-----------|------------|----------|---------| + // All files | 20.00 | 1 | 0 | 4 | 0 | 0 | }); }); diff --git a/e2e/test/babel-transpiling/.mocharc.json b/e2e/test/babel-transpiling/.mocharc.json new file mode 100644 index 0000000000..3434b0aaa5 --- /dev/null +++ b/e2e/test/babel-transpiling/.mocharc.json @@ -0,0 +1,3 @@ +{ + "spec": "dist/test/**.js" +} diff --git a/e2e/test/babel-transpiling/package.json b/e2e/test/babel-transpiling/package.json index 0b77d5313c..4971349e46 100644 --- a/e2e/test/babel-transpiling/package.json +++ b/e2e/test/babel-transpiling/package.json @@ -5,9 +5,13 @@ "description": "A module to test stryker-babel with stryker-javascript-mutator", "main": "index.js", "scripts": { + "prebuild": "rimraf dist", + "tmp": "echo %cd%", + "build": "babel -d dist --only \"src/**/*.js\" --only \"test/**/*.js\" .", "pretest": "rimraf \"reports\"", "test": "stryker run", - "posttest": "mocha --require ../../tasks/ts-node-register.js verify/*.ts" + "test:unit": "mocha", + "posttest": "mocha --no-config --require ../../tasks/ts-node-register.js verify/*.ts" }, "keywords": [], "author": "", diff --git a/e2e/test/babel-transpiling/stryker.conf.js b/e2e/test/babel-transpiling/stryker.conf.js index f398fca69c..3c4441e087 100644 --- a/e2e/test/babel-transpiling/stryker.conf.js +++ b/e2e/test/babel-transpiling/stryker.conf.js @@ -2,18 +2,14 @@ module.exports = { mutate: [ 'src/*.js' ], - testFramework: 'mocha', testRunner: 'mocha', coverageAnalysis: 'off', - mutator: { - name: 'javascript', - plugins: [['pipelineOperator', { proposal: 'minimal' }]] - }, - transpilers: [ - 'babel' - ], + buildCommand: 'npm run build', timeoutMS: 60000, - reporters: ['clear-text', 'html', 'event-recorder'], - maxConcurrentTestRunners: 2, - logLevel: 'info' + reporters: ['clear-text', 'html', 'event-recorder', 'progress'], + concurrency: 1, + logLevel: 'info', + plugins: [ + '@stryker-mutator/mocha-runner' + ] }; diff --git a/e2e/test/babel-transpiling/verify/verify.ts b/e2e/test/babel-transpiling/verify/verify.ts index b855b55db8..871c0a4f94 100644 --- a/e2e/test/babel-transpiling/verify/verify.ts +++ b/e2e/test/babel-transpiling/verify/verify.ts @@ -10,12 +10,12 @@ describe('Verify stryker has ran correctly', () => { killed: 24, mutationScore: 55.81, mutationScoreBasedOnCoveredCode: 55.81, - runtimeErrors: 2, + runtimeErrors: 1, survived: 19, totalCovered: 43, totalDetected: 24, - totalInvalid: 2, - totalMutants: 45, + totalInvalid: 1, + totalMutants: 44, totalUndetected: 19, totalValid: 43 }) diff --git a/e2e/test/command/stryker.conf.json b/e2e/test/command/stryker.conf.json index b60da08268..44d8b5afc9 100644 --- a/e2e/test/command/stryker.conf.json +++ b/e2e/test/command/stryker.conf.json @@ -1,15 +1,10 @@ { - "mutate": [ - "src/*.js" - ], - "testFramework": "mocha", - "coverageAnalysis": "off", + "$schema": "../../node_modules/@stryker-mutator/core/schema/stryker-schema.json", "reporters": [ "clear-text", "event-recorder" ], - "mutator": "javascript", - "maxConcurrentTestRunners": 2, + "concurrency": 2, "commandRunner": { "command": "npm run mocha" }, diff --git a/e2e/test/command/verify/verify.ts b/e2e/test/command/verify/verify.ts index d7c32db4c1..c4baaf77bf 100644 --- a/e2e/test/command/verify/verify.ts +++ b/e2e/test/command/verify/verify.ts @@ -22,8 +22,9 @@ describe('After running stryker with the command test runner', () => { it('should write to a log file', async () => { const strykerLog = await fs.readFile('./stryker.log', 'utf8'); - expect(strykerLog).contains('INFO InitialTestExecutor Initial test run succeeded. Ran 1 test'); - expect(strykerLog).matches(/Stryker Done in \d+/); + expect(strykerLog).contains('INFO DryRunExecutor Initial test run succeeded. Ran 1 test'); + expect(strykerLog).matches(/MutationTestExecutor Done in \d+/); expect(strykerLog).not.contains('ERROR'); + expect(strykerLog).not.contains('WARN'); }); }); diff --git a/e2e/test/coverage-analysis/package.json b/e2e/test/coverage-analysis/package.json new file mode 100644 index 0000000000..20bf0cdfda --- /dev/null +++ b/e2e/test/coverage-analysis/package.json @@ -0,0 +1,8 @@ +{ + "name": "coverage-analysis", + "description": "A e2e test for --coverageAnalysis", + "scripts": { + "test:unit": "jasmine", + "test": "mocha --no-package --require \"../../tasks/ts-node-register.js\" verify/verify.ts" + } +} diff --git a/e2e/test/coverage-analysis/spec/concat.spec.js b/e2e/test/coverage-analysis/spec/concat.spec.js new file mode 100644 index 0000000000..176781f24e --- /dev/null +++ b/e2e/test/coverage-analysis/spec/concat.spec.js @@ -0,0 +1,7 @@ +const { concat } = require('../src/concat'); + +describe(concat.name, () => { + it('should concat a and b', () => { + expect(concat('foo', 'bar')).toBe('foobar'); + }) +}); diff --git a/e2e/test/coverage-analysis/spec/math.spec.js b/e2e/test/coverage-analysis/spec/math.spec.js new file mode 100644 index 0000000000..6fde7d0bf3 --- /dev/null +++ b/e2e/test/coverage-analysis/spec/math.spec.js @@ -0,0 +1,17 @@ +const { add, multiply } = require('../src/math'); + +describe(add.name, () => { + + it('should add two numbers', () => { + expect(add(1, 2)).toBe(3); + }); +}); + +describe(multiply.name, () => { + it('should multiply the numbers', () => { + // Bad test, surviving mutant when * => / + expect(multiply(2, 1)).toBe(2); + }); +}); + +// Missing describe for `addOne` -> surviving / noCoverage mutant diff --git a/e2e/test/coverage-analysis/spec/support/jasmine.json b/e2e/test/coverage-analysis/spec/support/jasmine.json new file mode 100644 index 0000000000..64be29c54b --- /dev/null +++ b/e2e/test/coverage-analysis/spec/support/jasmine.json @@ -0,0 +1,5 @@ +{ + "spec_files": [ + "**/*[sS]pec.[jt]s" + ] +} diff --git a/e2e/test/coverage-analysis/src/concat.js b/e2e/test/coverage-analysis/src/concat.js new file mode 100644 index 0000000000..b8cca300a7 --- /dev/null +++ b/e2e/test/coverage-analysis/src/concat.js @@ -0,0 +1,3 @@ +module.exports.concat = function concat(a, b){ + return `${a}${b}`; +}; diff --git a/e2e/test/coverage-analysis/src/math.js b/e2e/test/coverage-analysis/src/math.js new file mode 100644 index 0000000000..bcea182df7 --- /dev/null +++ b/e2e/test/coverage-analysis/src/math.js @@ -0,0 +1,17 @@ +function add(a, b) { + return a + b; +} + +function multiply(a, b) { + return a * b; +} + +function addOne(a) { + return ++a; +} + +module.exports = { + add, + multiply, + addOne +}; diff --git a/e2e/test/coverage-analysis/verify/coverage-analysis-reporter.js b/e2e/test/coverage-analysis/verify/coverage-analysis-reporter.js new file mode 100644 index 0000000000..22a9fc872a --- /dev/null +++ b/e2e/test/coverage-analysis/verify/coverage-analysis-reporter.js @@ -0,0 +1,31 @@ +const { PluginKind, declareClassPlugin } = require('@stryker-mutator/api/plugin'); + +class CoverageAnalysisReporter { + /** + * @type {import('mutation-testing-report-schema').MutationTestResult} + */ + report; + /** + * @type { CoverageAnalysisReporter } + */ + static instance; + + constructor() { + CoverageAnalysisReporter.instance = this; + } + + /** + * @param {import('mutation-testing-report-schema').MutationTestResult} report + * @returns {void} + */ + onMutationTestReportReady(report) { + this.report = report; + } +} +const strykerPlugins = [declareClassPlugin(PluginKind.Reporter, 'coverageAnalysis', CoverageAnalysisReporter)]; +module.exports = { + CoverageAnalysisReporter, + strykerPlugins +}; + + diff --git a/e2e/test/coverage-analysis/verify/verify.ts b/e2e/test/coverage-analysis/verify/verify.ts new file mode 100644 index 0000000000..e06df8246f --- /dev/null +++ b/e2e/test/coverage-analysis/verify/verify.ts @@ -0,0 +1,84 @@ +import { default as Stryker } from '@stryker-mutator/core'; +import { expect } from 'chai'; +import { CoverageAnalysisReporter } from './coverage-analysis-reporter'; +import { calculateMetrics, Metrics } from 'mutation-testing-metrics'; + +const expectedTestCount = Object.freeze({ + off: 18, + all: 12, + perTest: 6 +}); + +describe('Coverage analysis', () => { + it('should provide the expected with --coverageAnalysis off', async () => { + // Arrange + const stryker = new Stryker({ + coverageAnalysis: 'off', + testRunner: 'jasmine', + reporters: ['coverageAnalysis'], + plugins: ['@stryker-mutator/jasmine-runner', require.resolve('./coverage-analysis-reporter')] + }); + + // Act + const testsRan = (await stryker.runMutationTest()).reduce((a, b) => a + b.nrOfTestsRan, 0); + + // Assert + const metricsResult = calculateMetrics(CoverageAnalysisReporter.instance?.report.files); + const expectedMetricsResult: Partial = { + noCoverage: 0, + survived: 3, + killed: 5, + mutationScore: 62.5 + }; + expect(metricsResult.metrics).deep.include(expectedMetricsResult); + expect(testsRan).eq(expectedTestCount.off); + }); + + it('should provide the expected with --coverageAnalysis all', async () => { + // Arrange + const stryker = new Stryker({ + coverageAnalysis: 'all', + testRunner: 'jasmine', + reporters: ['coverageAnalysis'], + plugins: ['@stryker-mutator/jasmine-runner', require.resolve('./coverage-analysis-reporter')] + }); + + // Act + const testsRan = (await stryker.runMutationTest()).reduce((a, b) => a + b.nrOfTestsRan, 0); + + // Assert + const metricsResult = calculateMetrics(CoverageAnalysisReporter.instance?.report.files); + const expectedMetricsResult: Partial = { + noCoverage: 2, + survived: 1, + killed: 5, + mutationScore: 62.5 + }; + expect(metricsResult.metrics).deep.include(expectedMetricsResult); + expect(testsRan).eq(expectedTestCount.all); + }); + + it('should provide the expected with --coverageAnalysis perTest', async () => { + // Arrange + const stryker = new Stryker({ + coverageAnalysis: 'perTest', + testRunner: 'jasmine', + reporters: ['coverageAnalysis'], + plugins: ['@stryker-mutator/jasmine-runner', require.resolve('./coverage-analysis-reporter')] + }); + + // Act + const testsRan = (await stryker.runMutationTest()).reduce((a, b) => a + b.nrOfTestsRan, 0); + + // Assert + const metricsResult = calculateMetrics(CoverageAnalysisReporter.instance?.report.files); + const expectedMetricsResult: Partial = { + noCoverage: 2, + survived: 1, + killed: 5, + mutationScore: 62.5 + }; + expect(metricsResult.metrics).deep.include(expectedMetricsResult); + expect(testsRan).eq(expectedTestCount.perTest); + }); +}); diff --git a/e2e/test/exit-prematurely-dry-run-fails/.mocharc.jsonc b/e2e/test/exit-prematurely-dry-run-fails/.mocharc.jsonc new file mode 100644 index 0000000000..c923497a9a --- /dev/null +++ b/e2e/test/exit-prematurely-dry-run-fails/.mocharc.jsonc @@ -0,0 +1,3 @@ +{ + "spec": ["test/unit/*.js"] +} diff --git a/e2e/test/mocha-mocha/package-lock.json b/e2e/test/exit-prematurely-dry-run-fails/package-lock.json similarity index 100% rename from e2e/test/mocha-mocha/package-lock.json rename to e2e/test/exit-prematurely-dry-run-fails/package-lock.json diff --git a/e2e/test/exit-prematurely-dry-run-fails/package.json b/e2e/test/exit-prematurely-dry-run-fails/package.json new file mode 100644 index 0000000000..12d0ef2507 --- /dev/null +++ b/e2e/test/exit-prematurely-dry-run-fails/package.json @@ -0,0 +1,14 @@ +{ + "name": "exit-prematurely-dry-run-fails", + "version": "0.0.0", + "private": true, + "description": "A module to perform an integration test", + "main": "index.js", + "scripts": { + "pretest": "rimraf reports .stryker-tmp stryker.log", + "test": "stryker run || node -p \"require('fs').appendFileSync('stryker.log', 'Exited with an error exit code')\"", + "posttest": "mocha --no-config --require ../../tasks/ts-node-register.js verify/*.ts" + }, + "author": "", + "license": "ISC" +} diff --git a/e2e/test/exit-prematurely-dry-run-fails/src/add.js b/e2e/test/exit-prematurely-dry-run-fails/src/add.js new file mode 100644 index 0000000000..c76f6add0d --- /dev/null +++ b/e2e/test/exit-prematurely-dry-run-fails/src/add.js @@ -0,0 +1,6 @@ +module.exports.add = function(num1, num2) { + return num1 + num2; +}; + + + diff --git a/e2e/test/exit-prematurely-dry-run-fails/stryker.conf.json b/e2e/test/exit-prematurely-dry-run-fails/stryker.conf.json new file mode 100644 index 0000000000..0d3d3084b7 --- /dev/null +++ b/e2e/test/exit-prematurely-dry-run-fails/stryker.conf.json @@ -0,0 +1,11 @@ +{ + "$schema": "../../node_modules/@stryker-mutator/core/schema/stryker-schema.json", + "testRunner": "mocha", + "concurrency": 2, + "coverageAnalysis": "off", + "fileLogLevel": "info", + "reporters": ["clear-text", "html", "event-recorder"], + "plugins": [ + "@stryker-mutator/mocha-runner" + ] +} diff --git a/e2e/test/exit-prematurely-dry-run-fails/test/unit/add.spec.ts.js b/e2e/test/exit-prematurely-dry-run-fails/test/unit/add.spec.ts.js new file mode 100644 index 0000000000..9df5d88ef7 --- /dev/null +++ b/e2e/test/exit-prematurely-dry-run-fails/test/unit/add.spec.ts.js @@ -0,0 +1,13 @@ +const { add } = require('../../src/add'); +const { expect } = require('chai'); + +describe('add', () => { + + it('2 + 3 = 5', () => { + expect(add(2, 3)).to.be.equal(5); + }); + + it('1 + 1 = 3... ? (this is the test that should fail)', () => { + expect(add(1, 1)).to.be.equal(3); + }); +}); diff --git a/e2e/test/exit-prematurely-dry-run-fails/verify/verify.ts b/e2e/test/exit-prematurely-dry-run-fails/verify/verify.ts new file mode 100644 index 0000000000..558024b478 --- /dev/null +++ b/e2e/test/exit-prematurely-dry-run-fails/verify/verify.ts @@ -0,0 +1,35 @@ +import { promises as fs } from 'fs'; +import chai, { expect } from 'chai'; +import { it } from 'mocha'; +import chaiAsPromised from 'chai-as-promised'; +chai.use(chaiAsPromised); + +describe('Verify stryker has handled dry run failure correctly', () => { + + let strykerLog: string; + + before(async () => { + strykerLog = await fs.readFile('./stryker.log', 'utf8'); + }); + + it('should about failed tests in initial test run', async () => { + expect(strykerLog).contains('There were failed tests in the initial test run'); + }); + + it('should log exactly which test failed and why', async () => { + expect(strykerLog) + .contains('add 1 + 1 = 3... ? (this is the test that should fail)') + .contains('expected 2 to equal 3'); + }); + + it('should have exited with a non-zero exit code', async () => { + // This line is added in package.json script if the process exited in an error. + expect(strykerLog) + .contains('Exited with an error exit code'); + }); + + + it('should not delete the temp dir', async () => { + await expect(fs.stat('.stryker-tmp'), 'Expected the `.stryker-tmp` dir to not be deleted.').not.rejected; + }); +}); diff --git a/e2e/test/exit-prematurely/.babelrc b/e2e/test/exit-prematurely-no-tests-executed/.babelrc similarity index 100% rename from e2e/test/exit-prematurely/.babelrc rename to e2e/test/exit-prematurely-no-tests-executed/.babelrc diff --git a/e2e/test/exit-prematurely/package-lock.json b/e2e/test/exit-prematurely-no-tests-executed/package-lock.json similarity index 100% rename from e2e/test/exit-prematurely/package-lock.json rename to e2e/test/exit-prematurely-no-tests-executed/package-lock.json diff --git a/e2e/test/exit-prematurely-no-tests-executed/package.json b/e2e/test/exit-prematurely-no-tests-executed/package.json new file mode 100644 index 0000000000..842bba12c5 --- /dev/null +++ b/e2e/test/exit-prematurely-no-tests-executed/package.json @@ -0,0 +1,15 @@ +{ + "name": "exit-prematurely-no-tests-executed", + "version": "1.0.0", + "private": true, + "description": "A module to test the alternative flow when Stryker should exit prematurely, see https://github.com/stryker-mutator/stryker/issues/1519", + "main": "index.js", + "scripts": { + "pretest": "rimraf \"reports\" stryker.log .stryker-tmp ", + "test": "stryker run || node -e \"require('fs').appendFileSync('stryker.log', 'Exit with non-zero exit code');\"", + "posttest": "mocha --require ../../tasks/ts-node-register.js verify/*.ts" + }, + "keywords": [], + "author": "", + "license": "ISC" +} diff --git a/e2e/test/exit-prematurely-no-tests-executed/src/add.js b/e2e/test/exit-prematurely-no-tests-executed/src/add.js new file mode 100644 index 0000000000..c76f6add0d --- /dev/null +++ b/e2e/test/exit-prematurely-no-tests-executed/src/add.js @@ -0,0 +1,6 @@ +module.exports.add = function(num1, num2) { + return num1 + num2; +}; + + + diff --git a/e2e/test/exit-prematurely-no-tests-executed/stryker.conf.json b/e2e/test/exit-prematurely-no-tests-executed/stryker.conf.json new file mode 100644 index 0000000000..59e0604d96 --- /dev/null +++ b/e2e/test/exit-prematurely-no-tests-executed/stryker.conf.json @@ -0,0 +1,12 @@ +{ + "$schema": "../../node_modules/@stryker-mutator/core/schema/stryker-schema.json", + "testRunner": "mocha", + "concurrency": 2, + "coverageAnalysis": "perTest", + "reporters_comment": "Don't remove the html reporter here, we want to test that reports is not written", + "reporters": ["html"], + "plugins": [ + "@stryker-mutator/mocha-runner" + ], + "fileLogLevel": "info" +} diff --git a/e2e/test/exit-prematurely-no-tests-executed/test/test.js b/e2e/test/exit-prematurely-no-tests-executed/test/test.js new file mode 100644 index 0000000000..9ae73b95f5 --- /dev/null +++ b/e2e/test/exit-prematurely-no-tests-executed/test/test.js @@ -0,0 +1 @@ +// Idle diff --git a/e2e/test/exit-prematurely-no-tests-executed/verify/verify.ts b/e2e/test/exit-prematurely-no-tests-executed/verify/verify.ts new file mode 100644 index 0000000000..cb4e191982 --- /dev/null +++ b/e2e/test/exit-prematurely-no-tests-executed/verify/verify.ts @@ -0,0 +1,23 @@ +import fs from 'fs'; +import { expect } from 'chai'; + +describe('Verify stryker has ran correctly', () => { + + const strykerLog = fs.readFileSync('./stryker.log', 'utf8'); + + it('exit prematurely', () => { + expect(strykerLog).contains('No tests were executed. Stryker will exit prematurely.'); + }); + + it('should exit with a non-zero exit code', () => { + expect(strykerLog).contains('Exit with non-zero exit code'); + }); + + it('should not report the mutant run', () => { + expect(fs.existsSync('reports'), 'Expected no reports to be written to disk, but they did').false; + }); + + it('should not delete the temp dir', () => { + expect(fs.existsSync('.stryker-tmp'), 'Expected the `.stryker-tmp` dir to not be deleted.').true; + }); +}); diff --git a/e2e/test/exit-prematurely/package.json b/e2e/test/exit-prematurely/package.json deleted file mode 100644 index 547e081f16..0000000000 --- a/e2e/test/exit-prematurely/package.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "exit-prematurely", - "version": "1.0.0", - "private": true, - "description": "A module to test the alternative flow when Stryker should exit prematurely, see https://github.com/stryker-mutator/stryker/issues/1519", - "main": "index.js", - "scripts": { - "pretest": "rimraf \"reports\" stryker.log .stryker-tmp ", - "test": "stryker run", - "posttest": "mocha --require ../../tasks/ts-node-register.js verify/*.ts" - }, - "keywords": [], - "author": "", - "license": "ISC" -} diff --git a/e2e/test/exit-prematurely/stryker.conf.js b/e2e/test/exit-prematurely/stryker.conf.js deleted file mode 100644 index b7422238b2..0000000000 --- a/e2e/test/exit-prematurely/stryker.conf.js +++ /dev/null @@ -1,17 +0,0 @@ -module.exports = { - mutate: [ - 'src/*.js' - ], - testFramework: 'mocha', - testRunner: 'mocha', - coverageAnalysis: 'off', - mutator: 'javascript', - transpilers: [ - 'babel' - ], - timeoutMS: 60000, - reporters: ['clear-text', 'html', 'event-recorder'], - maxConcurrentTestRunners: 2, - logLevel: 'info', - fileLogLevel: 'info' -} diff --git a/e2e/test/exit-prematurely/test/test.js b/e2e/test/exit-prematurely/test/test.js deleted file mode 100644 index bf0dffa6ce..0000000000 --- a/e2e/test/exit-prematurely/test/test.js +++ /dev/null @@ -1 +0,0 @@ -// Idle \ No newline at end of file diff --git a/e2e/test/exit-prematurely/verify/verify.ts b/e2e/test/exit-prematurely/verify/verify.ts deleted file mode 100644 index b9ebe2c5ae..0000000000 --- a/e2e/test/exit-prematurely/verify/verify.ts +++ /dev/null @@ -1,19 +0,0 @@ -import * as fs from 'fs'; -import { expect } from 'chai'; - -describe('Verify stryker has ran correctly', () => { - - const strykerLog = fs.readFileSync('./stryker.log', 'utf8'); - - it('exit prematurely', async () => { - expect(strykerLog).contains('No tests were executed. Stryker will exit prematurely.'); - }); - - it('should log about a mutant free world', async () => { - expect(strykerLog).contains('It\'s a mutant-free world, nothing to test'); - }); - - it('should warn about the globbing expression resulting in no files', () => { - expect(strykerLog).contains('Globbing expression "src/*.js" did not result in any files.'); - }); -}); diff --git a/e2e/test/grunt-stryker-test/Gruntfile.js b/e2e/test/grunt-stryker-test/Gruntfile.js index a98928202e..4008e7b1c4 100644 --- a/e2e/test/grunt-stryker-test/Gruntfile.js +++ b/e2e/test/grunt-stryker-test/Gruntfile.js @@ -16,10 +16,9 @@ module.exports = function (grunt) { ] }, options: { - testFramework: 'jasmine', testRunner: 'karma', logLevel: 'info', - maxConcurrentTestRunners: 2, + concurrency: 2, tempDirName: '.stryker-tmp-2' }, }, diff --git a/e2e/test/grunt-stryker-test/stryker.conf.js b/e2e/test/grunt-stryker-test/stryker.conf.js index 5af0780ef6..065acc96b0 100644 --- a/e2e/test/grunt-stryker-test/stryker.conf.js +++ b/e2e/test/grunt-stryker-test/stryker.conf.js @@ -3,12 +3,13 @@ module.exports = function (config) { mutate: [ 'sampleProject/src/**' ], - karmaConfig: { - files: ['sampleProject/**'] + karma: { + config: { + files: ['sampleProject/**'] + } }, - testFramework: 'jasmine', testRunner: 'karma', logLevel: 'info', - maxConcurrentTestRunners: 2 + concurrency: 2 }); -} \ No newline at end of file +} diff --git a/e2e/test/mocha-mocha/.mocharc.jsonc b/e2e/test/ignore-project/.mocharc.jsonc similarity index 100% rename from e2e/test/mocha-mocha/.mocharc.jsonc rename to e2e/test/ignore-project/.mocharc.jsonc diff --git a/e2e/test/ignore-project/package-lock.json b/e2e/test/ignore-project/package-lock.json new file mode 100644 index 0000000000..3900182e5c --- /dev/null +++ b/e2e/test/ignore-project/package-lock.json @@ -0,0 +1,5 @@ +{ + "name": "mocha-mocha", + "version": "0.0.0", + "lockfileVersion": 1 +} diff --git a/e2e/test/ignore-project/package.json b/e2e/test/ignore-project/package.json new file mode 100644 index 0000000000..7345036e04 --- /dev/null +++ b/e2e/test/ignore-project/package.json @@ -0,0 +1,11 @@ +{ + "name": "ignore-project", + "description": "e2e test for different ignored mutants", + "version": "0.0.0", + "private": true, + "scripts": { + "test:unit": "mocha", + "test": "stryker run", + "posttest": "mocha --no-config --require ../../tasks/ts-node-register.js verify/*.ts" + } +} diff --git a/e2e/test/mocha-mocha/src/Add.js b/e2e/test/ignore-project/src/Add.js similarity index 100% rename from e2e/test/mocha-mocha/src/Add.js rename to e2e/test/ignore-project/src/Add.js diff --git a/e2e/test/mocha-mocha/src/Circle.js b/e2e/test/ignore-project/src/Circle.js similarity index 100% rename from e2e/test/mocha-mocha/src/Circle.js rename to e2e/test/ignore-project/src/Circle.js diff --git a/e2e/test/ignore-project/stryker.conf.json b/e2e/test/ignore-project/stryker.conf.json new file mode 100644 index 0000000000..90ba8aaf1c --- /dev/null +++ b/e2e/test/ignore-project/stryker.conf.json @@ -0,0 +1,18 @@ +{ + "$schema": "../../node_modules/@stryker-mutator/core/schema/stryker-schema.json", + "testRunner": "mocha", + "concurrency": 2, + "coverageAnalysis": "perTest", + "mutator": { + "excludedMutations": ["ArithmeticOperator", "BlockStatement"] + }, + "reporters": [ + "clear-text", + "html", + "event-recorder" + ], + "plugins": [ + "@stryker-mutator/mocha-runner" + ], + "allowConsoleColors": false +} diff --git a/e2e/test/mocha-mocha/test/helpers/testSetup.js b/e2e/test/ignore-project/test/helpers/testSetup.js similarity index 100% rename from e2e/test/mocha-mocha/test/helpers/testSetup.js rename to e2e/test/ignore-project/test/helpers/testSetup.js diff --git a/e2e/test/ignore-project/test/unit/AddSpec.js b/e2e/test/ignore-project/test/unit/AddSpec.js new file mode 100644 index 0000000000..a2e6d4fed4 --- /dev/null +++ b/e2e/test/ignore-project/test/unit/AddSpec.js @@ -0,0 +1,48 @@ +const { expect } = require('chai'); +const { add, addOne, isNegativeNumber, negate, notCovered } = require('../../src/Add'); + +describe('Add', function () { + it('should be able to add two numbers', function () { + var num1 = 2; + var num2 = 5; + var expected = num1 + num2; + + var actual = add(num1, num2); + + expect(actual).to.be.equal(expected); + }); + + it('should be able 1 to a number', function () { + var number = 2; + var expected = 3; + + var actual = addOne(number); + + expect(actual).to.be.equal(expected); + }); + + it('should be able negate a number', function () { + var number = 2; + var expected = -2; + + var actual = negate(number); + + expect(actual).to.be.equal(expected); + }); + + it('should be able to recognize a negative number', function () { + var number = -2; + + var isNegative = isNegativeNumber(number); + + expect(isNegative).to.be.true; + }); + + it('should be able to recognize that 0 is not a negative number', function () { + var number = 0; + + var isNegative = isNegativeNumber(number); + + expect(isNegative).to.be.false; + }); +}); diff --git a/e2e/test/ignore-project/test/unit/CircleSpec.js b/e2e/test/ignore-project/test/unit/CircleSpec.js new file mode 100644 index 0000000000..a04551753e --- /dev/null +++ b/e2e/test/ignore-project/test/unit/CircleSpec.js @@ -0,0 +1,13 @@ +const { expect } = require('chai'); +const { getCircumference } = require('../../src/Circle'); + +describe('Circle', function () { + it('should have a circumference of 2PI when the radius is 1', function () { + var radius = 1; + var expectedCircumference = 2 * Math.PI; + + var circumference = getCircumference(radius); + + expect(circumference).to.be.equal(expectedCircumference); + }); +}); diff --git a/e2e/test/ignore-project/verify/verify.ts b/e2e/test/ignore-project/verify/verify.ts new file mode 100644 index 0000000000..43b3ee5a4a --- /dev/null +++ b/e2e/test/ignore-project/verify/verify.ts @@ -0,0 +1,16 @@ +import { expectMetrics } from '../../../helpers'; + +describe('After running stryker on jest-react project', () => { + it('should report expected scores', async () => { + await expectMetrics({ + killed: 8, + ignored: 13, + mutationScore: 66.67, + }); + /* +-----------|---------|----------|-----------|------------|----------|---------| +File | % score | # killed | # timeout | # survived | # no cov | # error | +-----------|---------|----------|-----------|------------|----------|---------| +All files | 66.67 | 8 | 0 | 0 | 4 | 0 |*/ + }); +}); diff --git a/e2e/test/jasmine-jasmine/package.json b/e2e/test/jasmine-jasmine/package.json deleted file mode 100644 index 319ad73f5f..0000000000 --- a/e2e/test/jasmine-jasmine/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "jasmine-jasmine", - "version": "0.0.0", - "private": true, - "description": "A module to perform an integration test", - "main": "index.js", - "scripts": { - "pretest": "rimraf \"reports\" \"stryker.log\"", - "test": "stryker run", - "posttest": "mocha --require ../../tasks/ts-node-register.js verify/*.ts" - }, - "author": "", - "license": "Apache-2.0" -} diff --git a/e2e/test/jasmine-jasmine/stryker.conf.js b/e2e/test/jasmine-jasmine/stryker.conf.js deleted file mode 100644 index 63dc9b2847..0000000000 --- a/e2e/test/jasmine-jasmine/stryker.conf.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = function (config) { - config.set({ - mutate: ['lib/**/*.js'], - mutator: 'javascript', - coverageAnalysis: 'perTest', - testFramework: 'jasmine', - testRunner: 'jasmine', - reporters: ['clear-text', 'event-recorder'], - maxConcurrentTestRunners: 1, - jasmineConfigFile: 'spec/support/jasmine.json', - fileLogLevel: 'debug' - }); -}; diff --git a/e2e/test/jasmine-jasmine/verify/verify.ts b/e2e/test/jasmine-jasmine/verify/verify.ts deleted file mode 100644 index 021bd5dcdc..0000000000 --- a/e2e/test/jasmine-jasmine/verify/verify.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { promises as fs } from 'fs'; - -import { expect } from 'chai'; -import { expectMetricsResult, produceMetrics } from '../../../helpers'; - -describe('After running stryker with test runner jasmine, test framework jasmine', () => { - it('should report 85% mutation score', async () => { - await expectMetricsResult({ - metrics: produceMetrics({ - killed: 12, - mutationScore: 85.71, - mutationScoreBasedOnCoveredCode: 92.31, - noCoverage: 1, - survived: 1, - totalCovered: 13, - totalDetected: 12, - totalMutants: 14, - totalUndetected: 2, - totalValid: 14 - }) - }); - }); - - it('should write to a log file', async () => { - const strykerLog = await fs.readFile('./stryker.log', 'utf8'); - expect(strykerLog).matches(/INFO InputFileResolver Found 2 of 9 file\(s\) to be mutated/); - expect(strykerLog).matches(/Stryker Done in \d+/); - // TODO, we now have an error because of a memory leak: https://github.com/jasmine/jasmine-npm/issues/134 - // expect(strykerLog).not.contains('ERROR'); - }); -}); diff --git a/e2e/test/jasmine-jasmine/lib/jasmine_examples/Player.js b/e2e/test/jasmine-javascript/lib/jasmine_examples/Player.js similarity index 100% rename from e2e/test/jasmine-jasmine/lib/jasmine_examples/Player.js rename to e2e/test/jasmine-javascript/lib/jasmine_examples/Player.js diff --git a/e2e/test/jasmine-jasmine/lib/jasmine_examples/Song.js b/e2e/test/jasmine-javascript/lib/jasmine_examples/Song.js similarity index 100% rename from e2e/test/jasmine-jasmine/lib/jasmine_examples/Song.js rename to e2e/test/jasmine-javascript/lib/jasmine_examples/Song.js diff --git a/e2e/test/jasmine-jasmine/package-lock.json b/e2e/test/jasmine-javascript/package-lock.json similarity index 100% rename from e2e/test/jasmine-jasmine/package-lock.json rename to e2e/test/jasmine-javascript/package-lock.json diff --git a/e2e/test/jasmine-javascript/package.json b/e2e/test/jasmine-javascript/package.json new file mode 100644 index 0000000000..d6439f6332 --- /dev/null +++ b/e2e/test/jasmine-javascript/package.json @@ -0,0 +1,14 @@ +{ + "name": "jasmine-javascript", + "version": "0.0.0", + "private": true, + "description": "A module to perform an integration test", + "main": "index.js", + "scripts": { + "pretest": "rimraf \"reports\" \"stryker.log\"", + "test": "stryker run", + "posttest": "mocha --require ../../tasks/ts-node-register.js verify/*.ts" + }, + "author": "", + "license": "Apache-2.0" +} diff --git a/e2e/test/jasmine-jasmine/spec/helpers/jasmine_examples/SpecHelper.js b/e2e/test/jasmine-javascript/spec/helpers/jasmine_examples/SpecHelper.js similarity index 100% rename from e2e/test/jasmine-jasmine/spec/helpers/jasmine_examples/SpecHelper.js rename to e2e/test/jasmine-javascript/spec/helpers/jasmine_examples/SpecHelper.js diff --git a/e2e/test/jasmine-jasmine/spec/jasmine_examples/PlayerSpec.js b/e2e/test/jasmine-javascript/spec/jasmine_examples/PlayerSpec.js similarity index 100% rename from e2e/test/jasmine-jasmine/spec/jasmine_examples/PlayerSpec.js rename to e2e/test/jasmine-javascript/spec/jasmine_examples/PlayerSpec.js diff --git a/e2e/test/jasmine-jasmine/spec/support/jasmine.json b/e2e/test/jasmine-javascript/spec/support/jasmine.json similarity index 100% rename from e2e/test/jasmine-jasmine/spec/support/jasmine.json rename to e2e/test/jasmine-javascript/spec/support/jasmine.json diff --git a/e2e/test/jasmine-javascript/stryker.conf.js b/e2e/test/jasmine-javascript/stryker.conf.js new file mode 100644 index 0000000000..aed4210023 --- /dev/null +++ b/e2e/test/jasmine-javascript/stryker.conf.js @@ -0,0 +1,12 @@ +module.exports = function (config) { + config.set({ + mutate: ['lib/**/*.js'], + coverageAnalysis: 'perTest', + testRunner: 'jasmine', + reporters: ['clear-text', 'event-recorder'], + concurrency: 2, + jasmineConfigFile: 'spec/support/jasmine.json', + fileLogLevel: 'debug', + plugins: ['@stryker-mutator/jasmine-runner'] + }); +}; diff --git a/e2e/test/jasmine-javascript/verify/verify.ts b/e2e/test/jasmine-javascript/verify/verify.ts new file mode 100644 index 0000000000..8737472a96 --- /dev/null +++ b/e2e/test/jasmine-javascript/verify/verify.ts @@ -0,0 +1,29 @@ +import { promises as fs } from 'fs'; + +import { expect } from 'chai'; +import { expectMetrics } from '../../../helpers'; + +describe('After running stryker with test runner jasmine, test framework jasmine', () => { + it('should report 85% mutation score', async () => { + await expectMetrics({ + killed: 12, + mutationScore: 85.71, + mutationScoreBasedOnCoveredCode: 100, + noCoverage: 2, + survived: 0, + totalCovered: 12, + totalDetected: 12, + totalMutants: 14, + totalUndetected: 2, + totalValid: 14 + }); + }); + + it('should write to a log file', async () => { + const strykerLog = await fs.readFile('./stryker.log', 'utf8'); + expect(strykerLog).matches(/INFO InputFileResolver Found 2 of 9 file\(s\) to be mutated/); + expect(strykerLog).matches(/Done in \d+ second/); + // TODO, we now have an error because of a memory leak: https://github.com/jasmine/jasmine-npm/issues/134 + // expect(strykerLog).not.contains('ERROR'); + }); +}); diff --git a/e2e/test/jasmine-ts-node/package-lock.json b/e2e/test/jasmine-ts-node/package-lock.json new file mode 100644 index 0000000000..0b394df7ab --- /dev/null +++ b/e2e/test/jasmine-ts-node/package-lock.json @@ -0,0 +1,13 @@ +{ + "name": "jasmine-ts-node", + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "@types/jasmine": { + "version": "3.5.11", + "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.5.11.tgz", + "integrity": "sha512-fg1rOd/DehQTIJTifGqGVY6q92lDgnLfs7C6t1ccSwQrMyoTGSoH6wWzhJDZb6ezhsdwAX4EIBLe8w5fXWmEng==", + "dev": true + } + } +} diff --git a/e2e/test/jasmine-ts-node/package.json b/e2e/test/jasmine-ts-node/package.json new file mode 100644 index 0000000000..d29ac9554b --- /dev/null +++ b/e2e/test/jasmine-ts-node/package.json @@ -0,0 +1,16 @@ +{ + "name": "jasmine-ts-node", + "description": "A test for mocha using ts-node (no transpiler) using mocha package config", + "scripts": { + "test:unit": "jasmine", + "test": "stryker run", + "posttest": "mocha --no-package --require \"../../tasks/ts-node-register.js\" verify/verify.ts" + }, + "mocha": { + "require": "ts-node/register/transpile-only", + "spec": "test/**/*.ts" + }, + "devDependencies": { + "@types/jasmine": "~3.5.11" + } +} diff --git a/e2e/test/jasmine-ts-node/spec/PlayerSpec.ts b/e2e/test/jasmine-ts-node/spec/PlayerSpec.ts new file mode 100644 index 0000000000..5b3ac27ed6 --- /dev/null +++ b/e2e/test/jasmine-ts-node/spec/PlayerSpec.ts @@ -0,0 +1,61 @@ +import { Player } from '../src/Player'; +import { Song } from '../src/Song'; + +describe("Player", function () { + var player; + var song; + + beforeEach(function () { + player = new Player(); + song = new Song(); + }); + + it("should be able to play a Song", function () { + player.play(song); + expect(player.currentlyPlayingSong).toEqual(song); + + //demonstrates use of custom matcher + expect(player).toBePlaying(song); + }); + + describe("when song has been paused", function () { + beforeEach(function () { + player.play(song); + player.pause(); + }); + + it("should indicate that the song is currently paused", function () { + expect(player.isPlaying).toBeFalsy(); + + // demonstrates use of 'not' with a custom matcher + expect(player).not.toBePlaying(song); + }); + + it("should be possible to resume", function () { + player.resume(); + expect(player.isPlaying).toBeTruthy(); + expect(player.currentlyPlayingSong).toEqual(song); + }); + }); + + // demonstrates use of spies to intercept and test method calls + it("tells the current song if the user has made it a favorite", function () { + spyOn(song, 'persistFavoriteStatus'); + + player.play(song); + player.makeFavorite(); + + expect(song.persistFavoriteStatus).toHaveBeenCalledWith(true); + }); + + //demonstrates use of expected exceptions + describe("#resume", function () { + it("should throw an exception if song is already playing", function () { + player.play(song); + + expect(function () { + player.resume(); + }).toThrowError("song is already playing"); + }); + }); +}); diff --git a/e2e/test/jasmine-ts-node/spec/concat.spec.ts b/e2e/test/jasmine-ts-node/spec/concat.spec.ts new file mode 100644 index 0000000000..d14a2ce74b --- /dev/null +++ b/e2e/test/jasmine-ts-node/spec/concat.spec.ts @@ -0,0 +1,7 @@ +import { concat } from '../src/concat'; + +describe(concat.name, () => { + it('should concat a and b', () => { + expect(concat('foo', 'bar')).toBe('foobar'); + }) +}); diff --git a/e2e/test/jasmine-ts-node/spec/helpers/1-register-ts-node.js b/e2e/test/jasmine-ts-node/spec/helpers/1-register-ts-node.js new file mode 100644 index 0000000000..15ff12baa3 --- /dev/null +++ b/e2e/test/jasmine-ts-node/spec/helpers/1-register-ts-node.js @@ -0,0 +1,3 @@ +require('ts-node').register({ + transpileOnly: true +}); diff --git a/e2e/test/jasmine-ts-node/spec/helpers/CustomMatchers.ts b/e2e/test/jasmine-ts-node/spec/helpers/CustomMatchers.ts new file mode 100644 index 0000000000..77e339ea54 --- /dev/null +++ b/e2e/test/jasmine-ts-node/spec/helpers/CustomMatchers.ts @@ -0,0 +1,5 @@ +declare module jasmine { + interface Matchers { + toBePlaying(song: import('../../src/Song').Song): boolean; + } +} diff --git a/e2e/test/jasmine-ts-node/spec/helpers/IsCurrentlyPlayingMatcher.ts b/e2e/test/jasmine-ts-node/spec/helpers/IsCurrentlyPlayingMatcher.ts new file mode 100644 index 0000000000..755db1818f --- /dev/null +++ b/e2e/test/jasmine-ts-node/spec/helpers/IsCurrentlyPlayingMatcher.ts @@ -0,0 +1,20 @@ +import { Player } from "../../src/Player"; +import { Song } from "../../src/Song"; + +beforeEach(function () { + jasmine.addMatchers({ + toBePlaying: function () { + return { + compare: function (actual: Player, expected: Song) { + var player = actual; + + return { + pass: player.currentlyPlayingSong === expected && player.isPlaying + } + } + }; + } + }); +}); + + diff --git a/e2e/test/jasmine-ts-node/spec/support/jasmine.json b/e2e/test/jasmine-ts-node/spec/support/jasmine.json new file mode 100644 index 0000000000..a01449f719 --- /dev/null +++ b/e2e/test/jasmine-ts-node/spec/support/jasmine.json @@ -0,0 +1,11 @@ +{ + "spec_dir": "spec", + "spec_files": [ + "**/*[sS]pec.[jt]s" + ], + "helpers": [ + "helpers/**/*.[jt]s" + ], + "stopSpecOnExpectationFailure": false, + "random": true +} diff --git a/e2e/test/jasmine-ts-node/src/Player.ts b/e2e/test/jasmine-ts-node/src/Player.ts new file mode 100644 index 0000000000..0030bbdace --- /dev/null +++ b/e2e/test/jasmine-ts-node/src/Player.ts @@ -0,0 +1,26 @@ +import { Song } from "./Song"; + +export class Player { + public currentlyPlayingSong: Song; + public isPlaying: boolean; + + play(song: Song) { + this.currentlyPlayingSong = song; + this.isPlaying = true; + } + + pause() { + this.isPlaying = false; + } + + resume() { + if (this.isPlaying) { + throw new Error('song is already playing'); + } + this.isPlaying = true; + } + + makeFavorite() { + this.currentlyPlayingSong.persistFavoriteStatus(true); + } +} diff --git a/e2e/test/jasmine-ts-node/src/Song.ts b/e2e/test/jasmine-ts-node/src/Song.ts new file mode 100644 index 0000000000..c8dd25e1b7 --- /dev/null +++ b/e2e/test/jasmine-ts-node/src/Song.ts @@ -0,0 +1,5 @@ +export class Song { + persistFavoriteStatus(value: boolean) { + throw new Error('not yet implemented'); + } +} diff --git a/e2e/test/jasmine-ts-node/src/concat.ts b/e2e/test/jasmine-ts-node/src/concat.ts new file mode 100644 index 0000000000..6939b18d1f --- /dev/null +++ b/e2e/test/jasmine-ts-node/src/concat.ts @@ -0,0 +1,3 @@ +export function concat(a: string, b: string) { + return a + b; // Will be a compile error when mutated +} diff --git a/e2e/test/jasmine-ts-node/stryker.conf.json b/e2e/test/jasmine-ts-node/stryker.conf.json new file mode 100644 index 0000000000..d3a1cbb358 --- /dev/null +++ b/e2e/test/jasmine-ts-node/stryker.conf.json @@ -0,0 +1,19 @@ +{ + "$schema": "../../node_modules/@stryker-mutator/core/schema/stryker-schema.json", + "checkers": [ + "typescript" + ], + "testRunner": "jasmine", + "concurrency": 2, + "coverageAnalysis": "perTest", + "reporters": [ + "event-recorder", + "clear-text" + ], + "appendPlugins": [ + "@stryker-mutator/typescript-checker" + ], + "plugins": [ + "@stryker-mutator/jasmine-runner" + ] +} diff --git a/e2e/test/jasmine-ts-node/tsconfig.json b/e2e/test/jasmine-ts-node/tsconfig.json new file mode 100644 index 0000000000..cdcbe26312 --- /dev/null +++ b/e2e/test/jasmine-ts-node/tsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "lib": ["ES2017"], + "module": "CommonJS", + "target": "ES2017", + "types": ["jasmine"] + }, + "include": ["src", "spec"] +} diff --git a/e2e/test/jasmine-ts-node/verify/verify.ts b/e2e/test/jasmine-ts-node/verify/verify.ts new file mode 100644 index 0000000000..55c04b0826 --- /dev/null +++ b/e2e/test/jasmine-ts-node/verify/verify.ts @@ -0,0 +1,17 @@ +import { expectMetrics } from '../../../helpers'; + +describe('Verify stryker has ran correctly', () => { + + it('should report correct score', async () => { + await expectMetrics({ + ignored: 0, + killed: 12, + mutationScore: 85.71, + noCoverage: 2, + survived: 0, + timeout: 0, + runtimeErrors: 0, + compileErrors: 2 + }); + }); +}); diff --git a/e2e/test/jest-node/package.json b/e2e/test/jest-node/package.json index 35ecff6786..3519bcb7b8 100644 --- a/e2e/test/jest-node/package.json +++ b/e2e/test/jest-node/package.json @@ -4,6 +4,6 @@ "scripts": { "test:unit": "jest", "test": "stryker run", - "posttest": "mocha --require ts-node/register verify/*.ts" + "posttest": "mocha --require \"../../tasks/ts-node-register.js\" verify/*.ts" } } diff --git a/e2e/test/jest-node/stryker.conf.json b/e2e/test/jest-node/stryker.conf.json index df8eb7ee6f..e2500aff77 100644 --- a/e2e/test/jest-node/stryker.conf.json +++ b/e2e/test/jest-node/stryker.conf.json @@ -1,11 +1,9 @@ { - "$schema": "https://raw.githubusercontent.com/stryker-mutator/stryker/master/packages/api/schema/stryker-core.json", - "mutator": "javascript", + "$schema": "../../node_modules/@stryker-mutator/core/schema/stryker-schema.json", "packageManager": "npm", "testRunner": "jest", "tempDirName": "stryker-tmp", - "transpilers": [], - "maxConcurrentTestRunners": 2, + "concurrency": 1, "coverageAnalysis": "off", "reporters": [ "clear-text", diff --git a/e2e/test/jest-react-enyme-ts/.gitignore b/e2e/test/jest-react-enyme-ts/.gitignore new file mode 100644 index 0000000000..3c3629e647 --- /dev/null +++ b/e2e/test/jest-react-enyme-ts/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/e2e/test/jest-react-enyme-ts/jest.config.js b/e2e/test/jest-react-enyme-ts/jest.config.js new file mode 100644 index 0000000000..04d92306bb --- /dev/null +++ b/e2e/test/jest-react-enyme-ts/jest.config.js @@ -0,0 +1,6 @@ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node', + setupFilesAfterEnv: ['./setupEnzyme.ts'], + snapshotSerializers: ["enzyme-to-json/serializer"] +}; diff --git a/e2e/test/jest-react-enyme-ts/package-lock.json b/e2e/test/jest-react-enyme-ts/package-lock.json new file mode 100644 index 0000000000..8788cf4b98 --- /dev/null +++ b/e2e/test/jest-react-enyme-ts/package-lock.json @@ -0,0 +1,1455 @@ +{ + "name": "jest-react-enzyme-ts", + "version": "0.1.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@jest/types": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^13.0.0" + } + }, + "@types/cheerio": { + "version": "0.22.21", + "resolved": "https://registry.npmjs.org/@types/cheerio/-/cheerio-0.22.21.tgz", + "integrity": "sha512-aGI3DfswwqgKPiEOTaiHV2ZPC9KEhprpgEbJnv0fZl3SGX0cGgEva1126dGrMC6AJM6v/aihlUgJn9M5DbDZ/Q==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "dev": true + }, + "@types/enzyme": { + "version": "3.10.5", + "resolved": "https://registry.npmjs.org/@types/enzyme/-/enzyme-3.10.5.tgz", + "integrity": "sha512-R+phe509UuUYy9Tk0YlSbipRpfVtIzb/9BHn5pTEtjJTF5LXvUjrIQcZvNyANNEyFrd2YGs196PniNT1fgvOQA==", + "dev": true, + "requires": { + "@types/cheerio": "*", + "@types/react": "*" + } + }, + "@types/enzyme-adapter-react-16": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.0.6.tgz", + "integrity": "sha512-VonDkZ15jzqDWL8mPFIQnnLtjwebuL9YnDkqeCDYnB4IVgwUm0mwKkqhrxLL6mb05xm7qqa3IE95m8CZE9imCg==", + "dev": true, + "requires": { + "@types/enzyme": "*" + } + }, + "@types/istanbul-lib-coverage": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", + "integrity": "sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==", + "dev": true + }, + "@types/istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*" + } + }, + "@types/istanbul-reports": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz", + "integrity": "sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "*", + "@types/istanbul-lib-report": "*" + } + }, + "@types/jest": { + "version": "24.9.1", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.9.1.tgz", + "integrity": "sha512-Fb38HkXSVA4L8fGKEZ6le5bB8r6MRWlOCZbVuWZcmOMSCd2wCYOwN1ibj8daIoV9naq7aaOZjrLCoCMptKU/4Q==", + "dev": true, + "requires": { + "jest-diff": "^24.3.0" + } + }, + "@types/node": { + "version": "12.12.38", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.38.tgz", + "integrity": "sha512-75eLjX0pFuTcUXnnWmALMzzkYorjND0ezNEycaKesbUBg9eGZp4GHPuDmkRc4mQQvIpe29zrzATNRA6hkYqwmA==" + }, + "@types/prop-types": { + "version": "15.7.3", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", + "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==" + }, + "@types/react": { + "version": "16.9.45", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.45.tgz", + "integrity": "sha512-vv950slTF5UZ5eDOf13b8qC1SD4rTvkqg3HfaUKzr17U97oeJZAa+dUaIHn0QoOJflNTIt6Pem9MmapULs9dkA==", + "requires": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + }, + "dependencies": { + "csstype": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.2.tgz", + "integrity": "sha512-ofovWglpqoqbfLNOTBNZLSbMuGrblAf1efvvArGKOZMBrIoJeu5UsAipQolkijtyQx5MtAzT/J9IHj/CEY1mJw==" + } + } + }, + "@types/react-dom": { + "version": "16.9.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.7.tgz", + "integrity": "sha512-GHTYhM8/OwUCf254WO5xqR/aqD3gC9kSTLpopWGpQLpnw23jk44RvMHsyUSEplvRJZdHxhJGMMLF0kCPYHPhQA==", + "requires": { + "@types/react": "*" + } + }, + "@types/yargs": { + "version": "13.0.8", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.8.tgz", + "integrity": "sha512-XAvHLwG7UQ+8M4caKIH0ZozIOYay5fQkAgyIXegXT9jPtdIGdhga+sUEdAr1CiG46aB+c64xQEYyEzlwWVTNzA==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-15.0.0.tgz", + "integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==", + "dev": true + }, + "airbnb-prop-types": { + "version": "2.16.0", + "resolved": "https://registry.npmjs.org/airbnb-prop-types/-/airbnb-prop-types-2.16.0.tgz", + "integrity": "sha512-7WHOFolP/6cS96PhKNrslCLMYAI8yB1Pp6u6XmxozQOiZbsI5ycglZr5cHhBFfuRcQQjzCMith5ZPZdYiJCxUg==", + "dev": true, + "requires": { + "array.prototype.find": "^2.1.1", + "function.prototype.name": "^1.1.2", + "is-regex": "^1.1.0", + "object-is": "^1.1.2", + "object.assign": "^4.1.0", + "object.entries": "^1.1.2", + "prop-types": "^15.7.2", + "prop-types-exact": "^1.2.0", + "react-is": "^16.13.1" + }, + "dependencies": { + "is-regex": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.1" + } + }, + "object.entries": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.2.tgz", + "integrity": "sha512-BQdB9qKmb/HyNdMNWVr7O3+z5MUIx3aiegEIJqjMBbBf0YT9RRxTJSim4mzFqtyr7PDAHigq0N9dO0m0tRakQA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5", + "has": "^1.0.3" + } + } + } + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "array-filter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz", + "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=", + "dev": true + }, + "array.prototype.find": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.1.1.tgz", + "integrity": "sha512-mi+MYNJYLTx2eNYy+Yh6raoQacCsNeeMUaspFPh9Y141lFSsWxxB8V9mM2ye+eqiRs917J6/pJ4M9ZPzenWckA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.4" + } + }, + "array.prototype.flat": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz", + "integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "bs-logger": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz", + "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==", + "dev": true, + "requires": { + "fast-json-stable-stringify": "2.x" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "cheerio": { + "version": "1.0.0-rc.3", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.3.tgz", + "integrity": "sha512-0td5ijfUPuubwLUu0OBoe98gZj8C/AA+RW3v67GPlGOrvxWjZmBXiBCRU+I8VEiNyJzjth40POfHiz2RB3gImA==", + "dev": true, + "requires": { + "css-select": "~1.2.0", + "dom-serializer": "~0.1.1", + "entities": "~1.1.1", + "htmlparser2": "^3.9.1", + "lodash": "^4.15.0", + "parse5": "^3.0.1" + }, + "dependencies": { + "css-select": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", + "integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=", + "dev": true, + "requires": { + "boolbase": "~1.0.0", + "css-what": "2.1", + "domutils": "1.5.1", + "nth-check": "~1.0.1" + } + }, + "css-what": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", + "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==", + "dev": true + }, + "dom-serializer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", + "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", + "dev": true, + "requires": { + "domelementtype": "^1.3.0", + "entities": "^1.1.1" + } + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", + "dev": true + }, + "parse5": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", + "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", + "dev": true, + "requires": { + "@types/node": "*" + } + } + } + }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "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" + } + }, + "diff-sequences": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", + "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==", + "dev": true + }, + "discontinuous-range": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", + "integrity": "sha1-44Mx8IRLukm5qctxx3FYWqsbxlo=", + "dev": true + }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", + "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==", + "dev": true + } + } + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "domhandler": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", + "dev": true, + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "entities": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz", + "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==", + "dev": true + }, + "enzyme": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.11.0.tgz", + "integrity": "sha512-Dw8/Gs4vRjxY6/6i9wU0V+utmQO9kvh9XLnz3LIudviOnVYDEe2ec+0k+NQoMamn1VrjKgCUOWj5jG/5M5M0Qw==", + "dev": true, + "requires": { + "array.prototype.flat": "^1.2.3", + "cheerio": "^1.0.0-rc.3", + "enzyme-shallow-equal": "^1.0.1", + "function.prototype.name": "^1.1.2", + "has": "^1.0.3", + "html-element-map": "^1.2.0", + "is-boolean-object": "^1.0.1", + "is-callable": "^1.1.5", + "is-number-object": "^1.0.4", + "is-regex": "^1.0.5", + "is-string": "^1.0.5", + "is-subset": "^0.1.1", + "lodash.escape": "^4.0.1", + "lodash.isequal": "^4.5.0", + "object-inspect": "^1.7.0", + "object-is": "^1.0.2", + "object.assign": "^4.1.0", + "object.entries": "^1.1.1", + "object.values": "^1.1.1", + "raf": "^3.4.1", + "rst-selector-parser": "^2.2.3", + "string.prototype.trim": "^1.2.1" + } + }, + "enzyme-adapter-react-16": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/enzyme-adapter-react-16/-/enzyme-adapter-react-16-1.15.3.tgz", + "integrity": "sha512-98rqNI4n9HZslWIPuuwy4hK1bxRuMy+XX0CU1dS8iUqcgisTxeBaap6oPp2r4MWC8OphCbbqAT8EU/xHz3zIaQ==", + "dev": true, + "requires": { + "enzyme-adapter-utils": "^1.13.1", + "enzyme-shallow-equal": "^1.0.4", + "has": "^1.0.3", + "object.assign": "^4.1.0", + "object.values": "^1.1.1", + "prop-types": "^15.7.2", + "react-is": "^16.13.1", + "react-test-renderer": "^16.0.0-0", + "semver": "^5.7.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "enzyme-adapter-utils": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/enzyme-adapter-utils/-/enzyme-adapter-utils-1.13.1.tgz", + "integrity": "sha512-5A9MXXgmh/Tkvee3bL/9RCAAgleHqFnsurTYCbymecO4ohvtNO5zqIhHxV370t7nJAwaCfkgtffarKpC0GPt0g==", + "dev": true, + "requires": { + "airbnb-prop-types": "^2.16.0", + "function.prototype.name": "^1.1.2", + "object.assign": "^4.1.0", + "object.fromentries": "^2.0.2", + "prop-types": "^15.7.2", + "semver": "^5.7.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "enzyme-shallow-equal": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.4.tgz", + "integrity": "sha512-MttIwB8kKxypwHvRynuC3ahyNc+cFbR8mjVIltnmzQ0uKGqmsfO4bfBuLxb0beLNPhjblUEYvEbsg+VSygvF1Q==", + "dev": true, + "requires": { + "has": "^1.0.3", + "object-is": "^1.1.2" + } + }, + "enzyme-to-json": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/enzyme-to-json/-/enzyme-to-json-3.5.0.tgz", + "integrity": "sha512-clusXRsiaQhG7+wtyc4t7MU8N3zCOgf4eY9+CeSenYzKlFST4lxerfOvnWd4SNaToKhkuba+w6m242YpQOS7eA==", + "dev": true, + "requires": { + "lodash": "^4.17.15", + "react-is": "^16.12.0" + } + }, + "es-abstract": { + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", + "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", + "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.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" + } + }, + "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" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "function.prototype.name": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.2.tgz", + "integrity": "sha512-C8A+LlHBJjB2AdcRPorc5JvJ5VUoWlXdEHLOJdCI7kjHEtGTpHQUiqMvCIKUwIsGwZX2jZJy761AXsn356bJQg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "functions-have-names": "^1.2.0" + } + }, + "functions-have-names": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.1.tgz", + "integrity": "sha512-j48B/ZI7VKs3sgeI2cZp7WXWmZXu7Iq5pl5/vptV5N2mq+DGFuS/ulaDjtaoLpYzuD6u8UgrUKHfgo7fDTSiBA==", + "dev": true + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "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-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "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 + }, + "html-element-map": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/html-element-map/-/html-element-map-1.2.0.tgz", + "integrity": "sha512-0uXq8HsuG1v2TmQ8QkIhzbrqeskE4kn52Q18QJ9iAA/SnHoEKXWiUxHQtclRsCFWEUD2So34X+0+pZZu862nnw==", + "dev": true, + "requires": { + "array-filter": "^1.0.0" + } + }, + "htmlparser2": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "dev": true, + "requires": { + "domelementtype": "^1.3.1", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^3.1.1" + }, + "dependencies": { + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", + "dev": true + } + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-boolean-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.0.1.tgz", + "integrity": "sha512-TqZuVwa/sppcrhUCAYkGBk7w0yxfQQnxq28fjkO53tnK9FQXmdwz2JS5+GjsWQ6RByES1K40nI+yDic5c9/aAQ==", + "dev": true + }, + "is-callable": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "dev": true + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + } + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-number-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", + "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==", + "dev": true + }, + "is-regex": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==", + "dev": true + }, + "is-subset": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", + "integrity": "sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY=", + "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" + } + }, + "jest-diff": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", + "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", + "dev": true, + "requires": { + "chalk": "^2.0.1", + "diff-sequences": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" + } + }, + "jest-get-type": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", + "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", + "dev": true + }, + "jest-util": { + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.3.0.tgz", + "integrity": "sha512-4zpn6bwV0+AMFN0IYhH/wnzIQzRaYVrz1A8sYnRnj4UXDXbOVtWmlaZkO9mipFqZ13okIfN87aDoJWB7VH6hcw==", + "dev": true, + "requires": { + "@jest/types": "^26.3.0", + "@types/node": "*", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "is-ci": "^2.0.0", + "micromatch": "^4.0.2" + }, + "dependencies": { + "@jest/types": { + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.3.0.tgz", + "integrity": "sha512-BDPG23U0qDeAvU4f99haztXwdAg3hz4El95LkAM+tHAqqhiVzRpEGHHU8EDxT/AnxOrA65YjLBwDahdJ9pTLJQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + } + }, + "@types/istanbul-reports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz", + "integrity": "sha512-nwKNbvnwJ2/mndE9ItP/zc2TCzw6uuodnF4EHYWD+gCQDVBuRQL5UzbZD0/ezy1iKsFU2ZQiDqg4M9dN4+wZgA==", + "dev": true, + "requires": { + "@types/istanbul-lib-report": "*" + } + }, + "@types/yargs": { + "version": "15.0.5", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.5.tgz", + "integrity": "sha512-Dk/IDOPtOgubt/IaevIUbTgV7doaKkoorvOyYM2CMwuDyP89bekI7H4xLIwunNYiK9jhCkmc6pUrJk3cj2AB9w==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "json5": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "lodash.escape": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz", + "integrity": "sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg=", + "dev": true + }, + "lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", + "dev": true + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", + "dev": true + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "dev": true + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "moo": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", + "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==", + "dev": true + }, + "nearley": { + "version": "2.19.5", + "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.19.5.tgz", + "integrity": "sha512-qoh1ZXXl0Kpn40tFhmgvffUAlbpRMcjLUagNVnT1JmliUIsB4tFabmCNhD97+tkf9FZ/SLhhYzNow0V3GitzDg==", + "dev": true, + "requires": { + "commander": "^2.19.0", + "moo": "^0.5.0", + "railroad-diagrams": "^1.0.0", + "randexp": "0.4.6", + "semver": "^5.4.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "dev": true, + "requires": { + "boolbase": "~1.0.0" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "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.1.2", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.2.tgz", + "integrity": "sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "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.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.entries": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.1.tgz", + "integrity": "sha512-ilqR7BgdyZetJutmDPfXCDffGa0/Yzl2ivVNpbx/g4UeWrCdRnFDUBrKJGLhGieRHDATnyZXWBeCb29k9CJysQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "object.fromentries": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.2.tgz", + "integrity": "sha512-r3ZiBH7MQppDJVLx6fhD618GKNG40CZYH9wgwdhKxBDDbQgjeWGGd4AtkZad84d291YxvWe7bJGuE65Anh0dxQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "object.values": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", + "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true + }, + "pretty-format": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", + "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" + } + }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, + "prop-types-exact": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/prop-types-exact/-/prop-types-exact-1.2.0.tgz", + "integrity": "sha512-K+Tk3Kd9V0odiXFP9fwDHUYRyvK3Nun3GVyPapSIs5OBkITAm15W0CPFD/YKTkMUAbc0b9CUwRQp2ybiBIq+eA==", + "dev": true, + "requires": { + "has": "^1.0.3", + "object.assign": "^4.1.0", + "reflect.ownkeys": "^0.2.0" + } + }, + "raf": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", + "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", + "dev": true, + "requires": { + "performance-now": "^2.1.0" + } + }, + "railroad-diagrams": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", + "integrity": "sha1-635iZ1SN3t+4mcG5Dlc3RVnN234=", + "dev": true + }, + "randexp": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", + "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", + "dev": true, + "requires": { + "discontinuous-range": "1.0.0", + "ret": "~0.1.10" + } + }, + "react": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react/-/react-16.13.1.tgz", + "integrity": "sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2" + } + }, + "react-dom": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.13.1.tgz", + "integrity": "sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.19.1" + } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "react-test-renderer": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.13.1.tgz", + "integrity": "sha512-Sn2VRyOK2YJJldOqoh8Tn/lWQ+ZiKhyZTPtaO0Q6yNj+QDbmRkVFap6pZPy3YQk8DScRDfyqm/KxKYP9gCMRiQ==", + "dev": true, + "requires": { + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "react-is": "^16.8.6", + "scheduler": "^0.19.1" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "reflect.ownkeys": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/reflect.ownkeys/-/reflect.ownkeys-0.2.0.tgz", + "integrity": "sha1-dJrO7H8/34tj+SegSAnpDFwLNGA=", + "dev": true + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "rst-selector-parser": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz", + "integrity": "sha1-gbIw6i/MYGbInjRy3nlChdmwPZE=", + "dev": true, + "requires": { + "lodash.flattendeep": "^4.4.0", + "nearley": "^2.7.10" + } + }, + "scheduler": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", + "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1" + } + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + }, + "string.prototype.trim": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.1.tgz", + "integrity": "sha512-MjGFEeqixw47dAMFMtgUro/I0+wNqZB5GKXGt1fFr24u3TzDXCPu7J9Buppzoe3r/LqkSDLDDJzE15RGWDGAVw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1" + } + }, + "string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "string.prototype.trimleft": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz", + "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5", + "string.prototype.trimstart": "^1.0.0" + } + }, + "string.prototype.trimright": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz", + "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5", + "string.prototype.trimend": "^1.0.0" + } + }, + "string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", + "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "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" + }, + "dependencies": { + "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 + } + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "ts-jest": { + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.3.0.tgz", + "integrity": "sha512-Jq2uKfx6bPd9+JDpZNMBJMdMQUC3sJ08acISj8NXlVgR2d5OqslEHOR2KHMgwymu8h50+lKIm0m0xj/ioYdW2Q==", + "dev": true, + "requires": { + "@types/jest": "26.x", + "bs-logger": "0.x", + "buffer-from": "1.x", + "fast-json-stable-stringify": "2.x", + "jest-util": "26.x", + "json5": "2.x", + "lodash.memoize": "4.x", + "make-error": "1.x", + "mkdirp": "1.x", + "semver": "7.x", + "yargs-parser": "18.x" + }, + "dependencies": { + "@jest/types": { + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-25.5.0.tgz", + "integrity": "sha512-OXD0RgQ86Tu3MazKo8bnrkDRaDXXMGUqd+kTtLtK1Zb7CRzQcaSRPPPV37SvYTdevXEBVxe0HXylEjs8ibkmCw==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^15.0.0", + "chalk": "^3.0.0" + } + }, + "@types/jest": { + "version": "26.0.10", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.10.tgz", + "integrity": "sha512-i2m0oyh8w/Lum7wWK/YOZJakYF8Mx08UaKA1CtbmFeDquVhAEdA7znacsVSf2hJ1OQ/OfVMGN90pw/AtzF8s/Q==", + "dev": true, + "requires": { + "jest-diff": "^25.2.1", + "pretty-format": "^25.2.1" + } + }, + "@types/yargs": { + "version": "15.0.5", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.5.tgz", + "integrity": "sha512-Dk/IDOPtOgubt/IaevIUbTgV7doaKkoorvOyYM2CMwuDyP89bekI7H4xLIwunNYiK9jhCkmc6pUrJk3cj2AB9w==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "diff-sequences": { + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-25.2.6.tgz", + "integrity": "sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jest-diff": { + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-25.5.0.tgz", + "integrity": "sha512-z1kygetuPiREYdNIumRpAHY6RXiGmp70YHptjdaxTWGmA085W3iCnXNx0DhflK3vwrKmrRWyY1wUpkPMVxMK7A==", + "dev": true, + "requires": { + "chalk": "^3.0.0", + "diff-sequences": "^25.2.6", + "jest-get-type": "^25.2.6", + "pretty-format": "^25.5.0" + } + }, + "jest-get-type": { + "version": "25.2.6", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-25.2.6.tgz", + "integrity": "sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig==", + "dev": true + }, + "pretty-format": { + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-25.5.0.tgz", + "integrity": "sha512-kbo/kq2LQ/A/is0PQwsEHM7Ca6//bGPPvU6UnsdDRSKTWxT/ru/xb88v4BJf6a69H+uTytOEsTusT9ksd/1iWQ==", + "dev": true, + "requires": { + "@jest/types": "^25.5.0", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^16.12.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "typescript": { + "version": "3.9.7", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz", + "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } +} diff --git a/e2e/test/jest-react-enyme-ts/package.json b/e2e/test/jest-react-enyme-ts/package.json new file mode 100644 index 0000000000..cd05f5b00a --- /dev/null +++ b/e2e/test/jest-react-enyme-ts/package.json @@ -0,0 +1,49 @@ +{ + "name": "jest-react-enzyme-ts", + "description": "A test for jest with react-scripts and typescript", + "version": "0.1.0", + "private": true, + "scripts": { + "pretest": "rimraf \"reports\" \"stryker.log\"", + "test:unit": "jest src/*", + "test": "stryker run", + "posttest": "mocha --require ../../tasks/ts-node-register.js verify/*.ts" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + }, + "dependencies": { + "@types/node": "^12.0.0", + "@types/react-dom": "~16.9.0", + "react": "~16.13.1", + "react-dom": "~16.13.1" + }, + "devDependencies": { + "@types/enzyme": "~3.10.5", + "@types/enzyme-adapter-react-16": "~1.0.6", + "@types/jest": "~24.9.1", + "@types/react": "~16.9.34", + "enzyme": "~3.11.0", + "enzyme-adapter-react-16": "~1.15.3", + "enzyme-to-json": "~3.5.0", + "ts-jest": "~26.3.0", + "typescript": "~3.9.7" + }, + "localDependencies": { + "@stryker-mutator/api": "../../../packages/api", + "@stryker-mutator/core": "../../../packages/core", + "@stryker-mutator/instrumenter": "../../../packages/instrumenter", + "@stryker-mutator/typescript-checker": "../../../packages/typescript-checker", + "@stryker-mutator/jest-runner": "../../../packages/jest-runner", + "@stryker-mutator/util": "../../../packages/util" + } +} diff --git a/e2e/test/jest-react-enyme-ts/setupEnzyme.ts b/e2e/test/jest-react-enyme-ts/setupEnzyme.ts new file mode 100644 index 0000000000..d78568c6c4 --- /dev/null +++ b/e2e/test/jest-react-enyme-ts/setupEnzyme.ts @@ -0,0 +1,6 @@ +// @ts-ignore +import Enzyme from 'enzyme'; +// @ts-ignore +import Adapter from 'enzyme-adapter-react-16'; + +Enzyme.configure({ adapter: new Adapter() }); diff --git a/e2e/test/jest-react-enyme-ts/src/ChildComponent.spec.tsx b/e2e/test/jest-react-enyme-ts/src/ChildComponent.spec.tsx new file mode 100644 index 0000000000..e3ca5f0101 --- /dev/null +++ b/e2e/test/jest-react-enyme-ts/src/ChildComponent.spec.tsx @@ -0,0 +1,9 @@ +import React from 'react'; +import { shallow } from 'enzyme'; +import ChildComponent from './ChildComponent'; + +describe('Child Component', () => { + it('should render correctly', () => { + expect(shallow()).toMatchSnapshot(); + }); +}); diff --git a/e2e/test/jest-react-enyme-ts/src/ChildComponent.tsx b/e2e/test/jest-react-enyme-ts/src/ChildComponent.tsx new file mode 100644 index 0000000000..45666580d1 --- /dev/null +++ b/e2e/test/jest-react-enyme-ts/src/ChildComponent.tsx @@ -0,0 +1,5 @@ +import React from 'react'; + +const ChildComponent = ({ text }: { text: string }) =>
{text}
; + +export default ChildComponent; diff --git a/e2e/test/jest-react-enyme-ts/src/ParentComponent.spec.tsx b/e2e/test/jest-react-enyme-ts/src/ParentComponent.spec.tsx new file mode 100644 index 0000000000..11b1b9ef1f --- /dev/null +++ b/e2e/test/jest-react-enyme-ts/src/ParentComponent.spec.tsx @@ -0,0 +1,9 @@ +import React from 'react'; +import { shallow } from 'enzyme'; +import ParentComponent from './ParentComponent'; + +describe('Parent Component', () => { + it('should render correctly', () => { + expect(shallow()).toMatchSnapshot(); + }) +}) diff --git a/e2e/test/jest-react-enyme-ts/src/ParentComponent.tsx b/e2e/test/jest-react-enyme-ts/src/ParentComponent.tsx new file mode 100644 index 0000000000..fa63dd3dce --- /dev/null +++ b/e2e/test/jest-react-enyme-ts/src/ParentComponent.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import ChildComponent from './ChildComponent'; + +const ParentComponent = () =>
+ This is a parent component + + +
+ +export default ParentComponent; diff --git a/e2e/test/jest-react-enyme-ts/src/__snapshots__/ChildComponent.spec.tsx.snap b/e2e/test/jest-react-enyme-ts/src/__snapshots__/ChildComponent.spec.tsx.snap new file mode 100644 index 0000000000..e3dd9e8ccf --- /dev/null +++ b/e2e/test/jest-react-enyme-ts/src/__snapshots__/ChildComponent.spec.tsx.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Child Component should render correctly 1`] = ` +
+ text +
+`; diff --git a/e2e/test/jest-react-enyme-ts/src/__snapshots__/ParentComponent.spec.tsx.snap b/e2e/test/jest-react-enyme-ts/src/__snapshots__/ParentComponent.spec.tsx.snap new file mode 100644 index 0000000000..a599cd52a3 --- /dev/null +++ b/e2e/test/jest-react-enyme-ts/src/__snapshots__/ParentComponent.spec.tsx.snap @@ -0,0 +1,10 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Parent Component should render correctly 1`] = ` +
+ This is a parent component + +
+`; diff --git a/e2e/test/jest-react-enyme-ts/stryker.conf.json b/e2e/test/jest-react-enyme-ts/stryker.conf.json new file mode 100644 index 0000000000..1ba1dc735e --- /dev/null +++ b/e2e/test/jest-react-enyme-ts/stryker.conf.json @@ -0,0 +1,18 @@ +{ + "$schema": "../../node_modules/@stryker-mutator/core/schema/stryker-schema.json", + "packageManager": "npm", + "testRunner": "jest", + "tempDirName": "stryker-tmp", + "concurrency": 2, + "coverageAnalysis": "off", + "reporters": [ + "event-recorder", + "progress", + "clear-text", + "html" + ], + "jest": { + "projectType": "custom", + "configFile": "./jest.config.js" + } +} diff --git a/e2e/test/jest-react-enyme-ts/tsconfig.json b/e2e/test/jest-react-enyme-ts/tsconfig.json new file mode 100644 index 0000000000..120c551532 --- /dev/null +++ b/e2e/test/jest-react-enyme-ts/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ES2019", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "module": "esnext", + "moduleResolution": "classic", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "types": ["@testing-library/jest-dom", "jest"], + "typeRoots": ["node_modules/@types"], + "jsx": "react" + }, + "include": ["src"] +} diff --git a/e2e/test/jest-react-enyme-ts/verify/verify.ts b/e2e/test/jest-react-enyme-ts/verify/verify.ts new file mode 100644 index 0000000000..6f4eeffc57 --- /dev/null +++ b/e2e/test/jest-react-enyme-ts/verify/verify.ts @@ -0,0 +1,13 @@ +import { expectMetrics } from '../../../helpers'; + +describe('After running stryker on jest-react-enzyme-ts project', () => { + it('should report expected scores', async () => { + await expectMetrics({ + killed: 2, + survived: 0, + timeout: 0, + compileErrors: 0, + ignored: 0 + }); + }); +}); diff --git a/e2e/test/jest-react-ts/b.js b/e2e/test/jest-react-ts/b.js deleted file mode 100644 index 0b2cddd0ed..0000000000 --- a/e2e/test/jest-react-ts/b.js +++ /dev/null @@ -1,4 +0,0 @@ -const m = require('mutation-testing-metrics'); -const r =require ('./reports/mutation/events/00141-onMutationTestReportReady.json') -const s = m.calculateMetrics(r.files); -console.log(s); diff --git a/e2e/test/jest-react-ts/package-lock.json b/e2e/test/jest-react-ts/package-lock.json index 2ab6b72566..d18dd8f228 100644 --- a/e2e/test/jest-react-ts/package-lock.json +++ b/e2e/test/jest-react-ts/package-lock.json @@ -1575,9 +1575,9 @@ } }, "@types/yargs": { - "version": "15.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.4.tgz", - "integrity": "sha512-9T1auFmbPZoxHz0enUFlUuKRy3it01R+hlggyVUMtnCTQRunsQYifnSGb8hET4Xo8yiC0o0r1paW3ud5+rbURg==", + "version": "15.0.5", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.5.tgz", + "integrity": "sha512-Dk/IDOPtOgubt/IaevIUbTgV7doaKkoorvOyYM2CMwuDyP89bekI7H4xLIwunNYiK9jhCkmc6pUrJk3cj2AB9w==", "requires": { "@types/yargs-parser": "*" } @@ -1635,9 +1635,9 @@ } }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "requires": { "has-flag": "^4.0.0" } @@ -1661,13 +1661,13 @@ } }, "@testing-library/react": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-9.5.0.tgz", - "integrity": "sha512-di1b+D0p+rfeboHO5W7gTVeZDIK5+maEgstrZbWZSSvxDyfDRkkyBE1AJR5Psd6doNldluXlCWqXriUfqu/9Qg==", + "version": "9.3.3", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-9.3.3.tgz", + "integrity": "sha512-IuoiJR/NAzu9EuT3Fqs92sRHe/9egCipar92wTnXe3fMloWy0Q7JdAXaszzbv2ogH30ztb6Axp5XW63vOTd4jA==", "requires": { - "@babel/runtime": "^7.8.4", - "@testing-library/dom": "^6.15.0", - "@types/testing-library__react": "^9.1.2" + "@babel/runtime": "^7.6.0", + "@testing-library/dom": "^6.3.0", + "@types/testing-library__react": "^9.1.0" } }, "@types/babel__core": { @@ -1860,9 +1860,9 @@ } }, "@types/yargs": { - "version": "15.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.4.tgz", - "integrity": "sha512-9T1auFmbPZoxHz0enUFlUuKRy3it01R+hlggyVUMtnCTQRunsQYifnSGb8hET4Xo8yiC0o0r1paW3ud5+rbURg==", + "version": "15.0.5", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.5.tgz", + "integrity": "sha512-Dk/IDOPtOgubt/IaevIUbTgV7doaKkoorvOyYM2CMwuDyP89bekI7H4xLIwunNYiK9jhCkmc6pUrJk3cj2AB9w==", "requires": { "@types/yargs-parser": "*" } @@ -1920,9 +1920,9 @@ } }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "requires": { "has-flag": "^4.0.0" } @@ -2345,12 +2345,31 @@ } }, "aria-query": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.0.2.tgz", - "integrity": "sha512-S1G1V790fTaigUSM/Gd0NngzEfiMy9uTUfMyHhKhVyy4cH5O/eTuR01ydhGL0z4Za1PXFTRGH3qL8VhUQuEO5w==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-4.2.2.tgz", + "integrity": "sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==", "requires": { - "@babel/runtime": "^7.7.4", - "@babel/runtime-corejs3": "^7.7.4" + "@babel/runtime": "^7.10.2", + "@babel/runtime-corejs3": "^7.10.2" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.11.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz", + "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/runtime-corejs3": { + "version": "7.11.2", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.11.2.tgz", + "integrity": "sha512-qh5IR+8VgFz83VBa6OkaET6uN/mJOhHONuy3m1sgF0CV6mXdPSEBdA7e1eUbVvyNtANjMbg22JUv71BaDXLY6A==", + "requires": { + "core-js-pure": "^3.0.0", + "regenerator-runtime": "^0.13.4" + } + } } }, "arity-n": { diff --git a/e2e/test/jest-react-ts/package.json b/e2e/test/jest-react-ts/package.json index 29d4f6caf1..7ae6f9d828 100644 --- a/e2e/test/jest-react-ts/package.json +++ b/e2e/test/jest-react-ts/package.json @@ -3,22 +3,6 @@ "description": "A test for jest with react-scripts and typescript", "version": "0.1.0", "private": true, - "dependencies": { - "@emotion/core": "^10.0.28", - "@emotion/styled": "^10.0.27", - "@laststance/use-app-state": "^1.2.5", - "@reach/router": "^1.3.3", - "@testing-library/jest-dom": "^4.2.4", - "@testing-library/react": "^9.3.2", - "@types/jest": "^24.0.0", - "@types/node": "^12.0.0", - "@types/react": "^16.9.0", - "@types/react-dom": "^16.9.0", - "react": "^16.13.1", - "react-dom": "^16.13.1", - "react-scripts": "3.4.1", - "typescript": "~3.7.2" - }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", @@ -42,13 +26,30 @@ "last 1 safari version" ] }, + "dependencies": { + "@emotion/core": "~10.0.28", + "@emotion/styled": "~10.0.27", + "@laststance/use-app-state": "~1.2.5", + "@reach/router": "~1.3.3", + "@testing-library/jest-dom": "~4.2.4", + "@testing-library/react": "~9.3.2", + "@types/jest": "~24.9.1", + "@types/node": "^12.0.0", + "@types/react": "~16.9.0", + "@types/react-dom": "~16.9.0", + "react": "~16.13.1", + "react-dom": "~16.13.1", + "react-scripts": "~3.4.1", + "typescript": "~3.7.2" + }, "devDependencies": { - "@types/reach__router": "^1.3.5" + "@types/reach__router": "~1.3.5" }, "localDependencies": { "@stryker-mutator/api": "../../../packages/api", "@stryker-mutator/core": "../../../packages/core", - "@stryker-mutator/typescript": "../../../packages/typescript", + "@stryker-mutator/instrumenter": "../../../packages/instrumenter", + "@stryker-mutator/typescript-checker": "../../../packages/typescript-checker", "@stryker-mutator/jest-runner": "../../../packages/jest-runner", "@stryker-mutator/util": "../../../packages/util" } diff --git a/e2e/test/jest-react-ts/stryker.conf.json b/e2e/test/jest-react-ts/stryker.conf.json index cbf04fa235..46c40cbaba 100644 --- a/e2e/test/jest-react-ts/stryker.conf.json +++ b/e2e/test/jest-react-ts/stryker.conf.json @@ -1,6 +1,5 @@ { - "$schema": "https://raw.githubusercontent.com/stryker-mutator/stryker/master/packages/api/schema/stryker-core.json", - "mutator": "typescript", + "$schema": "../../node_modules/@stryker-mutator/core/schema/stryker-schema.json", "packageManager": "npm", "testRunner": "jest", "tempDirName": "stryker-tmp", @@ -8,10 +7,13 @@ "src/App/TodoList/Item/index.tsx", "src/NotFound.tsx" ], - "maxConcurrentTestRunners": 2, + "concurrency": 2, "coverageAnalysis": "off", "reporters": [ - "event-recorder" + "event-recorder", + "progress", + "clear-text", + "html" ], "jest": { "projectType": "create-react-app" diff --git a/e2e/test/jest-react-ts/verify/verify.ts b/e2e/test/jest-react-ts/verify/verify.ts index c6d4a7bace..91a01a8a9a 100644 --- a/e2e/test/jest-react-ts/verify/verify.ts +++ b/e2e/test/jest-react-ts/verify/verify.ts @@ -1,11 +1,11 @@ import { expectMetrics } from '../../../helpers'; -describe('After running stryker on jest-react project', () => { +describe('After running stryker on jest-react-ts project', () => { it('should report expected scores', async () => { await expectMetrics({ - survived: 45, - killed: 46, - timeout: 5, + survived: 53, + killed: 53, + timeout: 6, noCoverage: 0 }); }); diff --git a/e2e/test/jest-react/.babelrc b/e2e/test/jest-react/.babelrc index 3fed1fce7a..cd1339d754 100644 --- a/e2e/test/jest-react/.babelrc +++ b/e2e/test/jest-react/.babelrc @@ -1,20 +1,48 @@ { "presets": [ - ["es2015", {"modules": false}], - "react" + [ + "@babel/env", + { + "loose": true, + "shippedProposals": true, + "modules": "commonjs", + "targets": { + "ie": 9 + } + } + ], + "@babel/react" ], "plugins": [ - "transform-object-rest-spread" + "@babel/plugin-proposal-export-default-from", + "@babel/plugin-proposal-export-namespace-from", + "@babel/plugin-transform-runtime", + "@babel/plugin-proposal-object-rest-spread" ], "env": { - "lib-dir": { - "plugins": ["transform-es2015-modules-commonjs"] - }, - "webpack": { - "plugins": ["transform-es2015-modules-commonjs"] - }, - "test": { - "plugins": ["transform-es2015-modules-commonjs"] + "esm-dir": { + "presets": [ + [ + "@babel/env", + { + "loose": true, + "shippedProposals": true, + "modules": false, + "targets": { + "ie": 9 + } + } + ], + "@babel/react" + ], + "plugins": [ + [ + "@babel/plugin-transform-runtime", + { + "useESModules": true + } + ] + ] } } -} +} \ No newline at end of file diff --git a/e2e/test/jest-react/package-lock.json b/e2e/test/jest-react/package-lock.json index 8b718b7ddb..39fb6a8b3a 100644 --- a/e2e/test/jest-react/package-lock.json +++ b/e2e/test/jest-react/package-lock.json @@ -4,37 +4,98 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/cli": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.10.5.tgz", + "integrity": "sha512-j9H9qSf3kLdM0Ao3aGPbGZ73mEA9XazuupcS6cDGWuiyAcANoguhP0r2Lx32H5JGw4sSSoHG3x/mxVnHgvOoyA==", + "dev": true, + "requires": { + "chokidar": "^2.1.8", + "commander": "^4.0.1", + "convert-source-map": "^1.1.0", + "fs-readdir-recursive": "^1.1.0", + "glob": "^7.0.0", + "lodash": "^4.17.19", + "make-dir": "^2.1.0", + "slash": "^2.0.0", + "source-map": "^0.5.0" + }, + "dependencies": { + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true + }, + "lodash": { + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", + "dev": true + } + } + }, "@babel/code-frame": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", - "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/compat-data": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.11.0.tgz", + "integrity": "sha512-TPSvJfv73ng0pfnEOh17bYMPQbI95+nGWc71Ss4vZdRBHTDqmM9Z8ZV4rYz8Ks7sfzc95n30k6ODIq5UGnXcYQ==", "dev": true, "requires": { - "@babel/highlight": "^7.8.3" + "browserslist": "^4.12.0", + "invariant": "^2.2.4", + "semver": "^5.5.0" } }, "@babel/core": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.6.0.tgz", - "integrity": "sha512-FuRhDRtsd6IptKpHXAa+4WPZYY2ZzgowkbLBecEDDSje1X/apG7jQM33or3NdOmjXBKWGOg4JmSiRfUfuTtHXw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.6.0", - "@babel/helpers": "^7.6.0", - "@babel/parser": "^7.6.0", - "@babel/template": "^7.6.0", - "@babel/traverse": "^7.6.0", - "@babel/types": "^7.6.0", - "convert-source-map": "^1.1.0", + "version": "7.11.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.4.tgz", + "integrity": "sha512-5deljj5HlqRXN+5oJTY7Zs37iH3z3b++KjiKtIsJy1NrjOOVSEaJHEetLBhyu0aQOSNNZ/0IuEAan9GzRuDXHg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.11.4", + "@babel/helper-module-transforms": "^7.11.0", + "@babel/helpers": "^7.10.4", + "@babel/parser": "^7.11.4", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.11.0", + "@babel/types": "^7.11.0", + "convert-source-map": "^1.7.0", "debug": "^4.1.0", - "json5": "^2.1.0", - "lodash": "^4.17.13", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.19", "resolve": "^1.3.2", "semver": "^5.4.1", "source-map": "^0.5.0" }, "dependencies": { + "@babel/generator": { + "version": "7.11.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.4.tgz", + "integrity": "sha512-Rn26vueFx0eOoz7iifCN2UHT6rGtnkSGWSoDRIy8jZN3B91PzeSULbswfLoOWuTuAcNwpG/mxy+uCTDnZ9Mp1g==", + "dev": true, + "requires": { + "@babel/types": "^7.11.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/parser": { + "version": "7.11.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.4.tgz", + "integrity": "sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA==", + "dev": true + }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -44,6 +105,12 @@ "ms": "^2.1.1" } }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -53,14 +120,13 @@ } }, "@babel/generator": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.8.4.tgz", - "integrity": "sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.0.tgz", + "integrity": "sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ==", "dev": true, "requires": { - "@babel/types": "^7.8.3", + "@babel/types": "^7.11.0", "jsesc": "^2.5.1", - "lodash": "^4.17.13", "source-map": "^0.5.0" }, "dependencies": { @@ -73,287 +139,302 @@ } }, "@babel/helper-annotate-as-pure": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz", - "integrity": "sha512-6o+mJrZBxOoEX77Ezv9zwW7WV8DdluouRKNY/IR5u/YTMuKHgugHOzYWlYvYLpLA9nPsQCAAASpCIbjI9Mv+Uw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz", + "integrity": "sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "@babel/types": "^7.10.4" } }, "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.8.3.tgz", - "integrity": "sha512-5eFOm2SyFPK4Rh3XMMRDjN7lBH0orh3ss0g3rTYZnBQ+r6YPj7lgDyCvPphynHvUrobJmeMignBr6Acw9mAPlw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz", + "integrity": "sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg==", "dev": true, "requires": { - "@babel/helper-explode-assignable-expression": "^7.8.3", - "@babel/types": "^7.8.3" + "@babel/helper-explode-assignable-expression": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/helper-builder-react-jsx": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.8.3.tgz", - "integrity": "sha512-JT8mfnpTkKNCboTqZsQTdGo3l3Ik3l7QIt9hh0O9DYiwVel37VoJpILKM4YFbP2euF32nkQSb+F9cUk9b7DDXQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.10.4.tgz", + "integrity": "sha512-5nPcIZ7+KKDxT1427oBivl9V9YTal7qk0diccnh7RrcgrT/pGFOjgGw1dgryyx1GvHEpXVfoDF6Ak3rTiWh8Rg==", "dev": true, "requires": { - "@babel/types": "^7.8.3", - "esutils": "^2.0.0" + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/types": "^7.10.4" } }, - "@babel/helper-call-delegate": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.8.3.tgz", - "integrity": "sha512-6Q05px0Eb+N4/GTyKPPvnkig7Lylw+QzihMpws9iiZQv7ZImf84ZsZpQH7QoWN4n4tm81SnSzPgHw2qtO0Zf3A==", + "@babel/helper-builder-react-jsx-experimental": { + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-react-jsx-experimental/-/helper-builder-react-jsx-experimental-7.10.5.tgz", + "integrity": "sha512-Buewnx6M4ttG+NLkKyt7baQn7ScC/Td+e99G914fRU8fGIUivDDgVIQeDHFa5e4CRSJQt58WpNHhsAZgtzVhsg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-module-imports": "^7.10.4", + "@babel/types": "^7.10.5" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz", + "integrity": "sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ==", "dev": true, "requires": { - "@babel/helper-hoist-variables": "^7.8.3", - "@babel/traverse": "^7.8.3", - "@babel/types": "^7.8.3" + "@babel/compat-data": "^7.10.4", + "browserslist": "^4.12.0", + "invariant": "^2.2.4", + "levenary": "^1.1.1", + "semver": "^5.5.0" } }, "@babel/helper-create-class-features-plugin": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.8.3.tgz", - "integrity": "sha512-qmp4pD7zeTxsv0JNecSBsEmG1ei2MqwJq4YQcK3ZWm/0t07QstWfvuV/vm3Qt5xNMFETn2SZqpMx2MQzbtq+KA==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz", + "integrity": "sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.8.3", - "@babel/helper-member-expression-to-functions": "^7.8.3", - "@babel/helper-optimise-call-expression": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/helper-replace-supers": "^7.8.3", - "@babel/helper-split-export-declaration": "^7.8.3" + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-member-expression-to-functions": "^7.10.5", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.10.4" } }, "@babel/helper-create-regexp-features-plugin": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.3.tgz", - "integrity": "sha512-Gcsm1OHCUr9o9TcJln57xhWHtdXbA2pgQ58S0Lxlks0WMGNXuki4+GLfX0p+L2ZkINUGZvfkz8rzoqJQSthI+Q==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz", + "integrity": "sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g==", "dev": true, "requires": { - "@babel/helper-regex": "^7.8.3", - "regexpu-core": "^4.6.0" - }, - "dependencies": { - "regexpu-core": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.6.0.tgz", - "integrity": "sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg==", - "dev": true, - "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.1.0", - "regjsgen": "^0.5.0", - "regjsparser": "^0.6.0", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.1.0" - } - }, - "regjsgen": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.1.tgz", - "integrity": "sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg==", - "dev": true - }, - "regjsparser": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.3.tgz", - "integrity": "sha512-8uZvYbnfAtEm9Ab8NTb3hdLwL4g/LQzEYP7Xs27T96abJCCE2d6r3cPZPQEsLKy0vRSGVNG+/zVGtLr86HQduA==", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - } - } + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-regex": "^7.10.4", + "regexpu-core": "^4.7.0" } }, "@babel/helper-define-map": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.8.3.tgz", - "integrity": "sha512-PoeBYtxoZGtct3md6xZOCWPcKuMuk3IHhgxsRRNtnNShebf4C8YonTSblsK4tvDbm+eJAw2HAPOfCr+Q/YRG/g==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz", + "integrity": "sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.8.3", - "@babel/types": "^7.8.3", - "lodash": "^4.17.13" + "@babel/helper-function-name": "^7.10.4", + "@babel/types": "^7.10.5", + "lodash": "^4.17.19" + }, + "dependencies": { + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + } } }, "@babel/helper-explode-assignable-expression": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.8.3.tgz", - "integrity": "sha512-N+8eW86/Kj147bO9G2uclsg5pwfs/fqqY5rwgIL7eTBklgXjcOJ3btzS5iM6AitJcftnY7pm2lGsrJVYLGjzIw==", + "version": "7.11.4", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.11.4.tgz", + "integrity": "sha512-ux9hm3zR4WV1Y3xXxXkdG/0gxF9nvI0YVmKVhvK9AfMoaQkemL3sJpXw+Xbz65azo8qJiEz2XVDUpK3KYhH3ZQ==", "dev": true, "requires": { - "@babel/traverse": "^7.8.3", - "@babel/types": "^7.8.3" + "@babel/types": "^7.10.4" } }, "@babel/helper-function-name": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz", - "integrity": "sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", + "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/types": "^7.8.3" + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/helper-get-function-arity": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", - "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", + "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "@babel/types": "^7.10.4" } }, "@babel/helper-hoist-variables": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.8.3.tgz", - "integrity": "sha512-ky1JLOjcDUtSc+xkt0xhYff7Z6ILTAHKmZLHPxAhOP0Nd77O+3nCsd6uSVYur6nJnCI029CrNbYlc0LoPfAPQg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz", + "integrity": "sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "@babel/types": "^7.10.4" } }, "@babel/helper-member-expression-to-functions": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz", - "integrity": "sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz", + "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "@babel/types": "^7.11.0" } }, "@babel/helper-module-imports": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz", - "integrity": "sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz", + "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "@babel/types": "^7.10.4" } }, "@babel/helper-module-transforms": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.8.3.tgz", - "integrity": "sha512-C7NG6B7vfBa/pwCOshpMbOYUmrYQDfCpVL/JCRu0ek8B5p8kue1+BCXpg2vOYs7w5ACB9GTOBYQ5U6NwrMg+3Q==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz", + "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.8.3", - "@babel/helper-simple-access": "^7.8.3", - "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/types": "^7.8.3", - "lodash": "^4.17.13" + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4", + "@babel/helper-simple-access": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/template": "^7.10.4", + "@babel/types": "^7.11.0", + "lodash": "^4.17.19" + }, + "dependencies": { + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + } } }, "@babel/helper-optimise-call-expression": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz", - "integrity": "sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz", + "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "@babel/types": "^7.10.4" } }, "@babel/helper-plugin-utils": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz", - "integrity": "sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", "dev": true }, "@babel/helper-regex": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.8.3.tgz", - "integrity": "sha512-BWt0QtYv/cg/NecOAZMdcn/waj/5P26DR4mVLXfFtDokSR6fyuG0Pj+e2FqtSME+MqED1khnSMulkmGl8qWiUQ==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.10.5.tgz", + "integrity": "sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg==", "dev": true, "requires": { - "lodash": "^4.17.13" + "lodash": "^4.17.19" + }, + "dependencies": { + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + } } }, "@babel/helper-remap-async-to-generator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.8.3.tgz", - "integrity": "sha512-kgwDmw4fCg7AVgS4DukQR/roGp+jP+XluJE5hsRZwxCYGg+Rv9wSGErDWhlI90FODdYfd4xG4AQRiMDjjN0GzA==", + "version": "7.11.4", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.11.4.tgz", + "integrity": "sha512-tR5vJ/vBa9wFy3m5LLv2faapJLnDFxNWff2SAYkSE4rLUdbp7CdObYFgI7wK4T/Mj4UzpjPwzR8Pzmr5m7MHGA==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.8.3", - "@babel/helper-wrap-function": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/traverse": "^7.8.3", - "@babel/types": "^7.8.3" + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-wrap-function": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/helper-replace-supers": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.8.3.tgz", - "integrity": "sha512-xOUssL6ho41U81etpLoT2RTdvdus4VfHamCuAm4AHxGr+0it5fnwoVdwUJ7GFEqCsQYzJUhcbsN9wB9apcYKFA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz", + "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==", "dev": true, "requires": { - "@babel/helper-member-expression-to-functions": "^7.8.3", - "@babel/helper-optimise-call-expression": "^7.8.3", - "@babel/traverse": "^7.8.3", - "@babel/types": "^7.8.3" + "@babel/helper-member-expression-to-functions": "^7.10.4", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/helper-simple-access": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz", - "integrity": "sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz", + "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==", + "dev": true, + "requires": { + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz", + "integrity": "sha512-0XIdiQln4Elglgjbwo9wuJpL/K7AGCY26kmEt0+pRP0TAj4jjyNq1MjoRvikrTVqKcx4Gysxt4cXvVFXP/JO2Q==", "dev": true, "requires": { - "@babel/template": "^7.8.3", - "@babel/types": "^7.8.3" + "@babel/types": "^7.11.0" } }, "@babel/helper-split-export-declaration": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", - "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", + "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", "dev": true, "requires": { - "@babel/types": "^7.8.3" + "@babel/types": "^7.11.0" } }, "@babel/helper-validator-identifier": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz", - "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", "dev": true }, "@babel/helper-wrap-function": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz", - "integrity": "sha512-LACJrbUET9cQDzb6kG7EeD7+7doC3JNvUgTEQOx2qaO1fKlzE/Bf05qs9w1oXQMmXlPO65lC3Tq9S6gZpTErEQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz", + "integrity": "sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/traverse": "^7.8.3", - "@babel/types": "^7.8.3" + "@babel/helper-function-name": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/helpers": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.8.4.tgz", - "integrity": "sha512-VPbe7wcQ4chu4TDQjimHv/5tj73qz88o12EPkO2ValS2QiQS/1F2SsjyIGNnAD0vF/nZS6Cf9i+vW6HIlnaR8w==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz", + "integrity": "sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==", "dev": true, "requires": { - "@babel/template": "^7.8.3", - "@babel/traverse": "^7.8.4", - "@babel/types": "^7.8.3" + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/highlight": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz", - "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", "dev": true, "requires": { + "@babel/helper-validator-identifier": "^7.10.4", "chalk": "^2.0.0", - "esutils": "^2.0.2", "js-tokens": "^4.0.0" }, "dependencies": { @@ -389,102 +470,162 @@ } }, "@babel/parser": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.8.4.tgz", - "integrity": "sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw==", + "version": "7.11.1", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.1.tgz", + "integrity": "sha512-u9QMIRdKVF7hfEkb3nu2LgZDIzCQPv+yHD9Eg6ruoJLjkrQ9fFz4IBSlF/9XwoNri9+2F1IY+dYuOfZrXq8t3w==", "dev": true }, "@babel/plugin-proposal-async-generator-functions": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz", - "integrity": "sha512-NZ9zLv848JsV3hs8ryEh7Uaz/0KsmPLqv0+PdkDJL1cJy0K4kOCFa8zc1E3mp+RHPQcpdfb/6GovEsW4VDrOMw==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz", + "integrity": "sha512-cNMCVezQbrRGvXJwm9fu/1sJj9bHdGAgKodZdLqOQIpfoH3raqmRPBM17+lh7CzhiKRRBrGtZL9WcjxSoGYUSg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/helper-remap-async-to-generator": "^7.8.3", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-remap-async-to-generator": "^7.10.4", "@babel/plugin-syntax-async-generators": "^7.8.0" } }, "@babel/plugin-proposal-class-properties": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.5.5.tgz", - "integrity": "sha512-AF79FsnWFxjlaosgdi421vmYG6/jg79bVD0dpD44QdgobzHKuLZ6S3vl8la9qIeSwGi8i1fS0O1mfuDAAdo1/A==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.8.3.tgz", + "integrity": "sha512-EqFhbo7IosdgPgZggHaNObkmO1kNUe3slaKu54d5OWvy+p9QIKOzK1GAEpAIsZtWVtPXUHSMcT4smvDrCfY4AA==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.5.5", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-create-class-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3" } }, "@babel/plugin-proposal-decorators": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.6.0.tgz", - "integrity": "sha512-ZSyYw9trQI50sES6YxREXKu+4b7MAg6Qx2cvyDDYjP2Hpzd3FleOUwC9cqn1+za8d0A2ZU8SHujxFao956efUg==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.8.3.tgz", + "integrity": "sha512-e3RvdvS4qPJVTe288DlXjwKflpfy1hr0j5dz5WpIYYeP7vQZg2WfAEIp8k5/Lwis/m5REXEteIz6rrcDtXXG7w==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.6.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-decorators": "^7.2.0" + "@babel/helper-create-class-features-plugin": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-decorators": "^7.8.3" } }, "@babel/plugin-proposal-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.8.3.tgz", - "integrity": "sha512-NyaBbyLFXFLT9FP+zk0kYlUlA8XtCUbehs67F0nnEg7KICgMc2mNkIeu9TYhKzyXMkrapZFwAhXLdnt4IYHy1w==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz", + "integrity": "sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-plugin-utils": "^7.10.4", "@babel/plugin-syntax-dynamic-import": "^7.8.0" - }, - "dependencies": { - "@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - } + } + }, + "@babel/plugin-proposal-export-default-from": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.10.4.tgz", + "integrity": "sha512-G1l00VvDZ7Yk2yRlC5D8Ybvu3gmeHS3rCHoUYdjrqGYUtdeOBoRypnvDZ5KQqxyaiiGHWnVDeSEzA5F9ozItig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-export-default-from": "^7.10.4" + } + }, + "@babel/plugin-proposal-export-namespace-from": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.10.4.tgz", + "integrity": "sha512-aNdf0LY6/3WXkhh0Fdb6Zk9j1NMD8ovj3F6r0+3j837Pn1S1PdNtcwJ5EG9WkVPNHPxyJDaxMaAOVq4eki0qbg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" } }, "@babel/plugin-proposal-json-strings": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz", + "integrity": "sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.0" + } + }, + "@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.11.0.tgz", + "integrity": "sha512-/f8p4z+Auz0Uaf+i8Ekf1iM7wUNLcViFUGiPxKeXvxTSl63B875YPiVdUDdem7hREcI0E0kSpEhS8tF5RphK7Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.8.3.tgz", - "integrity": "sha512-KGhQNZ3TVCQG/MjRbAUwuH+14y9q0tpxs1nWWs3pbSleRdDro9SAMMDyye8HhY1gqZ7/NqIc8SKhya0wRDgP1Q==", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.0" + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" + } + }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.8.3.tgz", + "integrity": "sha512-jWioO1s6R/R+wEHizfaScNsAx+xKgwTLNXSh7tTC4Usj3ItsPEhYkEpU4h+lpnBwq7NBVOJXfO6cRFYcX69JUQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.8.3" } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.5.5.tgz", - "integrity": "sha512-F2DxJJSQ7f64FyTVl5cw/9MWn6naXGdk3Q3UhDbFEEHv+EilCPoeRD3Zh/Utx1CJz4uyKlQ4uH+bJPbEhMV7Zw==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz", + "integrity": "sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-object-rest-spread": "^7.2.0" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-transform-parameters": "^7.10.4" } }, "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-0gkX7J7E+AtAw9fcwlVQj8peP61qhdg/89D5swOkjYbkboA2CVckn3kiyum1DE0wskGb7KJJxBdyEBApDLLVdw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz", + "integrity": "sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3", + "@babel/helper-plugin-utils": "^7.10.4", "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" } }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.9.0.tgz", + "integrity": "sha512-NDn5tu3tcv4W30jNhmc2hyD5c56G6cXx4TesJubhxrJeCvuuMpttxr0OnNCqbZGhFjLrg+NIhxxC+BK5F6yS3w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.0" + } + }, + "@babel/plugin-proposal-private-methods": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz", + "integrity": "sha512-wh5GJleuI8k3emgTg5KkJK6kHNsGEr0uBTDBuQUBJwckk9xs1ez79ioheEVVxMLyPscB0LfkbVHslQqIzWV6Bw==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.3.tgz", - "integrity": "sha512-1/1/rEZv2XGweRwwSkLpY+s60za9OZ1hJs4YDqFHCw0kYWYwL5IFljVY1MYBL+weT1l9pokDO2uhSTLVxzoHkQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz", + "integrity": "sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-create-regexp-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-syntax-async-generators": { @@ -496,51 +637,60 @@ "@babel/helper-plugin-utils": "^7.8.0" } }, - "@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "@babel/plugin-syntax-class-properties": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz", + "integrity": "sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, - "@babel/plugin-syntax-class-properties": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.8.3.tgz", - "integrity": "sha512-UcAyQWg2bAN647Q+O811tG9MrJ38Z10jjhQdKNAL8fsyPzE3cCN/uT+f55cFVY4aGO4jqJAvmqsuY3GQDwAoXg==", + "@babel/plugin-syntax-decorators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.10.4.tgz", + "integrity": "sha512-2NaoC6fAk2VMdhY1eerkfHV+lVYC1u8b+jmRJISqANCJlTxYy19HGdIkkQtix2UtkcPuPu+IlDgrVseZnU03bw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, - "@babel/plugin-syntax-decorators": { + "@babel/plugin-syntax-dynamic-import": { "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.8.3.tgz", - "integrity": "sha512-8Hg4dNNT9/LcA1zQlfwuKR8BUc/if7Q7NkTam9sGTcJphLwpf2g4S42uhspQrIrR+dpzE0dtTqBVFoHl8GtnnQ==", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.8.0" } }, - "@babel/plugin-syntax-dynamic-import": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz", - "integrity": "sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w==", + "@babel/plugin-syntax-export-default-from": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.10.4.tgz", + "integrity": "sha512-79V6r6Pgudz0RnuMGp5xidu6Z+bPFugh8/Q9eDHonmLp4wKFAZDwygJwYgCzuDu8lFA/sYyT+mc5y2wkd7bTXA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, - "@babel/plugin-syntax-flow": { + "@babel/plugin-syntax-export-namespace-from": { "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.8.3.tgz", - "integrity": "sha512-innAx3bUbA0KSYj2E2MNFSn9hiCeowOFLxlsuhXzw8hMQnzkDomUr9QCD7E9VF60NmnG1sNTuuv6Qf4f8INYsg==", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.8.3" } }, + "@babel/plugin-syntax-flow": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.10.4.tgz", + "integrity": "sha512-yxQsX1dJixF4qEEdzVbst3SZQ58Nrooz8NV9Z9GL4byTE25BvJgl5lf0RECUf0fh28rZBb/RYTWn/eeKwCMrZQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, "@babel/plugin-syntax-json-strings": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", @@ -551,21 +701,21 @@ } }, "@babel/plugin-syntax-jsx": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.8.3.tgz", - "integrity": "sha512-WxdW9xyLgBdefoo0Ynn3MRSkhe5tFVxxKNVdnZSh318WrG2e2jH+E9wd/++JsqcLJZPfz87njQJ8j2Upjm0M0A==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.10.4.tgz", + "integrity": "sha512-KCg9mio9jwiARCB7WAcQ7Y1q+qicILjoK8LP/VkPkEKaf5dkaZZK1EcTe91a3JJlZ3qy6L5s9X52boEYi8DM9g==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.8.3.tgz", - "integrity": "sha512-Zpg2Sgc++37kuFl6ppq2Q7Awc6E6AIW671x5PY8E/f7MCIyPPGK/EoeZXvvY3P42exZ3Q4/t3YOzP/HiN79jDg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-syntax-nullish-coalescing-operator": { @@ -578,12 +728,12 @@ } }, "@babel/plugin-syntax-numeric-separator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.8.3.tgz", - "integrity": "sha512-H7dCMAdN83PcCmqmkHB5dtp+Xa9a6LKSvA2hiFBC/5alSHxM5VgWZXFqDi0YFe8XNGT6iCa+z4V4zSt/PdZ7Dw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-syntax-object-rest-spread": { @@ -613,67 +763,75 @@ "@babel/helper-plugin-utils": "^7.8.0" } }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz", + "integrity": "sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, "@babel/plugin-syntax-typescript": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.8.3.tgz", - "integrity": "sha512-GO1MQ/SGGGoiEXY0e0bSpHimJvxqB7lktLLIq2pv8xG7WZ8IMEle74jIe1FhprHBWjwjZtXHkycDLZXIWM5Wfg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.10.4.tgz", + "integrity": "sha512-oSAEz1YkBCAKr5Yiq8/BNtvSAPwkp/IyUnwZogd8p+F0RuYQQrLeRUzIQhueQTTBy/F+a40uS7OFKxnkRvmvFQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-arrow-functions": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz", - "integrity": "sha512-0MRF+KC8EqH4dbuITCWwPSzsyO3HIWWlm30v8BbbpOrS1B++isGxPnnuq/IZvOX5J2D/p7DQalQm+/2PnlKGxg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz", + "integrity": "sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-async-to-generator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.8.3.tgz", - "integrity": "sha512-imt9tFLD9ogt56Dd5CI/6XgpukMwd/fLGSrix2httihVe7LOGVPhyhMh1BU5kDM7iHD08i8uUtmV2sWaBFlHVQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz", + "integrity": "sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/helper-remap-async-to-generator": "^7.8.3" + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-remap-async-to-generator": "^7.10.4" } }, "@babel/plugin-transform-block-scoped-functions": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.8.3.tgz", - "integrity": "sha512-vo4F2OewqjbB1+yaJ7k2EJFHlTP3jR634Z9Cj9itpqNjuLXvhlVxgnjsHsdRgASR8xYDrx6onw4vW5H6We0Jmg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz", + "integrity": "sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-block-scoping": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.8.3.tgz", - "integrity": "sha512-pGnYfm7RNRgYRi7bids5bHluENHqJhrV4bCZRwc5GamaWIIs07N4rZECcmJL6ZClwjDz1GbdMZFtPs27hTB06w==", + "version": "7.11.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.11.1.tgz", + "integrity": "sha512-00dYeDE0EVEHuuM+26+0w/SCL0BH2Qy7LwHuI4Hi4MH5gkC8/AqMN5uWFJIsoXZrAphiMm1iXzBw6L2T+eA0ew==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3", - "lodash": "^4.17.13" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-classes": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.8.3.tgz", - "integrity": "sha512-SjT0cwFJ+7Rbr1vQsvphAHwUHvSUPmMjMU/0P59G8U2HLFqSa082JO7zkbDNWs9kH/IUqpHI6xWNesGf8haF1w==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.8.3", - "@babel/helper-define-map": "^7.8.3", - "@babel/helper-function-name": "^7.8.3", - "@babel/helper-optimise-call-expression": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/helper-replace-supers": "^7.8.3", - "@babel/helper-split-export-declaration": "^7.8.3", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz", + "integrity": "sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-define-map": "^7.10.4", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.10.4", "globals": "^11.1.0" }, "dependencies": { @@ -686,466 +844,582 @@ } }, "@babel/plugin-transform-computed-properties": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.8.3.tgz", - "integrity": "sha512-O5hiIpSyOGdrQZRQ2ccwtTVkgUDBBiCuK//4RJ6UfePllUTCENOzKxfh6ulckXKc0DixTFLCfb2HVkNA7aDpzA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz", + "integrity": "sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-destructuring": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.6.0.tgz", - "integrity": "sha512-2bGIS5P1v4+sWTCnKNDZDxbGvEqi0ijeqM/YqHtVGrvG2y0ySgnEEhXErvE9dA0bnIzY9bIzdFK0jFA46ASIIQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz", + "integrity": "sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-dotall-regex": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.8.3.tgz", - "integrity": "sha512-kLs1j9Nn4MQoBYdRXH6AeaXMbEJFaFu/v1nQkvib6QzTj8MZI5OQzqmD83/2jEM1z0DLilra5aWO5YpyC0ALIw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz", + "integrity": "sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-create-regexp-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-duplicate-keys": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.8.3.tgz", - "integrity": "sha512-s8dHiBUbcbSgipS4SMFuWGqCvyge5V2ZeAWzR6INTVC3Ltjig/Vw1G2Gztv0vU/hRG9X8IvKvYdoksnUfgXOEQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz", + "integrity": "sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-exponentiation-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.8.3.tgz", - "integrity": "sha512-zwIpuIymb3ACcInbksHaNcR12S++0MDLKkiqXHl3AzpgdKlFNhog+z/K0+TGW+b0w5pgTq4H6IwV/WhxbGYSjQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz", + "integrity": "sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw==", "dev": true, "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-flow-strip-types": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.4.4.tgz", - "integrity": "sha512-WyVedfeEIILYEaWGAUWzVNyqG4sfsNooMhXWsu/YzOvVGcsnPb5PguysjJqI3t3qiaYj0BR8T2f5njdjTGe44Q==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.9.0.tgz", + "integrity": "sha512-7Qfg0lKQhEHs93FChxVLAvhBshOPQDtJUTVHr/ZwQNRccCm4O9D79r9tVSoV8iNwjP1YgfD+e/fgHcPkN1qEQg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-flow": "^7.2.0" + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-syntax-flow": "^7.8.3" } }, "@babel/plugin-transform-for-of": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.8.4.tgz", - "integrity": "sha512-iAXNlOWvcYUYoV8YIxwS7TxGRJcxyl8eQCfT+A5j8sKUzRFvJdcyjp97jL2IghWSRDaL2PU2O2tX8Cu9dTBq5A==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz", + "integrity": "sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-function-name": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.8.3.tgz", - "integrity": "sha512-rO/OnDS78Eifbjn5Py9v8y0aR+aSYhDhqAwVfsTl0ERuMZyr05L1aFSCJnbv2mmsLkit/4ReeQ9N2BgLnOcPCQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz", + "integrity": "sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-literals": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.8.3.tgz", - "integrity": "sha512-3Tqf8JJ/qB7TeldGl+TT55+uQei9JfYaregDcEAyBZ7akutriFrt6C/wLYIer6OYhleVQvH/ntEhjE/xMmy10A==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz", + "integrity": "sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-member-expression-literals": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.8.3.tgz", - "integrity": "sha512-3Wk2EXhnw+rP+IDkK6BdtPKsUE5IeZ6QOGrPYvw52NwBStw9V1ZVzxgK6fSKSxqUvH9eQPR3tm3cOq79HlsKYA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz", + "integrity": "sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-modules-amd": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.8.3.tgz", - "integrity": "sha512-MadJiU3rLKclzT5kBH4yxdry96odTUwuqrZM+GllFI/VhxfPz+k9MshJM+MwhfkCdxxclSbSBbUGciBngR+kEQ==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz", + "integrity": "sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3", - "babel-plugin-dynamic-import-node": "^2.3.0" + "@babel/helper-module-transforms": "^7.10.5", + "@babel/helper-plugin-utils": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.8.3.tgz", - "integrity": "sha512-JpdMEfA15HZ/1gNuB9XEDlZM1h/gF/YOH7zaZzQu2xCFRfwc01NXBMHHSTT6hRjlXJJs5x/bfODM3LiCk94Sxg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz", + "integrity": "sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/helper-simple-access": "^7.8.3", - "babel-plugin-dynamic-import-node": "^2.3.0" + "@babel/helper-module-transforms": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-simple-access": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.8.3.tgz", - "integrity": "sha512-8cESMCJjmArMYqa9AO5YuMEkE4ds28tMpZcGZB/jl3n0ZzlsxOAi3mC+SKypTfT8gjMupCnd3YiXCkMjj2jfOg==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz", + "integrity": "sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw==", "dev": true, "requires": { - "@babel/helper-hoist-variables": "^7.8.3", - "@babel/helper-module-transforms": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3", - "babel-plugin-dynamic-import-node": "^2.3.0" + "@babel/helper-hoist-variables": "^7.10.4", + "@babel/helper-module-transforms": "^7.10.5", + "@babel/helper-plugin-utils": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-umd": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.8.3.tgz", - "integrity": "sha512-evhTyWhbwbI3/U6dZAnx/ePoV7H6OUG+OjiJFHmhr9FPn0VShjwC2kdxqIuQ/+1P50TMrneGzMeyMTFOjKSnAw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz", + "integrity": "sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-module-transforms": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.8.3.tgz", - "integrity": "sha512-f+tF/8UVPU86TrCb06JoPWIdDpTNSGGcAtaD9mLP0aYGA0OS0j7j7DHJR0GTFrUZPUU6loZhbsVZgTh0N+Qdnw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz", + "integrity": "sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.8.3" + "@babel/helper-create-regexp-features-plugin": "^7.10.4" } }, "@babel/plugin-transform-new-target": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.8.3.tgz", - "integrity": "sha512-QuSGysibQpyxexRyui2vca+Cmbljo8bcRckgzYV4kRIsHpVeyeC3JDO63pY+xFZ6bWOBn7pfKZTqV4o/ix9sFw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz", + "integrity": "sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-object-super": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.8.3.tgz", - "integrity": "sha512-57FXk+gItG/GejofIyLIgBKTas4+pEU47IXKDBWFTxdPd7F80H8zybyAY7UoblVfBhBGs2EKM+bJUu2+iUYPDQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz", + "integrity": "sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/helper-replace-supers": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4" } }, "@babel/plugin-transform-parameters": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.8.4.tgz", - "integrity": "sha512-IsS3oTxeTsZlE5KqzTbcC2sV0P9pXdec53SU+Yxv7o/6dvGM5AkTotQKhoSffhNgZ/dftsSiOoxy7evCYJXzVA==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz", + "integrity": "sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw==", "dev": true, "requires": { - "@babel/helper-call-delegate": "^7.8.3", - "@babel/helper-get-function-arity": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-property-literals": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.8.3.tgz", - "integrity": "sha512-uGiiXAZMqEoQhRWMK17VospMZh5sXWg+dlh2soffpkAl96KAm+WZuJfa6lcELotSRmooLqg0MWdH6UUq85nmmg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz", + "integrity": "sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-react-constant-elements": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.8.3.tgz", - "integrity": "sha512-glrzN2U+egwRfkNFtL34xIBYTxbbUF2qJTP8HD3qETBBqzAWSeNB821X0GjU06+dNpq/UyCIjI72FmGE5NNkQQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.10.4.tgz", + "integrity": "sha512-cYmQBW1pXrqBte1raMkAulXmi7rjg3VI6ZLg9QIic8Hq7BtYXaWuZSxsr2siOMI6SWwpxjWfnwhTUrd7JlAV7g==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-react-display-name": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.2.0.tgz", - "integrity": "sha512-Htf/tPa5haZvRMiNSQSFifK12gtr/8vwfr+A9y69uF0QcU77AVu4K7MiHEkTxF7lQoHOL0F9ErqgfNEAKgXj7A==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.8.3.tgz", + "integrity": "sha512-3Jy/PCw8Fe6uBKtEgz3M82ljt+lTg+xJaM4og+eyu83qLT87ZUSckn0wy7r31jflURWLO83TW6Ylf7lyXj3m5A==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.8.3" } }, "@babel/plugin-transform-react-jsx": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.8.3.tgz", - "integrity": "sha512-r0h+mUiyL595ikykci+fbwm9YzmuOrUBi0b+FDIKmi3fPQyFokWVEMJnRWHJPPQEjyFJyna9WZC6Viv6UHSv1g==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.10.4.tgz", + "integrity": "sha512-L+MfRhWjX0eI7Js093MM6MacKU4M6dnCRa/QPDwYMxjljzSCzzlzKzj9Pk4P3OtrPcxr2N3znR419nr3Xw+65A==", "dev": true, "requires": { - "@babel/helper-builder-react-jsx": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/plugin-syntax-jsx": "^7.8.3" + "@babel/helper-builder-react-jsx": "^7.10.4", + "@babel/helper-builder-react-jsx-experimental": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-jsx": "^7.10.4" + } + }, + "@babel/plugin-transform-react-jsx-development": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.10.4.tgz", + "integrity": "sha512-RM3ZAd1sU1iQ7rI2dhrZRZGv0aqzNQMbkIUCS1txYpi9wHQ2ZHNjo5TwX+UD6pvFW4AbWqLVYvKy5qJSAyRGjQ==", + "dev": true, + "requires": { + "@babel/helper-builder-react-jsx-experimental": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-jsx": "^7.10.4" } }, "@babel/plugin-transform-react-jsx-self": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.8.3.tgz", - "integrity": "sha512-01OT7s5oa0XTLf2I8XGsL8+KqV9lx3EZV+jxn/L2LQ97CGKila2YMroTkCEIE0HV/FF7CMSRsIAybopdN9NTdg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.10.4.tgz", + "integrity": "sha512-yOvxY2pDiVJi0axdTWHSMi5T0DILN+H+SaeJeACHKjQLezEzhLx9nEF9xgpBLPtkZsks9cnb5P9iBEi21En3gg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/plugin-syntax-jsx": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-jsx": "^7.10.4" } }, "@babel/plugin-transform-react-jsx-source": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.8.3.tgz", - "integrity": "sha512-PLMgdMGuVDtRS/SzjNEQYUT8f4z1xb2BAT54vM1X5efkVuYBf5WyGUMbpmARcfq3NaglIwz08UVQK4HHHbC6ag==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.10.5.tgz", + "integrity": "sha512-wTeqHVkN1lfPLubRiZH3o73f4rfon42HpgxUSs86Nc+8QIcm/B9s8NNVXu/gwGcOyd7yDib9ikxoDLxJP0UiDA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/plugin-syntax-jsx": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-jsx": "^7.10.4" + } + }, + "@babel/plugin-transform-react-pure-annotations": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.10.4.tgz", + "integrity": "sha512-+njZkqcOuS8RaPakrnR9KvxjoG1ASJWpoIv/doyWngId88JoFlPlISenGXjrVacZUIALGUr6eodRs1vmPnF23A==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-regenerator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.3.tgz", - "integrity": "sha512-qt/kcur/FxrQrzFR432FGZznkVAjiyFtCOANjkAKwCbt465L6ZCiUQh2oMYGU3Wo8LRFJxNDFwWn106S5wVUNA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz", + "integrity": "sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw==", "dev": true, "requires": { - "regenerator-transform": "^0.14.0" - }, - "dependencies": { - "regenerator-transform": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.1.tgz", - "integrity": "sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ==", - "dev": true, - "requires": { - "private": "^0.1.6" - } - } + "regenerator-transform": "^0.14.2" } }, "@babel/plugin-transform-reserved-words": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.8.3.tgz", - "integrity": "sha512-mwMxcycN3omKFDjDQUl+8zyMsBfjRFr0Zn/64I41pmjv4NJuqcYlEtezwYtw9TFd9WR1vN5kiM+O0gMZzO6L0A==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz", + "integrity": "sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-runtime": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.6.0.tgz", - "integrity": "sha512-Da8tMf7uClzwUm/pnJ1S93m/aRXmoYNDD7TkHua8xBDdaAs54uZpTWvEt6NGwmoVMb9mZbntfTqmG2oSzN/7Vg==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.11.0.tgz", + "integrity": "sha512-LFEsP+t3wkYBlis8w6/kmnd6Kb1dxTd+wGJ8MlxTGzQo//ehtqlVL4S9DNUa53+dtPSQobN2CXx4d81FqC58cw==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", "resolve": "^1.8.1", "semver": "^5.5.1" } }, "@babel/plugin-transform-shorthand-properties": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz", - "integrity": "sha512-I9DI6Odg0JJwxCHzbzW08ggMdCezoWcuQRz3ptdudgwaHxTjxw5HgdFJmZIkIMlRymL6YiZcped4TTCB0JcC8w==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz", + "integrity": "sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.8.3.tgz", - "integrity": "sha512-CkuTU9mbmAoFOI1tklFWYYbzX5qCIZVXPVy0jpXgGwkplCndQAa58s2jr66fTeQnA64bDox0HL4U56CFYoyC7g==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.11.0.tgz", + "integrity": "sha512-UwQYGOqIdQJe4aWNyS7noqAnN2VbaczPLiEtln+zPowRNlD+79w3oi2TWfYe0eZgd+gjZCbsydN7lzWysDt+gw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0" } }, "@babel/plugin-transform-sticky-regex": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.8.3.tgz", - "integrity": "sha512-9Spq0vGCD5Bb4Z/ZXXSK5wbbLFMG085qd2vhL1JYu1WcQ5bXqZBAYRzU1d+p79GcHs2szYv5pVQCX13QgldaWw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz", + "integrity": "sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/helper-regex": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-regex": "^7.10.4" } }, "@babel/plugin-transform-template-literals": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.8.3.tgz", - "integrity": "sha512-820QBtykIQOLFT8NZOcTRJ1UNuztIELe4p9DCgvj4NK+PwluSJ49we7s9FB1HIGNIYT7wFUJ0ar2QpCDj0escQ==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz", + "integrity": "sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-typeof-symbol": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.4.tgz", - "integrity": "sha512-2QKyfjGdvuNfHsb7qnBBlKclbD4CfshH2KvDabiijLMGXPHJXGxtDzwIF7bQP+T0ysw8fYTtxPafgfs/c1Lrqg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz", + "integrity": "sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-typescript": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.8.3.tgz", - "integrity": "sha512-Ebj230AxcrKGZPKIp4g4TdQLrqX95TobLUWKd/CwG7X1XHUH1ZpkpFvXuXqWbtGRWb7uuEWNlrl681wsOArAdQ==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.11.0.tgz", + "integrity": "sha512-edJsNzTtvb3MaXQwj8403B7mZoGu9ElDJQZOKjGUnvilquxBA3IQoEIOvkX/1O8xfAsnHS/oQhe2w/IXrr+w0w==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3", - "@babel/plugin-syntax-typescript": "^7.8.3" + "@babel/helper-create-class-features-plugin": "^7.10.5", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-typescript": "^7.10.4" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz", + "integrity": "sha512-y5XJ9waMti2J+e7ij20e+aH+fho7Wb7W8rNuu72aKRwCHFqQdhkdU2lo3uZ9tQuboEJcUFayXdARhcxLQ3+6Fg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-unicode-regex": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz", - "integrity": "sha512-+ufgJjYdmWfSQ+6NS9VGUR2ns8cjJjYbrbi11mZBTaWm+Fui/ncTLFF28Ei1okavY+xkojGr1eJxNsWYeA5aZw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz", + "integrity": "sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.8.3", - "@babel/helper-plugin-utils": "^7.8.3" + "@babel/helper-create-regexp-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/preset-env": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.6.0.tgz", - "integrity": "sha512-1efzxFv/TcPsNXlRhMzRnkBFMeIqBBgzwmZwlFDw5Ubj0AGLeufxugirwZmkkX/ayi3owsSqoQ4fw8LkfK9SYg==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.11.0.tgz", + "integrity": "sha512-2u1/k7rG/gTh02dylX2kL3S0IJNF+J6bfDSp4DI2Ma8QN6Y9x9pmAax59fsCk6QUQG0yqH47yJWA+u1I1LccAg==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.11.0", + "@babel/helper-compilation-targets": "^7.10.4", + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-proposal-async-generator-functions": "^7.10.4", + "@babel/plugin-proposal-class-properties": "^7.10.4", + "@babel/plugin-proposal-dynamic-import": "^7.10.4", + "@babel/plugin-proposal-export-namespace-from": "^7.10.4", + "@babel/plugin-proposal-json-strings": "^7.10.4", + "@babel/plugin-proposal-logical-assignment-operators": "^7.11.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4", + "@babel/plugin-proposal-numeric-separator": "^7.10.4", + "@babel/plugin-proposal-object-rest-spread": "^7.11.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.10.4", + "@babel/plugin-proposal-optional-chaining": "^7.11.0", + "@babel/plugin-proposal-private-methods": "^7.10.4", + "@babel/plugin-proposal-unicode-property-regex": "^7.10.4", + "@babel/plugin-syntax-async-generators": "^7.8.0", + "@babel/plugin-syntax-class-properties": "^7.10.4", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.0", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.0", + "@babel/plugin-syntax-top-level-await": "^7.10.4", + "@babel/plugin-transform-arrow-functions": "^7.10.4", + "@babel/plugin-transform-async-to-generator": "^7.10.4", + "@babel/plugin-transform-block-scoped-functions": "^7.10.4", + "@babel/plugin-transform-block-scoping": "^7.10.4", + "@babel/plugin-transform-classes": "^7.10.4", + "@babel/plugin-transform-computed-properties": "^7.10.4", + "@babel/plugin-transform-destructuring": "^7.10.4", + "@babel/plugin-transform-dotall-regex": "^7.10.4", + "@babel/plugin-transform-duplicate-keys": "^7.10.4", + "@babel/plugin-transform-exponentiation-operator": "^7.10.4", + "@babel/plugin-transform-for-of": "^7.10.4", + "@babel/plugin-transform-function-name": "^7.10.4", + "@babel/plugin-transform-literals": "^7.10.4", + "@babel/plugin-transform-member-expression-literals": "^7.10.4", + "@babel/plugin-transform-modules-amd": "^7.10.4", + "@babel/plugin-transform-modules-commonjs": "^7.10.4", + "@babel/plugin-transform-modules-systemjs": "^7.10.4", + "@babel/plugin-transform-modules-umd": "^7.10.4", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.10.4", + "@babel/plugin-transform-new-target": "^7.10.4", + "@babel/plugin-transform-object-super": "^7.10.4", + "@babel/plugin-transform-parameters": "^7.10.4", + "@babel/plugin-transform-property-literals": "^7.10.4", + "@babel/plugin-transform-regenerator": "^7.10.4", + "@babel/plugin-transform-reserved-words": "^7.10.4", + "@babel/plugin-transform-shorthand-properties": "^7.10.4", + "@babel/plugin-transform-spread": "^7.11.0", + "@babel/plugin-transform-sticky-regex": "^7.10.4", + "@babel/plugin-transform-template-literals": "^7.10.4", + "@babel/plugin-transform-typeof-symbol": "^7.10.4", + "@babel/plugin-transform-unicode-escapes": "^7.10.4", + "@babel/plugin-transform-unicode-regex": "^7.10.4", + "@babel/preset-modules": "^0.1.3", + "@babel/types": "^7.11.0", + "browserslist": "^4.12.0", + "core-js-compat": "^3.6.2", + "invariant": "^2.2.2", + "levenary": "^1.1.1", + "semver": "^5.5.0" + }, + "dependencies": { + "@babel/plugin-proposal-class-properties": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.10.4.tgz", + "integrity": "sha512-vhwkEROxzcHGNu2mzUC0OFFNXdZ4M23ib8aRRcJSsW8BZK9pQMD7QB7csl97NBbgGZO7ZyHUyKDnxzOaP4IrCg==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz", + "integrity": "sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" + } + }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz", + "integrity": "sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz", + "integrity": "sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.0" + } + } + } + }, + "@babel/preset-modules": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz", + "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.0.0", "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-async-generator-functions": "^7.2.0", - "@babel/plugin-proposal-dynamic-import": "^7.5.0", - "@babel/plugin-proposal-json-strings": "^7.2.0", - "@babel/plugin-proposal-object-rest-spread": "^7.5.5", - "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-syntax-async-generators": "^7.2.0", - "@babel/plugin-syntax-dynamic-import": "^7.2.0", - "@babel/plugin-syntax-json-strings": "^7.2.0", - "@babel/plugin-syntax-object-rest-spread": "^7.2.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", - "@babel/plugin-transform-arrow-functions": "^7.2.0", - "@babel/plugin-transform-async-to-generator": "^7.5.0", - "@babel/plugin-transform-block-scoped-functions": "^7.2.0", - "@babel/plugin-transform-block-scoping": "^7.6.0", - "@babel/plugin-transform-classes": "^7.5.5", - "@babel/plugin-transform-computed-properties": "^7.2.0", - "@babel/plugin-transform-destructuring": "^7.6.0", "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/plugin-transform-duplicate-keys": "^7.5.0", - "@babel/plugin-transform-exponentiation-operator": "^7.2.0", - "@babel/plugin-transform-for-of": "^7.4.4", - "@babel/plugin-transform-function-name": "^7.4.4", - "@babel/plugin-transform-literals": "^7.2.0", - "@babel/plugin-transform-member-expression-literals": "^7.2.0", - "@babel/plugin-transform-modules-amd": "^7.5.0", - "@babel/plugin-transform-modules-commonjs": "^7.6.0", - "@babel/plugin-transform-modules-systemjs": "^7.5.0", - "@babel/plugin-transform-modules-umd": "^7.2.0", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.6.0", - "@babel/plugin-transform-new-target": "^7.4.4", - "@babel/plugin-transform-object-super": "^7.5.5", - "@babel/plugin-transform-parameters": "^7.4.4", - "@babel/plugin-transform-property-literals": "^7.2.0", - "@babel/plugin-transform-regenerator": "^7.4.5", - "@babel/plugin-transform-reserved-words": "^7.2.0", - "@babel/plugin-transform-shorthand-properties": "^7.2.0", - "@babel/plugin-transform-spread": "^7.2.0", - "@babel/plugin-transform-sticky-regex": "^7.2.0", - "@babel/plugin-transform-template-literals": "^7.4.4", - "@babel/plugin-transform-typeof-symbol": "^7.2.0", - "@babel/plugin-transform-unicode-regex": "^7.4.4", - "@babel/types": "^7.6.0", - "browserslist": "^4.6.0", - "core-js-compat": "^3.1.1", - "invariant": "^2.2.2", - "js-levenshtein": "^1.1.3", - "semver": "^5.5.0" + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" } }, "@babel/preset-react": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.0.0.tgz", - "integrity": "sha512-oayxyPS4Zj+hF6Et11BwuBkmpgT/zMxyuZgFrMeZID6Hdh3dGlk4sHCAhdBCpuCKW2ppBfl2uCCetlrUIJRY3w==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.10.4.tgz", + "integrity": "sha512-BrHp4TgOIy4M19JAfO1LhycVXOPWdDbTRep7eVyatf174Hff+6Uk53sDyajqZPu8W1qXRBiYOfIamek6jA7YVw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-transform-react-display-name": "^7.0.0", - "@babel/plugin-transform-react-jsx": "^7.0.0", - "@babel/plugin-transform-react-jsx-self": "^7.0.0", - "@babel/plugin-transform-react-jsx-source": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-transform-react-display-name": "^7.10.4", + "@babel/plugin-transform-react-jsx": "^7.10.4", + "@babel/plugin-transform-react-jsx-development": "^7.10.4", + "@babel/plugin-transform-react-jsx-self": "^7.10.4", + "@babel/plugin-transform-react-jsx-source": "^7.10.4", + "@babel/plugin-transform-react-pure-annotations": "^7.10.4" + }, + "dependencies": { + "@babel/plugin-transform-react-display-name": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.10.4.tgz", + "integrity": "sha512-Zd4X54Mu9SBfPGnEcaGcOrVAYOtjT2on8QZkLKEq1S/tHexG39d9XXGZv19VfRrDjPJzFmPfTAqOQS1pfFOujw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + } } }, "@babel/preset-typescript": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.6.0.tgz", - "integrity": "sha512-4xKw3tTcCm0qApyT6PqM9qniseCE79xGHiUnNdKGdxNsGUc2X7WwZybqIpnTmoukg3nhPceI5KPNzNqLNeIJww==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.9.0.tgz", + "integrity": "sha512-S4cueFnGrIbvYJgwsVFKdvOmpiL0XGw9MFW9D0vgRys5g36PBhZRL8NX8Gr2akz8XRtzq6HuDXPD/1nniagNUg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-transform-typescript": "^7.6.0" + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-transform-typescript": "^7.9.0" } }, "@babel/runtime": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.8.4.tgz", - "integrity": "sha512-neAp3zt80trRVBI1x0azq6c57aNBqYZH8KhMm3TaB7wEI5Q4A2SHfBHE8w9gOhI/lrqxtEbXZgQIrHP+wvSGwQ==", + "version": "7.11.1", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.1.tgz", + "integrity": "sha512-nH5y8fLvVl3HAb+ezbgcgwrH8QbClWo8xzkOu7+oyqngo3EVorwpWJQaqXPjGRpfj7mQvsJCl/S8knkfkPWqrw==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/runtime-corejs3": { + "version": "7.11.1", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.11.1.tgz", + "integrity": "sha512-0gB7HCuTwvPxyCMWJTsRqh8muWkWR6U2c/o5x+oTJPR0xzaFl+thzQxHv4kzMkQadRIhe6KW1D/q1yVrjXmsKA==", + "dev": true, "requires": { - "regenerator-runtime": "^0.13.2" + "core-js-pure": "^3.0.0", + "regenerator-runtime": "^0.13.4" } }, "@babel/template": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.3.tgz", - "integrity": "sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", + "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", "dev": true, "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/parser": "^7.8.3", - "@babel/types": "^7.8.3" + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/traverse": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.8.4.tgz", - "integrity": "sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.0.tgz", + "integrity": "sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg==", "dev": true, "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.8.4", - "@babel/helper-function-name": "^7.8.3", - "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/parser": "^7.8.4", - "@babel/types": "^7.8.3", + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.11.0", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/parser": "^7.11.0", + "@babel/types": "^7.11.0", "debug": "^4.1.0", "globals": "^11.1.0", - "lodash": "^4.17.13" + "lodash": "^4.17.19" }, "dependencies": { "debug": { @@ -1163,6 +1437,12 @@ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true }, + "lodash": { + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", + "dev": true + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -1172,16 +1452,22 @@ } }, "@babel/types": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.8.3.tgz", - "integrity": "sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", + "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", "dev": true, "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", "to-fast-properties": "^2.0.0" }, "dependencies": { + "lodash": { + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", + "dev": true + }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -1190,12 +1476,6 @@ } } }, - "@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true - }, "@cnakazawa/watch": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@cnakazawa/watch/-/watch-1.0.4.tgz", @@ -1213,9 +1493,9 @@ "dev": true }, "@csstools/normalize.css": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-9.0.1.tgz", - "integrity": "sha512-6It2EVfGskxZCQhuykrfnALg7oVeiI6KclWSmGDqB0AiInVrTGB9Jp9i4/Ad21u9Jde/voVQz6eFX/eSg/UsPA==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@csstools/normalize.css/-/normalize.css-10.1.0.tgz", + "integrity": "sha512-ij4wRiunFfaJxjB0BdrYHIH8FxBJpOwNPhhAcunlmPdXudL1WQV1qoP9un6JsEBAgQH+7UXyyjh0g7jTxXK6tg==", "dev": true }, "@hapi/address": { @@ -1257,575 +1537,210 @@ "@hapi/hoek": "^8.3.0" } }, - "@istanbuljs/load-nyc-config": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz", - "integrity": "sha512-ZR0rq/f/E4f4XcgnDvtMWXCUJpi8eO0rssVhmztsZqLIEFA9UUP9zmpE0VxlM+kv/E1ul2I876Fwil2ayptDVg==", + "@jest/console": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", + "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", "dev": true, "requires": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" + "@jest/source-map": "^24.9.0", + "chalk": "^2.0.1", + "slash": "^2.0.0" + } + }, + "@jest/core": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-24.9.0.tgz", + "integrity": "sha512-Fogg3s4wlAr1VX7q+rhV9RVnUv5tD7VuWfYy1+whMiWUrvl7U3QJSJyWcDio9Lq2prqYsZaeTv2Rz24pWGkJ2A==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/reporters": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "graceful-fs": "^4.1.15", + "jest-changed-files": "^24.9.0", + "jest-config": "^24.9.0", + "jest-haste-map": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-resolve-dependencies": "^24.9.0", + "jest-runner": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-snapshot": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "jest-watcher": "^24.9.0", + "micromatch": "^3.1.10", + "p-each-series": "^1.0.0", + "realpath-native": "^1.1.0", + "rimraf": "^2.5.4", + "slash": "^2.0.0", + "strip-ansi": "^5.0.0" }, "dependencies": { - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", "dev": true } } }, - "@istanbuljs/schema": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", - "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", - "dev": true + "@jest/environment": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-24.9.0.tgz", + "integrity": "sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ==", + "dev": true, + "requires": { + "@jest/fake-timers": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0" + } }, - "@jest/console": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-26.0.1.tgz", - "integrity": "sha512-9t1KUe/93coV1rBSxMmBAOIK3/HVpwxArCA1CxskKyRiv6o8J70V8C/V3OJminVCTa2M0hQI9AWRd5wxu2dAHw==", + "@jest/fake-timers": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", + "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-mock": "^24.9.0" + } + }, + "@jest/reporters": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-24.9.0.tgz", + "integrity": "sha512-mu4X0yjaHrffOsWmVLzitKmmmWSQ3GGuefgNscUSWNiUNcEOSEQk9k3pERKEQVBb0Cnn88+UESIsZEMH3o88Gw==", "dev": true, "requires": { - "@jest/types": "^26.0.1", - "chalk": "^4.0.0", - "jest-message-util": "^26.0.1", - "jest-util": "^26.0.1", - "slash": "^3.0.0" + "@jest/environment": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "glob": "^7.1.2", + "istanbul-lib-coverage": "^2.0.2", + "istanbul-lib-instrument": "^3.0.1", + "istanbul-lib-report": "^2.0.4", + "istanbul-lib-source-maps": "^3.0.1", + "istanbul-reports": "^2.2.6", + "jest-haste-map": "^24.9.0", + "jest-resolve": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.6.0", + "node-notifier": "^5.4.2", + "slash": "^2.0.0", + "source-map": "^0.6.0", + "string-length": "^2.0.0" }, "dependencies": { - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", - "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "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 - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } } } }, - "@jest/core": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-26.0.1.tgz", - "integrity": "sha512-Xq3eqYnxsG9SjDC+WLeIgf7/8KU6rddBxH+SCt18gEpOhAGYC/Mq+YbtlNcIdwjnnT+wDseXSbU0e5X84Y4jTQ==", + "@jest/source-map": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", + "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", "dev": true, "requires": { - "@jest/console": "^26.0.1", - "@jest/reporters": "^26.0.1", - "@jest/test-result": "^26.0.1", - "@jest/transform": "^26.0.1", - "@jest/types": "^26.0.1", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.4", - "jest-changed-files": "^26.0.1", - "jest-config": "^26.0.1", - "jest-haste-map": "^26.0.1", - "jest-message-util": "^26.0.1", - "jest-regex-util": "^26.0.0", - "jest-resolve": "^26.0.1", - "jest-resolve-dependencies": "^26.0.1", - "jest-runner": "^26.0.1", - "jest-runtime": "^26.0.1", - "jest-snapshot": "^26.0.1", - "jest-util": "^26.0.1", - "jest-validate": "^26.0.1", - "jest-watcher": "^26.0.1", - "micromatch": "^4.0.2", - "p-each-series": "^2.1.0", - "rimraf": "^3.0.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" + "callsites": "^3.0.0", + "graceful-fs": "^4.1.15", + "source-map": "^0.6.0" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", - "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "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 - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } } } }, - "@jest/environment": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-26.0.1.tgz", - "integrity": "sha512-xBDxPe8/nx251u0VJ2dFAFz2H23Y98qdIaNwnMK6dFQr05jc+Ne/2np73lOAx+5mSBO/yuQldRrQOf6hP1h92g==", + "@jest/test-result": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", + "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", "dev": true, "requires": { - "@jest/fake-timers": "^26.0.1", - "@jest/types": "^26.0.1", - "jest-mock": "^26.0.1" + "@jest/console": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/istanbul-lib-coverage": "^2.0.0" } }, - "@jest/fake-timers": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-26.0.1.tgz", - "integrity": "sha512-Oj/kCBnTKhm7CR+OJSjZty6N1bRDr9pgiYQr4wY221azLz5PHi08x/U+9+QpceAYOWheauLP8MhtSVFrqXQfhg==", + "@jest/test-sequencer": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-24.9.0.tgz", + "integrity": "sha512-6qqsU4o0kW1dvA95qfNog8v8gkRN9ph6Lz7r96IvZpHdNipP2cBcb07J1Z45mz/VIS01OHJ3pY8T5fUY38tg4A==", "dev": true, "requires": { - "@jest/types": "^26.0.1", - "@sinonjs/fake-timers": "^6.0.1", - "jest-message-util": "^26.0.1", - "jest-mock": "^26.0.1", - "jest-util": "^26.0.1" + "@jest/test-result": "^24.9.0", + "jest-haste-map": "^24.9.0", + "jest-runner": "^24.9.0", + "jest-runtime": "^24.9.0" } }, - "@jest/globals": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-26.0.1.tgz", - "integrity": "sha512-iuucxOYB7BRCvT+TYBzUqUNuxFX1hqaR6G6IcGgEqkJ5x4htNKo1r7jk1ji9Zj8ZMiMw0oB5NaA7k5Tx6MVssA==", + "@jest/transform": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-24.9.0.tgz", + "integrity": "sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ==", "dev": true, "requires": { - "@jest/environment": "^26.0.1", - "@jest/types": "^26.0.1", - "expect": "^26.0.1" - } - }, - "@jest/reporters": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-26.0.1.tgz", - "integrity": "sha512-NWWy9KwRtE1iyG/m7huiFVF9YsYv/e+mbflKRV84WDoJfBqUrNRyDbL/vFxQcYLl8IRqI4P3MgPn386x76Gf2g==", - "dev": true, - "requires": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^26.0.1", - "@jest/test-result": "^26.0.1", - "@jest/transform": "^26.0.1", - "@jest/types": "^26.0.1", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.2", - "graceful-fs": "^4.2.4", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^4.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.0.2", - "jest-haste-map": "^26.0.1", - "jest-resolve": "^26.0.1", - "jest-util": "^26.0.1", - "jest-worker": "^26.0.0", - "node-notifier": "^7.0.0", - "slash": "^3.0.0", - "source-map": "^0.6.0", - "string-length": "^4.0.1", - "terminal-link": "^2.0.0", - "v8-to-istanbul": "^4.1.3" + "@babel/core": "^7.1.0", + "@jest/types": "^24.9.0", + "babel-plugin-istanbul": "^5.1.0", + "chalk": "^2.0.1", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.1.15", + "jest-haste-map": "^24.9.0", + "jest-regex-util": "^24.9.0", + "jest-util": "^24.9.0", + "micromatch": "^3.1.10", + "pirates": "^4.0.1", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "2.4.1" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "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 - }, - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", - "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "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 - }, - "string-length": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.1.tgz", - "integrity": "sha512-PKyXUd0LK0ePjSOnWn34V2uD6acUWev9uy0Ft05k0E8xRW+SKcA0F7eMr7h5xlzfn+4O3N+55rduYyet3Jk+jw==", - "dev": true, - "requires": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "@jest/source-map": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-26.0.0.tgz", - "integrity": "sha512-S2Z+Aj/7KOSU2TfW0dyzBze7xr95bkm5YXNUqqCek+HE0VbNNSNzrRwfIi5lf7wvzDTSS0/ib8XQ1krFNyYgbQ==", - "dev": true, - "requires": { - "callsites": "^3.0.0", - "graceful-fs": "^4.2.4", - "source-map": "^0.6.0" - }, - "dependencies": { - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, - "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 - } - } - }, - "@jest/test-result": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-26.0.1.tgz", - "integrity": "sha512-oKwHvOI73ICSYRPe8WwyYPTtiuOAkLSbY8/MfWF3qDEd/sa8EDyZzin3BaXTqufir/O/Gzea4E8Zl14XU4Mlyg==", - "dev": true, - "requires": { - "@jest/console": "^26.0.1", - "@jest/types": "^26.0.1", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - } - }, - "@jest/test-sequencer": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-26.0.1.tgz", - "integrity": "sha512-ssga8XlwfP8YjbDcmVhwNlrmblddMfgUeAkWIXts1V22equp2GMIHxm7cyeD5Q/B0ZgKPK/tngt45sH99yLLGg==", - "dev": true, - "requires": { - "@jest/test-result": "^26.0.1", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^26.0.1", - "jest-runner": "^26.0.1", - "jest-runtime": "^26.0.1" - }, - "dependencies": { - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - } - } - }, - "@jest/transform": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-26.0.1.tgz", - "integrity": "sha512-pPRkVkAQ91drKGbzCfDOoHN838+FSbYaEAvBXvKuWeeRRUD8FjwXkqfUNUZL6Ke48aA/1cqq/Ni7kVMCoqagWA==", - "dev": true, - "requires": { - "@babel/core": "^7.1.0", - "@jest/types": "^26.0.1", - "babel-plugin-istanbul": "^6.0.0", - "chalk": "^4.0.0", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^26.0.1", - "jest-regex-util": "^26.0.0", - "jest-util": "^26.0.1", - "micromatch": "^4.0.2", - "pirates": "^4.0.1", - "slash": "^3.0.0", - "source-map": "^0.6.1", - "write-file-atomic": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", - "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "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 - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } } } }, "@jest/types": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.0.1.tgz", - "integrity": "sha512-IbtjvqI9+eS1qFnOIEL7ggWmT+iK/U+Vde9cGWtYb/b6XgKb3X44ZAe/z9YZzoAAZ/E92m0DqrilF934IGNnQA==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", + "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", "dev": true, "requires": { "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", - "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "@types/yargs": "^13.0.0" } }, "@mrmlnc/readdir-enhanced": { @@ -1844,24 +1759,6 @@ "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", "dev": true }, - "@sinonjs/commons": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.7.2.tgz", - "integrity": "sha512-+DUO6pnp3udV/v2VfUWgaY5BIE1IfT7lLfeDzPVeMT1XKkaAp9LgSI9x5RtrFQoZ9Oi0PgXQQHPaoKu7dCjVxw==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/fake-timers": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", - "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0" - } - }, "@svgr/babel-plugin-add-jsx-attribute": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-4.2.0.tgz", @@ -1970,25 +1867,25 @@ } }, "@svgr/webpack": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-4.3.2.tgz", - "integrity": "sha512-F3VE5OvyOWBEd2bF7BdtFRyI6E9it3mN7teDw0JQTlVtc4HZEYiiLSl+Uf9Uub6IYHVGc+qIrxxDyeedkQru2w==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-4.3.3.tgz", + "integrity": "sha512-bjnWolZ6KVsHhgyCoYRFmbd26p8XVbulCzSG53BDQqAr+JOAderYK7CuYrB3bDjHJuF6LJ7Wrr42+goLRV9qIg==", "dev": true, "requires": { "@babel/core": "^7.4.5", "@babel/plugin-transform-react-constant-elements": "^7.0.0", "@babel/preset-env": "^7.4.5", "@babel/preset-react": "^7.0.0", - "@svgr/core": "^4.3.2", - "@svgr/plugin-jsx": "^4.3.2", + "@svgr/core": "^4.3.3", + "@svgr/plugin-jsx": "^4.3.3", "@svgr/plugin-svgo": "^4.3.1", "loader-utils": "^1.2.3" } }, "@types/babel__core": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.4.tgz", - "integrity": "sha512-c/5MuRz5HM4aizqL5ViYfW4iEnmfPcfbH4Xa6GgLT21dMc1NGeNnuS6egHheOmP+kCJ9CAzC4pv4SDCWTnRkbg==", + "version": "7.1.9", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.9.tgz", + "integrity": "sha512-sY2RsIJ5rpER1u3/aQ8OFSI7qGIy8o1NEEbgb2UaJcvOtXOMpd39ko723NBpjQFg9SIX7TXtjejZVGeIMLhoOw==", "dev": true, "requires": { "@babel/parser": "^7.1.0", @@ -2018,9 +1915,9 @@ } }, "@types/babel__traverse": { - "version": "7.0.8", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.8.tgz", - "integrity": "sha512-yGeB2dHEdvxjP0y4UbRtQaSkXJ9649fYCmIdRoul5kfAoGCwxuCbMhag0k3RPfnuh9kPGm8x89btcfDEXdVWGw==", + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.13.tgz", + "integrity": "sha512-i+zS7t6/s9cdQvbqKDARrcbrPvtJGlbYsMkazo03nTAK3RX9FNrLllXys22uiTGJapPOTZTQ35nHh4ISph4SLQ==", "dev": true, "requires": { "@babel/types": "^7.3.0" @@ -2038,19 +1935,20 @@ "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==", "dev": true }, - "@types/graceful-fs": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.3.tgz", - "integrity": "sha512-AiHRaEB50LQg0pZmm659vNBb9f4SJ0qrAnteuzhSeAUcJKxoYgEnprg/83kppCnc2zvtCKbdZry1a5pVY3lOTQ==", + "@types/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", "dev": true, "requires": { + "@types/minimatch": "*", "@types/node": "*" } }, "@types/istanbul-lib-coverage": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz", - "integrity": "sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz", + "integrity": "sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==", "dev": true }, "@types/istanbul-lib-report": { @@ -2063,9 +1961,9 @@ } }, "@types/istanbul-reports": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz", - "integrity": "sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz", + "integrity": "sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw==", "dev": true, "requires": { "@types/istanbul-lib-coverage": "*", @@ -2073,33 +1971,33 @@ } }, "@types/json-schema": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.4.tgz", - "integrity": "sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.5.tgz", + "integrity": "sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ==", "dev": true }, - "@types/node": { - "version": "13.7.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-13.7.1.tgz", - "integrity": "sha512-Zq8gcQGmn4txQEJeiXo/KiLpon8TzAl0kmKH4zdWctPj05nWwp1ClMdAVEloqrQKfaC48PNLdgN/aVaLqUrluA==", + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", "dev": true }, - "@types/normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==", + "@types/node": { + "version": "14.0.27", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.27.tgz", + "integrity": "sha512-kVrqXhbclHNHGu9ztnAwSncIgJv/FaxmzXJvGXNdcCpV1b8u1/Mi6z6m0vwy0LzKeXFTPLH0NzwmoJ3fNCIq0g==", "dev": true }, - "@types/prettier": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.0.0.tgz", - "integrity": "sha512-/rM+sWiuOZ5dvuVzV37sUuklsbg+JPOP8d+nNFlo2ZtfpzPiPvh1/gc8liWOLBqe+sR+ZM7guPaIcTt6UZTo7Q==", + "@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", "dev": true }, "@types/q": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.2.tgz", - "integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz", + "integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==", "dev": true }, "@types/stack-utils": { @@ -2109,9 +2007,9 @@ "dev": true }, "@types/yargs": { - "version": "15.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.4.tgz", - "integrity": "sha512-9T1auFmbPZoxHz0enUFlUuKRy3it01R+hlggyVUMtnCTQRunsQYifnSGb8hET4Xo8yiC0o0r1paW3ud5+rbURg==", + "version": "13.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.9.tgz", + "integrity": "sha512-xrvhZ4DZewMDhoH1utLtOAwYQy60eYFoXeje30TzM3VOvQlBwQaEpKFq5m34k1wOw2AKIi2pwtiAjdmhvlBUzg==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -2124,45 +2022,45 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "2.19.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.19.2.tgz", - "integrity": "sha512-HX2qOq2GOV04HNrmKnTpSIpHjfl7iwdXe3u/Nvt+/cpmdvzYvY0NHSiTkYN257jHnq4OM/yo+OsFgati+7LqJA==", + "version": "2.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.34.0.tgz", + "integrity": "sha512-4zY3Z88rEE99+CNvTbXSyovv2z9PNOVffTWD2W8QF5s2prBQtwN2zadqERcrHpcR7O/+KMI3fcTAmUUhK/iQcQ==", "dev": true, "requires": { - "@typescript-eslint/experimental-utils": "2.19.2", - "eslint-utils": "^1.4.3", + "@typescript-eslint/experimental-utils": "2.34.0", "functional-red-black-tree": "^1.0.1", "regexpp": "^3.0.0", "tsutils": "^3.17.1" } }, "@typescript-eslint/experimental-utils": { - "version": "2.19.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.19.2.tgz", - "integrity": "sha512-B88QuwT1wMJR750YvTJBNjMZwmiPpbmKYLm1yI7PCc3x0NariqPwqaPsoJRwU9DmUi0cd9dkhz1IqEnwfD+P1A==", + "version": "2.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.34.0.tgz", + "integrity": "sha512-eS6FTkq+wuMJ+sgtuNTtcqavWXqsflWcfBnlYhg/nS4aZ1leewkXGbvBhaapn1q6qf4M71bsR1tez5JTRMuqwA==", "dev": true, "requires": { "@types/json-schema": "^7.0.3", - "@typescript-eslint/typescript-estree": "2.19.2", - "eslint-scope": "^5.0.0" + "@typescript-eslint/typescript-estree": "2.34.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^2.0.0" } }, "@typescript-eslint/parser": { - "version": "2.19.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.19.2.tgz", - "integrity": "sha512-8uwnYGKqX9wWHGPGdLB9sk9+12sjcdqEEYKGgbS8A0IvYX59h01o8os5qXUHMq2na8vpDRaV0suTLM7S8wraTA==", + "version": "2.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.34.0.tgz", + "integrity": "sha512-03ilO0ucSD0EPTw2X4PntSIRFtDPWjrVq7C3/Z3VQHRC7+13YB55rcJI3Jt+YgeHbjUdJPcPa7b23rXCBokuyA==", "dev": true, "requires": { "@types/eslint-visitor-keys": "^1.0.0", - "@typescript-eslint/experimental-utils": "2.19.2", - "@typescript-eslint/typescript-estree": "2.19.2", + "@typescript-eslint/experimental-utils": "2.34.0", + "@typescript-eslint/typescript-estree": "2.34.0", "eslint-visitor-keys": "^1.1.0" } }, "@typescript-eslint/typescript-estree": { - "version": "2.19.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.19.2.tgz", - "integrity": "sha512-Xu/qa0MDk6upQWqE4Qy2X16Xg8Vi32tQS2PR0AvnT/ZYS4YGDvtn2MStOh5y8Zy2mg4NuL06KUHlvCh95j9C6Q==", + "version": "2.34.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.34.0.tgz", + "integrity": "sha512-OMAr+nJWKdlVM9LOqCqh3pQQPwxHAN7Du8DR6dmwCrAmxtiXQnhHJ6tBNtf+cggqfo51SG/FCwnKhXCIM7hnVg==", "dev": true, "requires": { "debug": "^4.1.1", @@ -2170,7 +2068,7 @@ "glob": "^7.1.6", "is-glob": "^4.0.1", "lodash": "^4.17.15", - "semver": "^6.3.0", + "semver": "^7.3.2", "tsutils": "^3.17.1" }, "dependencies": { @@ -2190,9 +2088,9 @@ "dev": true }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", "dev": true } } @@ -2386,9 +2284,9 @@ "dev": true }, "abab": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.3.tgz", - "integrity": "sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.4.tgz", + "integrity": "sha512-Eu9ELJWCz/c1e9gTiCY+FceWxcqzjYEbqMgtndnuSqZSUCOL73TWNK2mHfIj4Cw2E/ongOp+JISVNCmovt2KYQ==", "dev": true }, "accepts": { @@ -2402,9 +2300,9 @@ } }, "acorn": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", - "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz", + "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==", "dev": true }, "acorn-globals": { @@ -2418,17 +2316,17 @@ }, "dependencies": { "acorn": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz", - "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", + "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", "dev": true } } }, "acorn-jsx": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz", - "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz", + "integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==", "dev": true }, "acorn-walk": { @@ -2461,9 +2359,45 @@ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", "dev": true + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true + }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", + "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^2.0.0", + "json5": "^1.0.1" + } } } }, + "aggregate-error": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz", + "integrity": "sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA==", + "dev": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, "airbnb-prop-types": { "version": "2.15.0", "resolved": "https://registry.npmjs.org/airbnb-prop-types/-/airbnb-prop-types-2.15.0.tgz", @@ -2483,9 +2417,9 @@ } }, "ajv": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz", - "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==", + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz", + "integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -2501,9 +2435,9 @@ "dev": true }, "ajv-keywords": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", - "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "dev": true }, "alphanum-sort": { @@ -2519,12 +2453,20 @@ "dev": true }, "ansi-escapes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.0.tgz", - "integrity": "sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", + "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", "dev": true, "requires": { - "type-fest": "^0.8.1" + "type-fest": "^0.11.0" + }, + "dependencies": { + "type-fest": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", + "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", + "dev": true + } } }, "ansi-html": { @@ -2534,25 +2476,60 @@ "dev": true }, "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true }, "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } }, "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "dev": true, "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } } }, "aproba": { @@ -2704,6 +2681,14 @@ "bn.js": "^4.0.0", "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } } }, "assert": { @@ -2773,55 +2758,18 @@ "dev": true }, "autoprefixer": { - "version": "9.7.4", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.7.4.tgz", - "integrity": "sha512-g0Ya30YrMBAEZk60lp+qfX5YQllG+S5W3GYCFvyHTvhOki0AEQJLPEcIuGRsqVwLi8FvXPVtwTGhfr38hVpm0g==", + "version": "9.8.6", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.6.tgz", + "integrity": "sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg==", "dev": true, "requires": { - "browserslist": "^4.8.3", - "caniuse-lite": "^1.0.30001020", - "chalk": "^2.4.2", + "browserslist": "^4.12.0", + "caniuse-lite": "^1.0.30001109", + "colorette": "^1.2.1", "normalize-range": "^0.1.2", "num2fraction": "^1.2.2", - "postcss": "^7.0.26", - "postcss-value-parser": "^4.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "postcss-value-parser": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.0.2.tgz", - "integrity": "sha512-LmeoohTpp/K4UiyQCwuGWlONxXamGzCMtFxLq4W1nZVGIQLYvMCJx3yAF9qyyuFpflABI9yVdtJAqbihOsCsJQ==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } + "postcss": "^7.0.32", + "postcss-value-parser": "^4.1.0" } }, "aws-sign2": { @@ -2831,15 +2779,15 @@ "dev": true }, "aws4": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", - "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.0.tgz", + "integrity": "sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA==", "dev": true }, "axobject-query": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.1.2.tgz", - "integrity": "sha512-ICt34ZmrVt8UQnvPl6TVyDTkmhXmAyAT4Jh5ugfGUX4MOrZ+U/ZY6/sdylRw3qGNr9Ub5AJsaHeDMzNLehRdOQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", + "integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==", "dev": true }, "babel-code-frame": { @@ -2853,24 +2801,64 @@ "js-tokens": "^3.0.2" }, "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, "js-tokens": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true } } }, "babel-eslint": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.0.3.tgz", - "integrity": "sha512-z3U7eMY6r/3f3/JB9mTsLjyxrv0Yb1zb8PCWCLpguxfCzBIZUwy23R1t/XKewP+8mEN2Ck8Dtr4q20z6ce6SoA==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", + "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.0.0", - "@babel/traverse": "^7.0.0", - "@babel/types": "^7.0.0", + "@babel/parser": "^7.7.0", + "@babel/traverse": "^7.7.0", + "@babel/types": "^7.7.0", "eslint-visitor-keys": "^1.0.0", "resolve": "^1.12.0" } @@ -2884,555 +2872,136 @@ "babylon": "^6.18.0" } }, - "babel-helper-builder-react-jsx": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.26.0.tgz", - "integrity": "sha1-Of+DE7dci2Xc7/HzHTg+D/KkCKA=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "esutils": "^2.0.2" - } - }, - "babel-helper-call-delegate": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", - "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", - "dev": true, - "requires": { - "babel-helper-hoist-variables": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-define-map": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", - "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - } - }, - "babel-helper-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", - "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "babel-jest": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-24.9.0.tgz", + "integrity": "sha512-ntuddfyiN+EhMw58PTNL1ph4C9rECiQXjI4nMMBKBaNjXvqLdkXpPRcMSr4iyBrJg/+wz9brFUD6RhOAT6r4Iw==", "dev": true, "requires": { - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/babel__core": "^7.1.0", + "babel-plugin-istanbul": "^5.1.0", + "babel-preset-jest": "^24.9.0", + "chalk": "^2.4.2", + "slash": "^2.0.0" } }, - "babel-helper-get-function-arity": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", - "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "babel-loader": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.1.0.tgz", + "integrity": "sha512-7q7nC1tYOrqvUrN3LQK4GwSk/TQorZSOlO9C+RZDZpODgyN4ZlCqE5q9cDsyWOliN+aU9B4JX01xK9eJXowJLw==", "dev": true, "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "find-cache-dir": "^2.1.0", + "loader-utils": "^1.4.0", + "mkdirp": "^0.5.3", + "pify": "^4.0.1", + "schema-utils": "^2.6.5" } }, - "babel-helper-hoist-variables": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", - "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", + "babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", "dev": true, "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "object.assign": "^4.1.0" } }, - "babel-helper-optimise-call-expression": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", - "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "babel-plugin-istanbul": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz", + "integrity": "sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw==", "dev": true, "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" + "@babel/helper-plugin-utils": "^7.0.0", + "find-up": "^3.0.0", + "istanbul-lib-instrument": "^3.3.0", + "test-exclude": "^5.2.3" } }, - "babel-helper-regex": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", - "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", + "babel-plugin-jest-hoist": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.9.0.tgz", + "integrity": "sha512-2EMA2P8Vp7lG0RAzr4HXqtYwacfMErOuv1U3wrvxHX6rD1sV6xS3WXG3r8TRQ2r6w8OhvSdWt+z41hQNwNm3Xw==", "dev": true, "requires": { - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" + "@types/babel__traverse": "^7.0.6" } }, - "babel-helper-replace-supers": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", - "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "babel-plugin-macros": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz", + "integrity": "sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==", "dev": true, "requires": { - "babel-helper-optimise-call-expression": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-jest": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.0.1.tgz", - "integrity": "sha512-Z4GGmSNQ8pX3WS1O+6v3fo41YItJJZsVxG5gIQ+HuB/iuAQBJxMTHTwz292vuYws1LnHfwSRgoqI+nxdy/pcvw==", - "dev": true, - "requires": { - "@jest/transform": "^26.0.1", - "@jest/types": "^26.0.1", - "@types/babel__core": "^7.1.7", - "babel-plugin-istanbul": "^6.0.0", - "babel-preset-jest": "^26.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "slash": "^3.0.0" + "@babel/runtime": "^7.7.2", + "cosmiconfig": "^6.0.0", + "resolve": "^1.12.0" }, "dependencies": { - "@types/babel__core": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.7.tgz", - "integrity": "sha512-RL62NqSFPCDK2FM1pSDH0scHpJvsXtZNiYlMB73DgPBaG1E38ZYVL+ei5EkWRbr+KC4YNiAUNBnRj+bgwpgjMw==", - "dev": true, - "requires": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" } }, - "chalk": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", - "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", + "import-fresh": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", "dev": true, "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" } }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "parse-json": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.1.tgz", + "integrity": "sha512-ztoZ4/DYeXQq4E21v169sC8qWINGpcosGv9XhTDvg9/hWvx/zrFkc9BiWxR58OJLHGk28j5BL0SDLeV2WmFZlQ==", "dev": true, "requires": { - "color-name": "~1.1.4" + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1", + "lines-and-columns": "^1.1.6" } }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, - "has-flag": { + "path-type": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "babel-loader": { - "version": "8.0.6", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.6.tgz", - "integrity": "sha512-4BmWKtBOBm13uoUwd08UwjZlaw3O9GWf456R9j+5YykFZ6LUIjIKLc0zEZf+hauxPOJs96C8k6FvYD09vWzhYw==", - "dev": true, - "requires": { - "find-cache-dir": "^2.0.0", - "loader-utils": "^1.0.2", - "mkdirp": "^0.5.1", - "pify": "^4.0.1" - }, - "dependencies": { - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true } } }, - "babel-messages": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-check-es2015-constants": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", - "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-dynamic-import-node": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", - "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==", - "dev": true, - "requires": { - "object.assign": "^4.1.0" - } - }, - "babel-plugin-external-helpers": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-external-helpers/-/babel-plugin-external-helpers-6.22.0.tgz", - "integrity": "sha1-IoX0iwK9Xe3oUXXK+MYuhq3M76E=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-istanbul": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz", - "integrity": "sha512-AF55rZXpe7trmEylbaE1Gv54wn6rwU03aptvRoVIGP8YykoSxqdVLV1TfwflBCE/QtHmqtP8SWlTENqbK8GCSQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-instrument": "^4.0.0", - "test-exclude": "^6.0.0" - } - }, - "babel-plugin-jest-hoist": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.0.0.tgz", - "integrity": "sha512-+AuoehOrjt9irZL7DOt2+4ZaTM6dlu1s5TTS46JBa0/qem4dy7VNW3tMb96qeEqcIh20LD73TVNtmVEeymTG7w==", - "dev": true, - "requires": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__traverse": "^7.0.6" - } - }, - "babel-plugin-macros": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.6.1.tgz", - "integrity": "sha512-6W2nwiXme6j1n2erPOnmRiWfObUhWH7Qw1LMi9XZy8cj+KtESu3T6asZvtk5bMQQjX8te35o7CFueiSdL/2NmQ==", - "dev": true, - "requires": { - "@babel/runtime": "^7.4.2", - "cosmiconfig": "^5.2.0", - "resolve": "^1.10.0" - } - }, "babel-plugin-named-asset-import": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.6.tgz", "integrity": "sha512-1aGDUfL1qOOIoqk9QKGIo2lANk+C7ko/fqH0uIyC71x3PEGz0uVP8ISgfEsFuG+FKmjHTvFK/nNM8dowpmUxLA==", "dev": true }, - "babel-plugin-syntax-flow": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz", - "integrity": "sha1-TDqyCiryaqIM0lmVw5jE63AxDI0=", - "dev": true - }, - "babel-plugin-syntax-jsx": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", - "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=", - "dev": true - }, "babel-plugin-syntax-object-rest-spread": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", "integrity": "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=", "dev": true }, - "babel-plugin-transform-es2015-arrow-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", - "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-block-scoped-functions": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", - "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-block-scoping": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", - "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "lodash": "^4.17.4" - } - }, - "babel-plugin-transform-es2015-classes": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", - "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", - "dev": true, - "requires": { - "babel-helper-define-map": "^6.24.1", - "babel-helper-function-name": "^6.24.1", - "babel-helper-optimise-call-expression": "^6.24.1", - "babel-helper-replace-supers": "^6.24.1", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-computed-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", - "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-destructuring": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", - "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-duplicate-keys": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", - "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-for-of": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", - "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", - "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", - "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-modules-amd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", - "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", - "dev": true, - "requires": { - "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-modules-commonjs": { - "version": "6.26.2", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", - "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", - "dev": true, - "requires": { - "babel-plugin-transform-strict-mode": "^6.24.1", - "babel-runtime": "^6.26.0", - "babel-template": "^6.26.0", - "babel-types": "^6.26.0" - } - }, - "babel-plugin-transform-es2015-modules-systemjs": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", - "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", - "dev": true, - "requires": { - "babel-helper-hoist-variables": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-modules-umd": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", - "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", - "dev": true, - "requires": { - "babel-plugin-transform-es2015-modules-amd": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-object-super": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", - "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", - "dev": true, - "requires": { - "babel-helper-replace-supers": "^6.24.1", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-parameters": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", - "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", - "dev": true, - "requires": { - "babel-helper-call-delegate": "^6.24.1", - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-shorthand-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", - "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-spread": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", - "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-sticky-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", - "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", - "dev": true, - "requires": { - "babel-helper-regex": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-plugin-transform-es2015-template-literals": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", - "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-typeof-symbol": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", - "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-es2015-unicode-regex": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", - "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", - "dev": true, - "requires": { - "babel-helper-regex": "^6.24.1", - "babel-runtime": "^6.22.0", - "regexpu-core": "^2.0.0" - } - }, - "babel-plugin-transform-flow-strip-types": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz", - "integrity": "sha1-hMtnKTXUNxT9wyvOhFaNh0Qc988=", - "dev": true, - "requires": { - "babel-plugin-syntax-flow": "^6.18.0", - "babel-runtime": "^6.22.0" - } - }, "babel-plugin-transform-object-rest-spread": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.26.0.tgz", @@ -3443,197 +3012,186 @@ "babel-runtime": "^6.26.0" } }, - "babel-plugin-transform-react-display-name": { - "version": "6.25.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.25.0.tgz", - "integrity": "sha1-Z+K/Hx6ck6sI25Z5LgU5K/LMKNE=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-react-jsx": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.24.1.tgz", - "integrity": "sha1-hAoCjn30YN/DotKfDA2R9jduZqM=", - "dev": true, - "requires": { - "babel-helper-builder-react-jsx": "^6.24.1", - "babel-plugin-syntax-jsx": "^6.8.0", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-react-jsx-self": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz", - "integrity": "sha1-322AqdomEqEh5t3XVYvL7PBuY24=", - "dev": true, - "requires": { - "babel-plugin-syntax-jsx": "^6.8.0", - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-transform-react-jsx-source": { - "version": "6.22.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz", - "integrity": "sha1-ZqwSFT9c0tF7PBkmj0vwGX9E7NY=", - "dev": true, - "requires": { - "babel-plugin-syntax-jsx": "^6.8.0", - "babel-runtime": "^6.22.0" - } - }, "babel-plugin-transform-react-remove-prop-types": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz", "integrity": "sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==", "dev": true }, - "babel-plugin-transform-regenerator": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", - "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", - "dev": true, - "requires": { - "regenerator-transform": "^0.10.0" - } - }, - "babel-plugin-transform-strict-mode": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", - "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-preset-current-node-syntax": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-0.1.2.tgz", - "integrity": "sha512-u/8cS+dEiK1SFILbOC8/rUI3ml9lboKuuMvZ/4aQnQmhecQAgPw5ew066C1ObnEAUmlx7dv/s2z52psWEtLNiw==", - "dev": true, - "requires": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.8.3", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3" - } - }, - "babel-preset-es2015": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz", - "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=", - "dev": true, - "requires": { - "babel-plugin-check-es2015-constants": "^6.22.0", - "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", - "babel-plugin-transform-es2015-block-scoping": "^6.24.1", - "babel-plugin-transform-es2015-classes": "^6.24.1", - "babel-plugin-transform-es2015-computed-properties": "^6.24.1", - "babel-plugin-transform-es2015-destructuring": "^6.22.0", - "babel-plugin-transform-es2015-duplicate-keys": "^6.24.1", - "babel-plugin-transform-es2015-for-of": "^6.22.0", - "babel-plugin-transform-es2015-function-name": "^6.24.1", - "babel-plugin-transform-es2015-literals": "^6.22.0", - "babel-plugin-transform-es2015-modules-amd": "^6.24.1", - "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", - "babel-plugin-transform-es2015-modules-systemjs": "^6.24.1", - "babel-plugin-transform-es2015-modules-umd": "^6.24.1", - "babel-plugin-transform-es2015-object-super": "^6.24.1", - "babel-plugin-transform-es2015-parameters": "^6.24.1", - "babel-plugin-transform-es2015-shorthand-properties": "^6.24.1", - "babel-plugin-transform-es2015-spread": "^6.22.0", - "babel-plugin-transform-es2015-sticky-regex": "^6.24.1", - "babel-plugin-transform-es2015-template-literals": "^6.22.0", - "babel-plugin-transform-es2015-typeof-symbol": "^6.22.0", - "babel-plugin-transform-es2015-unicode-regex": "^6.24.1", - "babel-plugin-transform-regenerator": "^6.24.1" - } - }, - "babel-preset-es2015-rollup": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/babel-preset-es2015-rollup/-/babel-preset-es2015-rollup-3.0.0.tgz", - "integrity": "sha1-hUtj7N4u6YysQOiC9nv88YWx8ko=", - "dev": true, - "requires": { - "babel-plugin-external-helpers": "^6.18.0", - "babel-preset-es2015": "^6.3.13", - "require-relative": "^0.8.7" - } - }, - "babel-preset-flow": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz", - "integrity": "sha1-5xIYiHCFrpoktb5Baa/7WZgWxJ0=", - "dev": true, - "requires": { - "babel-plugin-transform-flow-strip-types": "^6.22.0" - } - }, "babel-preset-jest": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-26.0.0.tgz", - "integrity": "sha512-9ce+DatAa31DpR4Uir8g4Ahxs5K4W4L8refzt+qHWQANb6LhGcAEfIFgLUwk67oya2cCUd6t4eUMtO/z64ocNw==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-24.9.0.tgz", + "integrity": "sha512-izTUuhE4TMfTRPF92fFwD2QfdXaZW08qvWTFCI51V8rW5x00UuPgc3ajRoWofXOuxjfcOM5zzSYsQS3H8KGCAg==", "dev": true, "requires": { - "babel-plugin-jest-hoist": "^26.0.0", - "babel-preset-current-node-syntax": "^0.1.2" - } - }, - "babel-preset-react": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz", - "integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=", - "dev": true, - "requires": { - "babel-plugin-syntax-jsx": "^6.3.13", - "babel-plugin-transform-react-display-name": "^6.23.0", - "babel-plugin-transform-react-jsx": "^6.24.1", - "babel-plugin-transform-react-jsx-self": "^6.22.0", - "babel-plugin-transform-react-jsx-source": "^6.22.0", - "babel-preset-flow": "^6.23.0" + "@babel/plugin-syntax-object-rest-spread": "^7.0.0", + "babel-plugin-jest-hoist": "^24.9.0" } }, "babel-preset-react-app": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/babel-preset-react-app/-/babel-preset-react-app-9.0.2.tgz", - "integrity": "sha512-aXD+CTH8Chn8sNJr4tO/trWKqe5sSE4hdO76j9fhVezJSzmpWYWUSc5JoPmdSxADwef5kQFNGKXd433vvkd2VQ==", - "dev": true, - "requires": { - "@babel/core": "7.6.0", - "@babel/plugin-proposal-class-properties": "7.5.5", - "@babel/plugin-proposal-decorators": "7.6.0", - "@babel/plugin-proposal-object-rest-spread": "7.5.5", - "@babel/plugin-syntax-dynamic-import": "7.2.0", - "@babel/plugin-transform-destructuring": "7.6.0", - "@babel/plugin-transform-flow-strip-types": "7.4.4", - "@babel/plugin-transform-react-display-name": "7.2.0", - "@babel/plugin-transform-runtime": "7.6.0", - "@babel/preset-env": "7.6.0", - "@babel/preset-react": "7.0.0", - "@babel/preset-typescript": "7.6.0", - "@babel/runtime": "7.6.0", - "babel-plugin-dynamic-import-node": "2.3.0", - "babel-plugin-macros": "2.6.1", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/babel-preset-react-app/-/babel-preset-react-app-9.1.2.tgz", + "integrity": "sha512-k58RtQOKH21NyKtzptoAvtAODuAJJs3ZhqBMl456/GnXEQ/0La92pNmwgWoMn5pBTrsvk3YYXdY7zpY4e3UIxA==", + "dev": true, + "requires": { + "@babel/core": "7.9.0", + "@babel/plugin-proposal-class-properties": "7.8.3", + "@babel/plugin-proposal-decorators": "7.8.3", + "@babel/plugin-proposal-nullish-coalescing-operator": "7.8.3", + "@babel/plugin-proposal-numeric-separator": "7.8.3", + "@babel/plugin-proposal-optional-chaining": "7.9.0", + "@babel/plugin-transform-flow-strip-types": "7.9.0", + "@babel/plugin-transform-react-display-name": "7.8.3", + "@babel/plugin-transform-runtime": "7.9.0", + "@babel/preset-env": "7.9.0", + "@babel/preset-react": "7.9.1", + "@babel/preset-typescript": "7.9.0", + "@babel/runtime": "7.9.0", + "babel-plugin-macros": "2.8.0", "babel-plugin-transform-react-remove-prop-types": "0.4.24" }, "dependencies": { + "@babel/core": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.9.0.tgz", + "integrity": "sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.9.0", + "@babel/helper-module-transforms": "^7.9.0", + "@babel/helpers": "^7.9.0", + "@babel/parser": "^7.9.0", + "@babel/template": "^7.8.6", + "@babel/traverse": "^7.9.0", + "@babel/types": "^7.9.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + } + }, + "@babel/plugin-transform-runtime": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.9.0.tgz", + "integrity": "sha512-pUu9VSf3kI1OqbWINQ7MaugnitRss1z533436waNXp+0N3ur3zfut37sXiQMxkuCF4VUjwZucen/quskCh7NHw==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "resolve": "^1.8.1", + "semver": "^5.5.1" + } + }, + "@babel/preset-env": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.9.0.tgz", + "integrity": "sha512-712DeRXT6dyKAM/FMbQTV/FvRCms2hPCx+3weRjZ8iQVQWZejWWk1wwG6ViWMyqb/ouBbGOl5b6aCk0+j1NmsQ==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.9.0", + "@babel/helper-compilation-targets": "^7.8.7", + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-proposal-async-generator-functions": "^7.8.3", + "@babel/plugin-proposal-dynamic-import": "^7.8.3", + "@babel/plugin-proposal-json-strings": "^7.8.3", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-proposal-numeric-separator": "^7.8.3", + "@babel/plugin-proposal-object-rest-spread": "^7.9.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.8.3", + "@babel/plugin-proposal-optional-chaining": "^7.9.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.8.3", + "@babel/plugin-syntax-async-generators": "^7.8.0", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-json-strings": "^7.8.0", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", + "@babel/plugin-syntax-numeric-separator": "^7.8.0", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.0", + "@babel/plugin-syntax-top-level-await": "^7.8.3", + "@babel/plugin-transform-arrow-functions": "^7.8.3", + "@babel/plugin-transform-async-to-generator": "^7.8.3", + "@babel/plugin-transform-block-scoped-functions": "^7.8.3", + "@babel/plugin-transform-block-scoping": "^7.8.3", + "@babel/plugin-transform-classes": "^7.9.0", + "@babel/plugin-transform-computed-properties": "^7.8.3", + "@babel/plugin-transform-destructuring": "^7.8.3", + "@babel/plugin-transform-dotall-regex": "^7.8.3", + "@babel/plugin-transform-duplicate-keys": "^7.8.3", + "@babel/plugin-transform-exponentiation-operator": "^7.8.3", + "@babel/plugin-transform-for-of": "^7.9.0", + "@babel/plugin-transform-function-name": "^7.8.3", + "@babel/plugin-transform-literals": "^7.8.3", + "@babel/plugin-transform-member-expression-literals": "^7.8.3", + "@babel/plugin-transform-modules-amd": "^7.9.0", + "@babel/plugin-transform-modules-commonjs": "^7.9.0", + "@babel/plugin-transform-modules-systemjs": "^7.9.0", + "@babel/plugin-transform-modules-umd": "^7.9.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.8.3", + "@babel/plugin-transform-new-target": "^7.8.3", + "@babel/plugin-transform-object-super": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.8.7", + "@babel/plugin-transform-property-literals": "^7.8.3", + "@babel/plugin-transform-regenerator": "^7.8.7", + "@babel/plugin-transform-reserved-words": "^7.8.3", + "@babel/plugin-transform-shorthand-properties": "^7.8.3", + "@babel/plugin-transform-spread": "^7.8.3", + "@babel/plugin-transform-sticky-regex": "^7.8.3", + "@babel/plugin-transform-template-literals": "^7.8.3", + "@babel/plugin-transform-typeof-symbol": "^7.8.4", + "@babel/plugin-transform-unicode-regex": "^7.8.3", + "@babel/preset-modules": "^0.1.3", + "@babel/types": "^7.9.0", + "browserslist": "^4.9.1", + "core-js-compat": "^3.6.2", + "invariant": "^2.2.2", + "levenary": "^1.1.1", + "semver": "^5.5.0" + } + }, + "@babel/preset-react": { + "version": "7.9.1", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.9.1.tgz", + "integrity": "sha512-aJBYF23MPj0RNdp/4bHnAP0NVqqZRr9kl0NAOP4nJCex6OYVio59+dnQzsAWFuogdLyeaKA1hmfUIVZkY5J+TQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-transform-react-display-name": "^7.8.3", + "@babel/plugin-transform-react-jsx": "^7.9.1", + "@babel/plugin-transform-react-jsx-development": "^7.9.0", + "@babel/plugin-transform-react-jsx-self": "^7.9.0", + "@babel/plugin-transform-react-jsx-source": "^7.9.0" + } + }, "@babel/runtime": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.6.0.tgz", - "integrity": "sha512-89eSBLJsxNxOERC0Op4vd+0Bqm6wRMqMbFtV3i0/fbaWw/mJ8Q3eBvgX0G4SyrOOLCtbu98HspF8o09MRT+KzQ==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.0.tgz", + "integrity": "sha512-cTIudHnzuWLS56ik4DnRnqqNf8MkdUzV4iFFI1h7Jo9xvrpQROYaAnaSd2mHLQAzzZAPfATynX5ord6YlNYNMA==", "dev": true, "requires": { - "regenerator-runtime": "^0.13.2" + "regenerator-runtime": "^0.13.4" } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "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 } } }, @@ -3647,6 +3205,12 @@ "regenerator-runtime": "^0.11.0" }, "dependencies": { + "core-js": { + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", + "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", + "dev": true + }, "regenerator-runtime": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", @@ -3655,48 +3219,6 @@ } } }, - "babel-template": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "lodash": "^4.17.4" - } - }, - "babel-traverse": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", - "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "debug": "^2.6.8", - "globals": "^9.18.0", - "invariant": "^2.2.2", - "lodash": "^4.17.4" - } - }, - "babel-types": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" - } - }, "babylon": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", @@ -3814,9 +3336,9 @@ "dev": true }, "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.2.tgz", + "integrity": "sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA==", "dev": true }, "body-parser": { @@ -3882,24 +3404,44 @@ } }, "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, "requires": { - "fill-range": "^7.0.1" - } - }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", - "dev": true - }, - "browser-process-hrtime": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz", - "integrity": "sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw==", + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", "dev": true }, "browser-resolve": { @@ -3964,21 +3506,39 @@ "requires": { "bn.js": "^4.1.0", "randombytes": "^2.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } } }, "browserify-sign": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", - "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", "dev": true, "requires": { - "bn.js": "^4.1.1", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.2", - "elliptic": "^6.0.0", - "inherits": "^2.0.1", - "parse-asn1": "^5.0.0" + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } } }, "browserify-zlib": { @@ -3991,14 +3551,15 @@ } }, "browserslist": { - "version": "4.8.7", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.8.7.tgz", - "integrity": "sha512-gFOnZNYBHrEyUML0xr5NJ6edFaaKbTFX9S9kQHlYfCP0Rit/boRIz4G+Avq6/4haEKJXdGGUnoolx+5MWW2BoA==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.13.0.tgz", + "integrity": "sha512-MINatJ5ZNrLnQ6blGvePd/QOz9Xtu+Ne+x29iQSCHfkU5BugKVJwZKn/iiL8UbpIpa3JhviKjz+XxMo0m2caFQ==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001027", - "electron-to-chromium": "^1.3.349", - "node-releases": "^1.1.49" + "caniuse-lite": "^1.0.30001093", + "electron-to-chromium": "^1.3.488", + "escalade": "^3.0.1", + "node-releases": "^1.1.58" } }, "bser": { @@ -4052,26 +3613,29 @@ "dev": true }, "cacache": { - "version": "12.0.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.3.tgz", - "integrity": "sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==", + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-13.0.1.tgz", + "integrity": "sha512-5ZvAxd05HDDU+y9BVvcqYu2LLXmPnQ0hW62h32g4xBTgL/MppR4/04NHfj/ycM2y6lmTnbw6HVi+1eN0Psba6w==", "dev": true, "requires": { - "bluebird": "^3.5.5", - "chownr": "^1.1.1", + "chownr": "^1.1.2", "figgy-pudding": "^3.5.1", + "fs-minipass": "^2.0.0", "glob": "^7.1.4", - "graceful-fs": "^4.1.15", - "infer-owner": "^1.0.3", + "graceful-fs": "^4.2.2", + "infer-owner": "^1.0.4", "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", + "minipass": "^3.0.0", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", "mkdirp": "^0.5.1", "move-concurrently": "^1.0.1", + "p-map": "^3.0.0", "promise-inflight": "^1.0.1", - "rimraf": "^2.6.3", - "ssri": "^6.0.1", - "unique-filename": "^1.1.1", - "y18n": "^4.0.0" + "rimraf": "^2.7.1", + "ssri": "^7.0.0", + "unique-filename": "^1.1.1" }, "dependencies": { "rimraf": { @@ -4133,13 +3697,13 @@ "dev": true }, "camel-case": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", - "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.1.tgz", + "integrity": "sha512-7fa2WcG4fYFkclIvEmxBbTvmibwF2/agfEBc6q3lOpVu0A13ltLsA+Hr/8Hp6kp5f+G7hKi6t8lys6XxP+1K6Q==", "dev": true, "requires": { - "no-case": "^2.2.0", - "upper-case": "^1.1.1" + "pascal-case": "^3.1.1", + "tslib": "^1.10.0" } }, "camelcase": { @@ -4161,9 +3725,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001027", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001027.tgz", - "integrity": "sha512-7xvKeErvXZFtUItTHgNtLgS9RJpVnwBlWX8jSo/BO8VsF6deszemZSkJJJA1KOKrXuzZH4WALpAJdq5EyfgMLg==", + "version": "1.0.30001111", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001111.tgz", + "integrity": "sha512-xnDje2wchd/8mlJu8sXvWxOGvMgv+uT3iZ3bkIAynKOzToCssWCmkz/ZIkQBs/2pUB4uwnJKVORWQ31UkbVjOg==", "dev": true }, "capture-exit": { @@ -4176,9 +3740,9 @@ } }, "case-sensitive-paths-webpack-plugin": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.2.0.tgz", - "integrity": "sha512-u5ElzokS8A1pm9vM3/iDgTcI3xqHxuCao94Oz8etI3cf0Tio0p8izkDYbTIn09uP3yUUr6+veaE6IkjnTYS46g==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.3.0.tgz", + "integrity": "sha512-/4YgnZS8y1UXXmC02xD5rRrBEu6T5ub+mQHLNRj0fzTRbgdBYhsNo2V5EqwgqrExjxsjtF/OpAKAMkKsxbD5XQ==", "dev": true }, "caseless": { @@ -4188,24 +3752,16 @@ "dev": true }, "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } }, - "char-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", - "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true - }, "chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", @@ -4244,902 +3800,180 @@ "path-is-absolute": "^1.0.0", "readdirp": "^2.2.1", "upath": "^1.1.1" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "chrome-trace-event": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", + "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" }, "dependencies": { - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } + "is-descriptor": "^0.1.0" } + } + } + }, + "classnames": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", + "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" + }, + "clean-css": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", + "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", + "dev": true, + "requires": { + "source-map": "~0.6.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 + } + } + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" } - }, - "fsevents": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz", - "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==", + } + } + }, + "clone-deep": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz", + "integrity": "sha1-TnPdCen7lxzDhnDF3O2cGJZIHMY=", + "dev": true, + "requires": { + "for-own": "^0.1.3", + "is-plain-object": "^2.0.1", + "kind-of": "^3.0.2", + "lazy-cache": "^1.0.3", + "shallow-clone": "^0.1.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, - "optional": true, "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1", - "node-pre-gyp": "*" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "3.2.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.7", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.6.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.6", - "bundled": true, - "dev": true, - "optional": 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" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "bundled": true, - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true, - "optional": true - }, - "minipass": { - "version": "2.9.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.3.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.9.0" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^3.2.6", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.14.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4.4.2" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-normalize-package-bin": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.4.7", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.7.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.7.1", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.13", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "yallist": { - "version": "3.1.1", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "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": { - "is-buffer": "^1.1.5" - } - } - } - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" + "is-buffer": "^1.1.5" } } } }, - "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", "dev": true }, - "chrome-trace-event": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz", - "integrity": "sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ==", + "coa": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", + "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", "dev": true, "requires": { - "tslib": "^1.9.0" - } - }, - "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", - "dev": true - }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "classnames": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", - "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" - }, - "clean-css": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", - "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", - "dev": true, - "requires": { - "source-map": "~0.6.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 - } - } - }, - "cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "requires": { - "restore-cursor": "^3.1.0" - } - }, - "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", - "dev": true - }, - "cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - } - } - }, - "clone-deep": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-0.2.4.tgz", - "integrity": "sha1-TnPdCen7lxzDhnDF3O2cGJZIHMY=", - "dev": true, - "requires": { - "for-own": "^0.1.3", - "is-plain-object": "^2.0.1", - "kind-of": "^3.0.2", - "lazy-cache": "^1.0.3", - "shallow-clone": "^0.1.2" - }, - "dependencies": { - "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": { - "is-buffer": "^1.1.5" - } - } - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "coa": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", - "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", - "dev": true, - "requires": { - "@types/q": "^1.5.1", - "chalk": "^2.4.1", - "q": "^1.1.2" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" } }, "code-point-at": { @@ -5148,12 +3982,6 @@ "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, - "collect-v8-coverage": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", - "dev": true - }, "collection-visit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", @@ -5199,6 +4027,12 @@ "simple-swizzle": "^0.2.2" } }, + "colorette": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz", + "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==", + "dev": true + }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -5387,17 +4221,6 @@ "mkdirp": "^0.5.1", "rimraf": "^2.5.4", "run-queue": "^1.0.0" - }, - "dependencies": { - "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" - } - } } }, "copy-descriptor": { @@ -5407,18 +4230,18 @@ "dev": true }, "core-js": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", - "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz", + "integrity": "sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==", "dev": true }, "core-js-compat": { - "version": "3.6.4", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.4.tgz", - "integrity": "sha512-zAa3IZPvsJ0slViBQ2z+vgyyTuhd3MFn1rBQjZSKVEgB0UMYhUkCj9jJUVPgGTGqWvsBVmfnruXgTcNyTlEiSA==", + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.5.tgz", + "integrity": "sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng==", "dev": true, "requires": { - "browserslist": "^4.8.3", + "browserslist": "^4.8.5", "semver": "7.0.0" }, "dependencies": { @@ -5430,6 +4253,12 @@ } } }, + "core-js-pure": { + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.6.5.tgz", + "integrity": "sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA==", + "dev": true + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", @@ -5449,13 +4278,21 @@ } }, "create-ecdh": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", - "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", "dev": true, "requires": { "bn.js": "^4.1.0", - "elliptic": "^6.0.0" + "elliptic": "^6.5.3" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } } }, "create-hash": { @@ -5592,22 +4429,23 @@ } }, "css-loader": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-2.1.1.tgz", - "integrity": "sha512-OcKJU/lt232vl1P9EEDamhoO9iKY3tIjY5GU+XDLblAykTdgs6Ux9P1hTHve8nFKy5KPpOXOsVI/hIwi3841+w==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.4.2.tgz", + "integrity": "sha512-jYq4zdZT0oS0Iykt+fqnzVLRIeiPWhka+7BqPn+oSIpWJAHak5tmB/WZrJ2a21JhCeFyNnnlroSl8c+MtVndzA==", "dev": true, "requires": { - "camelcase": "^5.2.0", - "icss-utils": "^4.1.0", + "camelcase": "^5.3.1", + "cssesc": "^3.0.0", + "icss-utils": "^4.1.1", "loader-utils": "^1.2.3", "normalize-path": "^3.0.0", - "postcss": "^7.0.14", + "postcss": "^7.0.23", "postcss-modules-extract-imports": "^2.0.0", - "postcss-modules-local-by-default": "^2.0.6", - "postcss-modules-scope": "^2.1.0", - "postcss-modules-values": "^2.0.0", - "postcss-value-parser": "^3.3.0", - "schema-utils": "^1.0.0" + "postcss-modules-local-by-default": "^3.0.2", + "postcss-modules-scope": "^2.1.1", + "postcss-modules-values": "^3.0.0", + "postcss-value-parser": "^4.0.2", + "schema-utils": "^2.6.0" } }, "css-prefers-color-scheme": { @@ -5655,12 +4493,6 @@ } } }, - "css-unit-converter": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.1.tgz", - "integrity": "sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY=", - "dev": true - }, "css-what": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", @@ -5757,41 +4589,57 @@ "dev": true }, "csso": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/csso/-/csso-4.0.2.tgz", - "integrity": "sha512-kS7/oeNVXkHWxby5tHVxlhjizRCSv8QdU7hB2FpdAibDU8FjTAolhNjKNTiLzXtUrKT6HwClE81yXwEk1309wg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.0.3.tgz", + "integrity": "sha512-NL3spysxUkcrOgnpsT4Xdl2aiEiBG6bXswAABQVHcMrfjjBisFOKwLDOmf4wf32aPdcJws1zds2B0Rg+jqMyHQ==", "dev": true, "requires": { - "css-tree": "1.0.0-alpha.37" + "css-tree": "1.0.0-alpha.39" + }, + "dependencies": { + "css-tree": { + "version": "1.0.0-alpha.39", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.39.tgz", + "integrity": "sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA==", + "dev": true, + "requires": { + "mdn-data": "2.0.6", + "source-map": "^0.6.1" + } + }, + "mdn-data": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.6.tgz", + "integrity": "sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA==", + "dev": true + }, + "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 + } } }, "cssom": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.4.4.tgz", - "integrity": "sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==", + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", "dev": true }, "cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz", + "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==", "dev": true, "requires": { - "cssom": "~0.3.6" - }, - "dependencies": { - "cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - } + "cssom": "0.3.x" } }, "csstype": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.9.tgz", - "integrity": "sha512-xz39Sb4+OaTsULgUERcCk+TJj8ylkL4aSVDQiX/ksxbELSqwkgt4d4RD7fovIdgJGSuNYqwZEiVjYY5l0ask+Q==" + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.2.tgz", + "integrity": "sha512-ofovWglpqoqbfLNOTBNZLSbMuGrblAf1efvvArGKOZMBrIoJeu5UsAipQolkijtyQx5MtAzT/J9IHj/CEY1mJw==" }, "cyclist": { "version": "1.0.1", @@ -5833,6 +4681,19 @@ "abab": "^2.0.0", "whatwg-mimetype": "^2.2.0", "whatwg-url": "^7.0.0" + }, + "dependencies": { + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } } }, "debug": { @@ -5850,12 +4711,6 @@ "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, - "decimal.js": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.2.0.tgz", - "integrity": "sha512-vDPw+rDgn3bZe1+F/pyEwb1oMG2XTlRVgAa6B4KccTEpYgF8w6eQllVbQcfIJnZyvzFtFpxnpGtx8dd7DJp/Rw==", - "dev": true - }, "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", @@ -5882,12 +4737,6 @@ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, - "deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true - }, "default-gateway": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", @@ -5949,17 +4798,18 @@ } }, "del": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", - "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", + "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", "dev": true, "requires": { + "@types/glob": "^7.1.1", "globby": "^6.1.0", - "is-path-cwd": "^1.0.0", - "is-path-in-cwd": "^1.0.0", - "p-map": "^1.1.1", - "pify": "^3.0.0", - "rimraf": "^2.2.8" + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.3" }, "dependencies": { "globby": { @@ -5983,14 +4833,11 @@ } } }, - "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" - } + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true } } }, @@ -6023,9 +4870,9 @@ "dev": true }, "detect-newline": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", - "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", "dev": true }, "detect-node": { @@ -6045,9 +4892,9 @@ } }, "diff-sequences": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.0.0.tgz", - "integrity": "sha512-JC/eHYEC3aSS0vZGjuoc4vHA0yAQTzhQQldXMeMF+JlxLGJlCO38Gma82NV9gk1jGFz8mDzUMeaKXvjRRdJ2dg==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", + "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==", "dev": true }, "diffie-hellman": { @@ -6059,7 +4906,15 @@ "bn.js": "^4.1.0", "miller-rabin": "^4.0.0", "randombytes": "^2.0.0" - } + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } }, "dir-glob": { "version": "2.0.0", @@ -6121,12 +4976,12 @@ } }, "dom-helpers": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.1.3.tgz", - "integrity": "sha512-nZD1OtwfWGRBWlpANxacBEZrEuLa16o1nh7YopFWeoF68Zt8GGEmzHu6Xv4F3XaFIC+YXtTLrzgqKxFgLEe4jw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.0.tgz", + "integrity": "sha512-Ru5o9+V8CpunKnz5LGgWXkmrH/20cGKwcHwS4m73zIvs54CN9epEmT/HLqFJW3kXpakAFkEdzgy1hzlJe3E4OQ==", "requires": { - "@babel/runtime": "^7.6.3", - "csstype": "^2.6.7" + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" } }, "dom-serializer": { @@ -6179,6 +5034,16 @@ "domelementtype": "1" } }, + "dot-case": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.3.tgz", + "integrity": "sha512-7hwEmg6RiSQfm/GwPL4AAWXKy3YNNZA3oFv2Pdiey0mwkRCPZ9x6SZbkLcn8Ma5PYeVokzoD4Twv2n7LKp5WeA==", + "dev": true, + "requires": { + "no-case": "^3.0.3", + "tslib": "^1.10.0" + } + }, "dot-prop": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz", @@ -6189,9 +5054,9 @@ } }, "dotenv": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.2.0.tgz", - "integrity": "sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==", "dev": true }, "dotenv-expand": { @@ -6261,15 +5126,15 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.349", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.349.tgz", - "integrity": "sha512-uEb2zs6EJ6OZIqaMsCSliYVgzE/f7/s1fLWqtvRtHg/v5KBF2xds974fUnyatfxIDgkqzQVwFtam5KExqywx0Q==", + "version": "1.3.520", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.520.tgz", + "integrity": "sha512-q6H9E1sXDCjRHP+X06vcP+N0ki8ZvYoRPZfKnDuiRX10WWXxEHzKFVf4O9rBFMpuPtR3M+2KAdJnugJoBBp3Rw==", "dev": true }, "elliptic": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz", - "integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==", + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", + "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", "dev": true, "requires": { "bn.js": "^4.4.0", @@ -6279,6 +5144,14 @@ "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0", "minimalistic-crypto-utils": "^1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } } }, "emoji-regex": { @@ -6288,9 +5161,9 @@ "dev": true }, "emojis-list": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", "dev": true }, "encodeurl": { @@ -6309,9 +5182,9 @@ } }, "enhanced-resolve": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz", - "integrity": "sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz", + "integrity": "sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ==", "dev": true, "requires": { "graceful-fs": "^4.1.2", @@ -6362,32 +5235,33 @@ "dev": true }, "enzyme": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.10.0.tgz", - "integrity": "sha512-p2yy9Y7t/PFbPoTvrWde7JIYB2ZyGC+NgTNbVEGvZ5/EyoYSr9aG/2rSbVvyNvMHEhw9/dmGUJHWtfQIEiX9pg==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.11.0.tgz", + "integrity": "sha512-Dw8/Gs4vRjxY6/6i9wU0V+utmQO9kvh9XLnz3LIudviOnVYDEe2ec+0k+NQoMamn1VrjKgCUOWj5jG/5M5M0Qw==", "dev": true, "requires": { - "array.prototype.flat": "^1.2.1", - "cheerio": "^1.0.0-rc.2", - "function.prototype.name": "^1.1.0", + "array.prototype.flat": "^1.2.3", + "cheerio": "^1.0.0-rc.3", + "enzyme-shallow-equal": "^1.0.1", + "function.prototype.name": "^1.1.2", "has": "^1.0.3", - "html-element-map": "^1.0.0", - "is-boolean-object": "^1.0.0", - "is-callable": "^1.1.4", - "is-number-object": "^1.0.3", - "is-regex": "^1.0.4", - "is-string": "^1.0.4", + "html-element-map": "^1.2.0", + "is-boolean-object": "^1.0.1", + "is-callable": "^1.1.5", + "is-number-object": "^1.0.4", + "is-regex": "^1.0.5", + "is-string": "^1.0.5", "is-subset": "^0.1.1", "lodash.escape": "^4.0.1", "lodash.isequal": "^4.5.0", - "object-inspect": "^1.6.0", - "object-is": "^1.0.1", + "object-inspect": "^1.7.0", + "object-is": "^1.0.2", "object.assign": "^4.1.0", - "object.entries": "^1.0.4", - "object.values": "^1.0.4", - "raf": "^3.4.0", + "object.entries": "^1.1.1", + "object.values": "^1.1.1", + "raf": "^3.4.1", "rst-selector-parser": "^2.2.3", - "string.prototype.trim": "^1.1.2" + "string.prototype.trim": "^1.2.1" } }, "enzyme-adapter-react-16": { @@ -6511,6 +5385,12 @@ "ext": "^1.1.2" } }, + "escalade": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.0.2.tgz", + "integrity": "sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ==", + "dev": true + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -6524,9 +5404,9 @@ "dev": true }, "escodegen": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.1.tgz", - "integrity": "sha512-Bmt7NcRySdIfNPfU2ZoXDrrXsG9ZjvDxcAlMfDUgRBjLOWTuIACXPBFJH7Z+cLb40JeQco5toikyc9t9P8E9SQ==", + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", "dev": true, "requires": { "esprima": "^4.0.1", @@ -6590,32 +5470,6 @@ "v8-compile-cache": "^2.0.3" }, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, "debug": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", @@ -6625,13 +5479,22 @@ "ms": "^2.1.1" } }, - "globals": { - "version": "12.3.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-12.3.0.tgz", - "integrity": "sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw==", + "eslint-utils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", + "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", "dev": true, "requires": { - "type-fest": "^0.8.1" + "is-glob": "^4.0.1" } }, "import-fresh": { @@ -6667,40 +5530,22 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } } } }, "eslint-config-react-app": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-5.2.0.tgz", - "integrity": "sha512-WrHjoGpKr1kLLiWDD81tme9jMM0hk5cMxasLSdyno6DdPt+IfLOrDJBVo6jN7tn4y1nzhs43TmUaZWO6Sf0blw==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-config-react-app/-/eslint-config-react-app-5.2.1.tgz", + "integrity": "sha512-pGIZ8t0mFLcV+6ZirRgYK6RVqUIKRIi9MmgzUEmrIknsn3AdO0I32asO86dJgloHq+9ZPl8UIg8mYrvgP5u2wQ==", "dev": true, "requires": { "confusing-browser-globals": "^1.0.9" } }, "eslint-import-resolver-node": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.3.tgz", - "integrity": "sha512-b8crLDo0M5RSe5YG8Pu2DYBj71tSB6OvXkfzwbJU2w7y8P4/yo0MyF8jU26IEuEuHF2K5/gcAJE3LhQGqBBbVg==", + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz", + "integrity": "sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA==", "dev": true, "requires": { "debug": "^2.6.9", @@ -6708,45 +5553,22 @@ } }, "eslint-loader": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/eslint-loader/-/eslint-loader-3.0.2.tgz", - "integrity": "sha512-S5VnD+UpVY1PyYRqeBd/4pgsmkvSokbHqTXAQMpvCyRr3XN2tvSLo9spm2nEpqQqh9dezw3os/0zWihLeOg2Rw==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/eslint-loader/-/eslint-loader-3.0.3.tgz", + "integrity": "sha512-+YRqB95PnNvxNp1HEjQmvf9KNvCin5HXYYseOXVC2U0KEcw4IkQ2IQEBG46j7+gW39bMzeu0GsUhVbBY3Votpw==", "dev": true, "requires": { "fs-extra": "^8.1.0", "loader-fs-cache": "^1.0.2", "loader-utils": "^1.2.3", - "object-hash": "^1.3.1", - "schema-utils": "^2.2.0" - }, - "dependencies": { - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "schema-utils": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.4.tgz", - "integrity": "sha512-VNjcaUxVnEeun6B2fiiUDjXXBtD4ZSH7pdbfIu1pOFwgptDPLMo/z9jr4sUfsjFVPqDCEin/F7IYlq7/E6yDbQ==", - "dev": true, - "requires": { - "ajv": "^6.10.2", - "ajv-keywords": "^3.4.1" - } - } + "object-hash": "^2.0.1", + "schema-utils": "^2.6.1" } }, "eslint-module-utils": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.5.2.tgz", - "integrity": "sha512-LGScZ/JSlqGKiT8OC+cYRxseMjyqt6QO54nl281CK93unD89ijSeRV6An8Ci/2nvWVKe8K/Tqdm75RQoIOCr+Q==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz", + "integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==", "dev": true, "requires": { "debug": "^2.6.9", @@ -6796,12 +5618,6 @@ "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", "dev": true }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, "pkg-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", @@ -6814,31 +5630,32 @@ } }, "eslint-plugin-flowtype": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-3.13.0.tgz", - "integrity": "sha512-bhewp36P+t7cEV0b6OdmoRWJCBYRiHFlqPZAG1oS3SF+Y0LQkeDvFSM4oxoxvczD1OdONCXMlJfQFiWLcV9urw==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-flowtype/-/eslint-plugin-flowtype-4.6.0.tgz", + "integrity": "sha512-W5hLjpFfZyZsXfo5anlu7HM970JBDqbEshAJUkeczP6BFCIfJXuiIBQXyberLRtOStT0OGPF8efeTbxlHk4LpQ==", "dev": true, "requires": { "lodash": "^4.17.15" } }, "eslint-plugin-import": { - "version": "2.18.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz", - "integrity": "sha512-5ohpsHAiUBRNaBWAF08izwUGlbrJoJJ+W9/TBwsGoR1MnlgfwMIKrFeSjWbt6moabiXW9xNvtFz+97KHRfI4HQ==", + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.20.1.tgz", + "integrity": "sha512-qQHgFOTjguR+LnYRoToeZWT62XM55MBVXObHM6SKFd1VzDcX/vqT1kAz8ssqigh5eMj8qXcRoXXGZpPP6RfdCw==", "dev": true, "requires": { "array-includes": "^3.0.3", + "array.prototype.flat": "^1.2.1", "contains-path": "^0.1.0", "debug": "^2.6.9", "doctrine": "1.5.0", "eslint-import-resolver-node": "^0.3.2", - "eslint-module-utils": "^2.4.0", + "eslint-module-utils": "^2.4.1", "has": "^1.0.3", "minimatch": "^3.0.4", "object.values": "^1.1.0", "read-pkg-up": "^2.0.0", - "resolve": "^1.11.0" + "resolve": "^1.12.0" }, "dependencies": { "doctrine": { @@ -6915,12 +5732,6 @@ "error-ex": "^1.2.0" } }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, "path-type": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", @@ -6956,12 +5767,6 @@ "find-up": "^2.0.0", "read-pkg": "^2.0.0" } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true } } }, @@ -6991,20 +5796,23 @@ } }, "eslint-plugin-react": { - "version": "7.14.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.14.3.tgz", - "integrity": "sha512-EzdyyBWC4Uz2hPYBiEJrKCUi2Fn+BJ9B/pJQcjw5X+x/H2Nm59S4MJIvL4O5NEE0+WbnQwEBxWY03oUk+Bc3FA==", + "version": "7.19.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.19.0.tgz", + "integrity": "sha512-SPT8j72CGuAP+JFbT0sJHOB80TX/pu44gQ4vXH/cq+hQTiY2PuZ6IHkqXJV6x1b28GDdo1lbInjKUrrdUf0LOQ==", "dev": true, "requires": { - "array-includes": "^3.0.3", + "array-includes": "^3.1.1", "doctrine": "^2.1.0", "has": "^1.0.3", - "jsx-ast-utils": "^2.1.0", - "object.entries": "^1.1.0", - "object.fromentries": "^2.0.0", - "object.values": "^1.1.0", + "jsx-ast-utils": "^2.2.3", + "object.entries": "^1.1.1", + "object.fromentries": "^2.0.2", + "object.values": "^1.1.1", "prop-types": "^15.7.2", - "resolve": "^1.10.1" + "resolve": "^1.15.1", + "semver": "^6.3.0", + "string.prototype.matchall": "^4.0.2", + "xregexp": "^4.3.0" }, "dependencies": { "doctrine": { @@ -7015,6 +5823,12 @@ "requires": { "esutils": "^2.0.2" } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true } } }, @@ -7025,9 +5839,9 @@ "dev": true }, "eslint-scope": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", - "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.0.tgz", + "integrity": "sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==", "dev": true, "requires": { "esrecurse": "^4.1.0", @@ -7035,28 +5849,28 @@ } }, "eslint-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz", - "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", "dev": true, "requires": { "eslint-visitor-keys": "^1.1.0" } }, "eslint-visitor-keys": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", - "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", "dev": true }, "espree": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.2.tgz", - "integrity": "sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", + "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", "dev": true, "requires": { - "acorn": "^7.1.0", - "acorn-jsx": "^5.1.0", + "acorn": "^7.1.1", + "acorn-jsx": "^5.2.0", "eslint-visitor-keys": "^1.1.0" } }, @@ -7067,12 +5881,20 @@ "dev": true }, "esquery": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.1.0.tgz", - "integrity": "sha512-MxYW9xKmROWF672KqjO75sszsA8Mxhw06YFeS5VHlB98KDHbOSurm3ArsjO60Eaf3QmGMCP1yn+0JQkNLo/97Q==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", + "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", "dev": true, "requires": { - "estraverse": "^4.0.0" + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.1.0.tgz", + "integrity": "sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw==", + "dev": true + } } }, "esrecurse": { @@ -7103,15 +5925,15 @@ "dev": true }, "eventemitter3": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.0.tgz", - "integrity": "sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz", + "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==", "dev": true }, "events": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.1.0.tgz", - "integrity": "sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", + "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==", "dev": true }, "eventsource": { @@ -7196,44 +6018,17 @@ } }, "expect": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-26.0.1.tgz", - "integrity": "sha512-QcCy4nygHeqmbw564YxNbHTJlXh47dVID2BUP52cZFpLU9zHViMFK6h07cC1wf7GYCTIigTdAXhVua8Yl1FkKg==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-24.9.0.tgz", + "integrity": "sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q==", "dev": true, "requires": { - "@jest/types": "^26.0.1", - "ansi-styles": "^4.0.0", - "jest-get-type": "^26.0.0", - "jest-matcher-utils": "^26.0.1", - "jest-message-util": "^26.0.1", - "jest-regex-util": "^26.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - } + "@jest/types": "^24.9.0", + "ansi-styles": "^3.2.0", + "jest-get-type": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-regex-util": "^24.9.0" } }, "express": { @@ -7415,9 +6210,9 @@ "dev": true }, "fast-deep-equal": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", - "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, "fast-glob": { @@ -7432,132 +6227,6 @@ "is-glob": "^4.0.0", "merge2": "^1.2.3", "micromatch": "^3.1.10" - }, - "dependencies": { - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "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": { - "is-buffer": "^1.1.5" - } - } - } - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - } } }, "fast-json-stable-stringify": { @@ -7573,9 +6242,9 @@ "dev": true }, "faye-websocket": { - "version": "0.11.3", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", - "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", + "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", "dev": true, "requires": { "websocket-driver": ">=0.5.1" @@ -7591,15 +6260,15 @@ } }, "figgy-pudding": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", - "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", "dev": true }, "figures": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.1.0.tgz", - "integrity": "sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", "dev": true, "requires": { "escape-string-regexp": "^1.0.5" @@ -7615,13 +6284,13 @@ } }, "file-loader": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-3.0.1.tgz", - "integrity": "sha512-4sNIOXgtH/9WZq4NvlfU3Opn5ynUsqBwSLyM+I7UOwdGigTBYfVVQEwe/msZNX/j4pCJTIM14Fsw66Svo1oVrw==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-4.3.0.tgz", + "integrity": "sha512-aKrYPYjF1yG3oX0kWRrqrSMfgftm7oJW5M+m4owoldH5C51C0RkIwB++JbRvEW3IU6/ZG5n8UvEcdgwOt2UOWA==", "dev": true, "requires": { - "loader-utils": "^1.0.2", - "schema-utils": "^1.0.0" + "loader-utils": "^1.2.3", + "schema-utils": "^2.5.0" } }, "file-uri-to-path": { @@ -7632,18 +6301,32 @@ "optional": true }, "filesize": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz", - "integrity": "sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/filesize/-/filesize-6.0.1.tgz", + "integrity": "sha512-u4AYWPgbI5GBhs6id1KdImZWn5yfyFrrQ8OWZdN7ZMfA8Bf4HcO0BGo9bmUIEV8yrp8I1xVfJ/dn90GtFNNJcg==", "dev": true }, "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, "requires": { - "to-regex-range": "^5.0.1" + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } } }, "finalhandler": { @@ -7670,77 +6353,15 @@ "commondir": "^1.0.1", "make-dir": "^2.0.0", "pkg-dir": "^3.0.0" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "requires": { - "find-up": "^3.0.0" - } - } } }, "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", "dev": true, "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" + "locate-path": "^3.0.0" } }, "flat-cache": { @@ -7752,23 +6373,12 @@ "flatted": "^2.0.0", "rimraf": "2.6.3", "write": "1.0.3" - }, - "dependencies": { - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } } }, "flatted": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", - "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", "dev": true }, "flatten": { @@ -7814,30 +6424,10 @@ } }, "follow-redirects": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.10.0.tgz", - "integrity": "sha512-4eyLK6s6lH32nOvLLwlIOnr9zrL8Sm+OvW4pVTJNoXeGzYIkHVf+pADQi+OJ0E67hiuSLezPVPyBcIZO50TmmQ==", - "dev": true, - "requires": { - "debug": "^3.0.0" - }, - "dependencies": { - "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" - } - }, - "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 - } - } + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.12.1.tgz", + "integrity": "sha512-tmRv0AVuR7ZyouUHLeNSiO6pqulF7dYa3s19c6t+wz9LD69/uSzdMxJ2S91nTI9U3rt/IldxpzMOFejp6f0hjg==", + "dev": true }, "for-in": { "version": "1.0.2", @@ -7861,14 +6451,14 @@ "dev": true }, "fork-ts-checker-webpack-plugin": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-1.5.0.tgz", - "integrity": "sha512-zEhg7Hz+KhZlBhILYpXy+Beu96gwvkROWJiTXOCyOOMMrdBIRPvsBpBqgTI4jfJGrJXcqGwJR8zsBGDmzY0jsA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-3.1.1.tgz", + "integrity": "sha512-DuVkPNrM12jR41KM2e+N+styka0EgLkTnXmNcXdgOM37vtGeY+oCBK/Jx0hzSeEU6memFCtWb4htrHPMDfwwUQ==", "dev": true, "requires": { "babel-code-frame": "^6.22.0", "chalk": "^2.4.1", - "chokidar": "^2.0.4", + "chokidar": "^3.3.0", "micromatch": "^3.1.10", "minimatch": "^3.0.4", "semver": "^5.6.0", @@ -7876,136 +6466,103 @@ "worker-rpc": "^0.1.0" }, "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", "dev": true, "requires": { - "color-convert": "^1.9.0" + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" } }, + "binary-extensions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "dev": true + }, "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dev": true, "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "fill-range": "^7.0.1" } }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "chokidar": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.1.tgz", + "integrity": "sha512-TQTJyr2stihpC4Sya9hs2Xh+O2wf+igjL36Y75xx2WdHuiICcn/XJza46Jwt0eT5hVpQOzo3FpY3cj3RVYLX0g==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.4.0" } }, "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "to-regex-range": "^5.0.1" } }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "dev": true, + "optional": true + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", "dev": true, "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "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": { - "is-buffer": "^1.1.5" - } - } + "is-glob": "^4.0.1" } }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" + "binary-extensions": "^2.0.0" } }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "readdirp": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", + "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "picomatch": "^2.2.1" } }, "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" + "is-number": "^7.0.0" } } } @@ -8079,16 +6636,31 @@ } }, "fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", + "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "dev": true + }, "fs-write-stream-atomic": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", @@ -8134,11 +6706,15 @@ "dev": true }, "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", "dev": true, - "optional": true + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } }, "function-bind": { "version": "1.1.1", @@ -8226,12 +6802,24 @@ } }, "glob-parent": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz", - "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, "requires": { - "is-glob": "^4.0.1" + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } } }, "glob-to-regexp": { @@ -8261,10 +6849,13 @@ } }, "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } }, "globby": { "version": "8.0.2", @@ -8287,6 +6878,12 @@ "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", "dev": true }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, "slash": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", @@ -8296,9 +6893,9 @@ } }, "graceful-fs": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", "dev": true }, "growly": { @@ -8315,20 +6912,12 @@ "requires": { "duplexer": "^0.1.1", "pify": "^4.0.1" - }, - "dependencies": { - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - } } }, "handle-thing": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.0.tgz", - "integrity": "sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", "dev": true }, "har-schema": { @@ -8338,12 +6927,12 @@ "dev": true }, "har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "dev": true, "requires": { - "ajv": "^6.5.5", + "ajv": "^6.12.3", "har-schema": "^2.0.0" } }, @@ -8369,6 +6958,14 @@ "dev": true, "requires": { "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + } } }, "has-flag": { @@ -8404,26 +7001,6 @@ "kind-of": "^4.0.0" }, "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "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": { - "is-buffer": "^1.1.5" - } - } - } - }, "kind-of": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", @@ -8436,13 +7013,22 @@ } }, "hash-base": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", - "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", "dev": true, "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } } }, "hash.js": { @@ -8479,9 +7065,9 @@ } }, "hosted-git-info": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz", - "integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==", + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", "dev": true }, "hpack.js": { @@ -8559,51 +7145,51 @@ } }, "html-entities": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", - "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.3.1.tgz", + "integrity": "sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA==", "dev": true }, "html-escaper": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.0.tgz", - "integrity": "sha512-a4u9BeERWGu/S8JiWEAQcdrg9v4QArtP9keViQjGMdff20fBdd8waotXaNmODqBe6uZ3Nafi7K/ho4gCQHV3Ig==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, - "html-minifier": { - "version": "3.5.21", - "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz", - "integrity": "sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==", + "html-minifier-terser": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz", + "integrity": "sha512-ZPr5MNObqnV/T9akshPKbVgyOqLmy+Bxo7juKCfTfnjNniTAMdy4hz21YQqoofMBJD2kdREaqPPdThoR78Tgxg==", "dev": true, "requires": { - "camel-case": "3.0.x", - "clean-css": "4.2.x", - "commander": "2.17.x", - "he": "1.2.x", - "param-case": "2.1.x", - "relateurl": "0.2.x", - "uglify-js": "3.4.x" + "camel-case": "^4.1.1", + "clean-css": "^4.2.3", + "commander": "^4.1.1", + "he": "^1.2.0", + "param-case": "^3.0.3", + "relateurl": "^0.2.7", + "terser": "^4.6.3" }, "dependencies": { "commander": { - "version": "2.17.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", - "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", "dev": true } } }, "html-webpack-plugin": { - "version": "4.0.0-beta.5", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-4.0.0-beta.5.tgz", - "integrity": "sha512-y5l4lGxOW3pz3xBTFdfB9rnnrWRPVxlAhX6nrBYIcW+2k2zC3mSp/3DxlWVCMBfnO6UAnoF8OcFn0IMy6kaKAQ==", + "version": "4.0.0-beta.11", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-4.0.0-beta.11.tgz", + "integrity": "sha512-4Xzepf0qWxf8CGg7/WQM5qBB2Lc/NFI7MhU59eUDTkuQp3skZczH4UA1d6oQyDEIoMDgERVhRyTdtUPZ5s5HBg==", "dev": true, "requires": { - "html-minifier": "^3.5.20", - "loader-utils": "^1.1.0", - "lodash": "^4.17.11", + "html-minifier-terser": "^5.0.1", + "loader-utils": "^1.2.3", + "lodash": "^4.17.15", "pretty-error": "^2.1.1", - "tapable": "^1.1.0", + "tapable": "^1.1.3", "util.promisify": "1.0.0" }, "dependencies": { @@ -8661,15 +7247,15 @@ } }, "http-parser-js": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz", - "integrity": "sha1-ksnBN0w1CF912zWexWzCV8u5P6Q=", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.2.tgz", + "integrity": "sha512-opCO9ASqg5Wy2FNo7A0sxy71yGbbkJJXLdgMK04Tcypw9jr2MgWbyubb0+WdmDmGnFflO7fRbqbaihh/ENDlRQ==", "dev": true }, "http-proxy": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.0.tgz", - "integrity": "sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ==", + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", "dev": true, "requires": { "eventemitter3": "^4.0.0", @@ -8687,111 +7273,6 @@ "is-glob": "^4.0.0", "lodash": "^4.17.11", "micromatch": "^3.1.10" - }, - "dependencies": { - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "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": { - "is-buffer": "^1.1.5" - } - } - } - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - } } }, "http-signature": { @@ -8811,12 +7292,6 @@ "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", "dev": true }, - "human-signals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", - "dev": true - }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -8826,12 +7301,6 @@ "safer-buffer": ">= 2.1.2 < 3" } }, - "icss-replace-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", - "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=", - "dev": true - }, "icss-utils": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", @@ -8903,13 +7372,13 @@ } }, "import-local": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", - "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", "dev": true, "requires": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" } }, "imurmurhash": { @@ -8918,6 +7387,12 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, "indexes-of": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", @@ -8953,68 +7428,89 @@ "dev": true }, "inquirer": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.4.tgz", - "integrity": "sha512-Bu5Td5+j11sCkqfqmUTiwv+tWisMtP0L7Q8WrqA2C/BbBhy1YTdFrvjjlrKq8oagA/tLQBski2Gcx/Sqyi2qSQ==", + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", + "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", "dev": true, "requires": { "ansi-escapes": "^4.2.1", - "chalk": "^2.4.2", + "chalk": "^4.1.0", "cli-cursor": "^3.1.0", - "cli-width": "^2.0.0", + "cli-width": "^3.0.0", "external-editor": "^3.0.3", "figures": "^3.0.0", - "lodash": "^4.17.15", + "lodash": "^4.17.19", "mute-stream": "0.0.8", - "run-async": "^2.2.0", - "rxjs": "^6.5.3", + "run-async": "^2.4.0", + "rxjs": "^6.6.0", "string-width": "^4.1.0", - "strip-ansi": "^5.1.0", + "strip-ansi": "^6.0.0", "through": "^2.3.6" }, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", "dev": true, "requires": { - "color-convert": "^1.9.0" + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" } }, "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" } }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "lodash": { + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", + "dev": true + }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "dev": true, "requires": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^5.0.0" } }, "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" } } } @@ -9029,6 +7525,17 @@ "ipaddr.js": "^1.9.0" } }, + "internal-slot": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.2.tgz", + "integrity": "sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g==", + "dev": true, + "requires": { + "es-abstract": "^1.17.0-next.1", + "has": "^1.0.3", + "side-channel": "^1.0.2" + } + }, "invariant": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", @@ -9057,9 +7564,9 @@ "dev": true }, "ipaddr.js": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", - "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "dev": true }, "is-absolute-url": { @@ -9202,11 +7709,10 @@ "dev": true }, "is-docker": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.0.0.tgz", - "integrity": "sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ==", - "dev": true, - "optional": true + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.1.1.tgz", + "integrity": "sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==", + "dev": true }, "is-extendable": { "version": "0.1.1", @@ -9242,10 +7748,24 @@ } }, "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "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": { + "is-buffer": "^1.1.5" + } + } + } }, "is-number-object": { "version": "1.0.4", @@ -9260,27 +7780,27 @@ "dev": true }, "is-path-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", "dev": true }, "is-path-in-cwd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", - "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", + "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", "dev": true, "requires": { - "is-path-inside": "^1.0.0" + "is-path-inside": "^2.1.0" } }, "is-path-inside": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", - "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", + "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", "dev": true, "requires": { - "path-is-inside": "^1.0.1" + "path-is-inside": "^1.0.2" } }, "is-plain-obj": { @@ -9298,18 +7818,6 @@ "isobject": "^3.0.1" } }, - "is-potential-custom-element-name": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz", - "integrity": "sha1-DFLlS8yjkbssSUsh6GJtczbG45c=", - "dev": true - }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", - "dev": true - }, "is-regex": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", @@ -9386,14 +7894,10 @@ "dev": true }, "is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "optional": true, - "requires": { - "is-docker": "^2.0.0" - } + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true }, "isarray": { "version": "1.0.0", @@ -9420,260 +7924,73 @@ "dev": true }, "istanbul-lib-coverage": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", - "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", "dev": true }, "istanbul-lib-instrument": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", - "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", + "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", "dev": true, "requires": { - "@babel/core": "^7.7.5", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", - "semver": "^6.3.0" + "@babel/generator": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "istanbul-lib-coverage": "^2.0.5", + "semver": "^6.0.0" }, "dependencies": { - "@babel/core": { - "version": "7.9.6", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.9.6.tgz", - "integrity": "sha512-nD3deLvbsApbHAHttzIssYqgb883yU/d9roe4RZymBCDaZryMJDbptVpEpeQuRh4BJ+SYI8le9YGxKvFEvl1Wg==", + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "istanbul-lib-report": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", + "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.9.6", - "@babel/helper-module-transforms": "^7.9.0", - "@babel/helpers": "^7.9.6", - "@babel/parser": "^7.9.6", - "@babel/template": "^7.8.6", - "@babel/traverse": "^7.9.6", - "@babel/types": "^7.9.6", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", - "json5": "^2.1.2", - "lodash": "^4.17.13", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } + "has-flag": "^3.0.0" } - }, - "@babel/generator": { - "version": "7.9.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.6.tgz", - "integrity": "sha512-+htwWKJbH2bL72HRluF8zumBxzuX0ZZUFl3JLNyoUjM/Ho8wnVpPXM6aUz8cfKDqQ/h7zHqKt4xzJteUosckqQ==", - "dev": true, - "requires": { - "@babel/types": "^7.9.6", - "jsesc": "^2.5.1", - "lodash": "^4.17.13", - "source-map": "^0.5.0" - } - }, - "@babel/helper-function-name": { - "version": "7.9.5", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz", - "integrity": "sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.8.3", - "@babel/template": "^7.8.3", - "@babel/types": "^7.9.5" - } - }, - "@babel/helper-module-transforms": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz", - "integrity": "sha512-0FvKyu0gpPfIQ8EkxlrAydOWROdHpBmiCiRwLkUiBGhCUPRRbVD2/tm3sFr/c/GWFrQ/ffutGUAnx7V0FzT2wA==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.8.3", - "@babel/helper-replace-supers": "^7.8.6", - "@babel/helper-simple-access": "^7.8.3", - "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/template": "^7.8.6", - "@babel/types": "^7.9.0", - "lodash": "^4.17.13" - } - }, - "@babel/helper-replace-supers": { - "version": "7.9.6", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.9.6.tgz", - "integrity": "sha512-qX+chbxkbArLyCImk3bWV+jB5gTNU/rsze+JlcF6Nf8tVTigPJSI1o1oBow/9Resa1yehUO9lIipsmu9oG4RzA==", - "dev": true, - "requires": { - "@babel/helper-member-expression-to-functions": "^7.8.3", - "@babel/helper-optimise-call-expression": "^7.8.3", - "@babel/traverse": "^7.9.6", - "@babel/types": "^7.9.6" - } - }, - "@babel/helpers": { - "version": "7.9.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.9.6.tgz", - "integrity": "sha512-tI4bUbldloLcHWoRUMAj4g1bF313M/o6fBKhIsb3QnGVPwRm9JsNf/gqMkQ7zjqReABiffPV6RWj7hEglID5Iw==", - "dev": true, - "requires": { - "@babel/template": "^7.8.3", - "@babel/traverse": "^7.9.6", - "@babel/types": "^7.9.6" - } - }, - "@babel/parser": { - "version": "7.9.6", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.6.tgz", - "integrity": "sha512-AoeIEJn8vt+d/6+PXDRPaksYhnlbMIiejioBZvvMQsOjW/JYK6k/0dKnvvP3EhK5GfMBWDPtrxRtegWdAcdq9Q==", - "dev": true - }, - "@babel/template": { - "version": "7.8.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz", - "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/parser": "^7.8.6", - "@babel/types": "^7.8.6" - } - }, - "@babel/traverse": { - "version": "7.9.6", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.6.tgz", - "integrity": "sha512-b3rAHSjbxy6VEAvlxM8OV/0X4XrG72zoxme6q1MOoe2vd0bEc+TwayhuC1+Dfgqh1QEG+pj7atQqvUprHIccsg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "@babel/generator": "^7.9.6", - "@babel/helper-function-name": "^7.9.5", - "@babel/helper-split-export-declaration": "^7.8.3", - "@babel/parser": "^7.9.6", - "@babel/types": "^7.9.6", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.13" - } - }, - "@babel/types": { - "version": "7.9.6", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.6.tgz", - "integrity": "sha512-qxXzvBO//jO9ZnoasKF1uJzHd2+M6Q2ZPIVfnFps8JJvXy0ZBbwbNOmE6SGIY5XOY6d1Bo5lb9d9RJ8nv3WSeA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.9.5", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - } - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "json5": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", - "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", - "dev": true - }, - "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 - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - } - } - }, - "istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "istanbul-lib-source-maps": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", - "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + } + } + }, + "istanbul-lib-source-maps": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", + "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "rimraf": "^2.6.3", + "source-map": "^0.6.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { "ms": "^2.1.1" @@ -9694,2847 +8011,1779 @@ } }, "istanbul-reports": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", - "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.7.tgz", + "integrity": "sha512-uu1F/L1o5Y6LzPVSVZXNOoD/KXpJue9aeLRd0sM9uMXfZvzomB0WxVamWb5ue8kA2vVWEmW7EG+A5n3f1kqHKg==", "dev": true, "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" + "html-escaper": "^2.0.0" } }, "jest": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-26.0.1.tgz", - "integrity": "sha512-29Q54kn5Bm7ZGKIuH2JRmnKl85YRigp0o0asTc6Sb6l2ch1DCXIeZTLLFy9ultJvhkTqbswF5DEx4+RlkmCxWg==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-24.9.0.tgz", + "integrity": "sha512-YvkBL1Zm7d2B1+h5fHEOdyjCG+sGMz4f8D86/0HiqJ6MB4MnDc8FgP5vdWsGnemOQro7lnYo8UakZ3+5A0jxGw==", "dev": true, "requires": { - "@jest/core": "^26.0.1", - "import-local": "^3.0.2", - "jest-cli": "^26.0.1" + "import-local": "^2.0.0", + "jest-cli": "^24.9.0" }, "dependencies": { - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", - "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, "jest-cli": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-26.0.1.tgz", - "integrity": "sha512-pFLfSOBcbG9iOZWaMK4Een+tTxi/Wcm34geqZEqrst9cZDkTQ1LZ2CnBrTlHWuYAiTMFr0EQeK52ScyFU8wK+w==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-24.9.0.tgz", + "integrity": "sha512-+VLRKyitT3BWoMeSUIHRxV/2g8y9gw91Jh5z2UmXZzkZKpbC08CSehVxgHUwTpy+HwGcns/tqafQDJW7imYvGg==", "dev": true, "requires": { - "@jest/core": "^26.0.1", - "@jest/test-result": "^26.0.1", - "@jest/types": "^26.0.1", - "chalk": "^4.0.0", + "@jest/core": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", "exit": "^0.1.2", - "graceful-fs": "^4.2.4", - "import-local": "^3.0.2", + "import-local": "^2.0.0", "is-ci": "^2.0.0", - "jest-config": "^26.0.1", - "jest-util": "^26.0.1", - "jest-validate": "^26.0.1", + "jest-config": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", "prompts": "^2.0.1", - "yargs": "^15.3.1" - } - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" + "realpath-native": "^1.1.0", + "yargs": "^13.3.0" } } } }, "jest-changed-files": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-26.0.1.tgz", - "integrity": "sha512-q8LP9Sint17HaE2LjxQXL+oYWW/WeeXMPE2+Op9X3mY8IEGFVc14xRxFjUuXUbcPAlDLhtWdIEt59GdQbn76Hw==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-24.9.0.tgz", + "integrity": "sha512-6aTWpe2mHF0DhL28WjdkO8LyGjs3zItPET4bMSeXU6T3ub4FPMw+mcOcbdGXQOAfmLcxofD23/5Bl9Z4AkFwqg==", "dev": true, "requires": { - "@jest/types": "^26.0.1", - "execa": "^4.0.0", - "throat": "^5.0.0" - }, - "dependencies": { - "cross-spawn": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.2.tgz", - "integrity": "sha512-PD6G8QG3S4FK/XCGFbEQrDqO2AnMMsy0meR7lerlIOHAAbkuavGU/pOqprrlvfTNjvowivTeBsjebAL0NSoMxw==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "execa": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.1.tgz", - "integrity": "sha512-SCjM/zlBdOK8Q5TIjOn6iEHZaPHFsMoTxXQ2nvUvtPnuohz3H2dIozSg+etNR98dGoYUp2ENSKLL/XaMmbxVgw==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" - } - }, - "get-stream": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", - "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", - "dev": true - }, - "npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "requires": { - "path-key": "^3.0.0" - } - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } + "@jest/types": "^24.9.0", + "execa": "^1.0.0", + "throat": "^4.0.0" } }, "jest-config": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-26.0.1.tgz", - "integrity": "sha512-9mWKx2L1LFgOXlDsC4YSeavnblN6A4CPfXFiobq+YYLaBMymA/SczN7xYTSmLaEYHZOcB98UdoN4m5uNt6tztg==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.9.0.tgz", + "integrity": "sha512-RATtQJtVYQrp7fvWg6f5y3pEFj9I+H8sWw4aKxnDZ96mob5i5SD6ZEGWgMLXQ4LE8UurrjbdlLWdUeo+28QpfQ==", "dev": true, "requires": { "@babel/core": "^7.1.0", - "@jest/test-sequencer": "^26.0.1", - "@jest/types": "^26.0.1", - "babel-jest": "^26.0.1", - "chalk": "^4.0.0", - "deepmerge": "^4.2.2", + "@jest/test-sequencer": "^24.9.0", + "@jest/types": "^24.9.0", + "babel-jest": "^24.9.0", + "chalk": "^2.0.1", "glob": "^7.1.1", - "graceful-fs": "^4.2.4", - "jest-environment-jsdom": "^26.0.1", - "jest-environment-node": "^26.0.1", - "jest-get-type": "^26.0.0", - "jest-jasmine2": "^26.0.1", - "jest-regex-util": "^26.0.0", - "jest-resolve": "^26.0.1", - "jest-util": "^26.0.1", - "jest-validate": "^26.0.1", - "micromatch": "^4.0.2", - "pretty-format": "^26.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", - "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "jest-environment-jsdom": "^24.9.0", + "jest-environment-node": "^24.9.0", + "jest-get-type": "^24.9.0", + "jest-jasmine2": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "micromatch": "^3.1.10", + "pretty-format": "^24.9.0", + "realpath-native": "^1.1.0" } }, "jest-diff": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.0.1.tgz", - "integrity": "sha512-odTcHyl5X+U+QsczJmOjWw5tPvww+y9Yim5xzqxVl/R1j4z71+fHW4g8qu1ugMmKdFdxw+AtQgs5mupPnzcIBQ==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", + "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", "dev": true, "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^26.0.0", - "jest-get-type": "^26.0.0", - "pretty-format": "^26.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", - "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "chalk": "^2.0.1", + "diff-sequences": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" } }, "jest-docblock": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-26.0.0.tgz", - "integrity": "sha512-RDZ4Iz3QbtRWycd8bUEPxQsTlYazfYn/h5R65Fc6gOfwozFhoImx+affzky/FFBuqISPTqjXomoIGJVKBWoo0w==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-24.9.0.tgz", + "integrity": "sha512-F1DjdpDMJMA1cN6He0FNYNZlo3yYmOtRUnktrT9Q37njYzC5WEaDdmbynIgy0L/IvXvvgsG8OsqhLPXTpfmZAA==", "dev": true, "requires": { - "detect-newline": "^3.0.0" + "detect-newline": "^2.1.0" } }, "jest-each": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-26.0.1.tgz", - "integrity": "sha512-OTgJlwXCAR8NIWaXFL5DBbeS4QIYPuNASkzSwMCJO+ywo9BEa6TqkaSWsfR7VdbMLdgYJqSfQcIyjJCNwl5n4Q==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-24.9.0.tgz", + "integrity": "sha512-ONi0R4BvW45cw8s2Lrx8YgbeXL1oCQ/wIDwmsM3CqM/nlblNCPmnC3IPQlMbRFZu3wKdQ2U8BqM6lh3LJ5Bsog==", "dev": true, "requires": { - "@jest/types": "^26.0.1", - "chalk": "^4.0.0", - "jest-get-type": "^26.0.0", - "jest-util": "^26.0.1", - "pretty-format": "^26.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", - "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "jest-get-type": "^24.9.0", + "jest-util": "^24.9.0", + "pretty-format": "^24.9.0" } }, "jest-environment-jsdom": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-26.0.1.tgz", - "integrity": "sha512-u88NJa3aptz2Xix2pFhihRBAatwZHWwSiRLBDBQE1cdJvDjPvv7ZGA0NQBxWwDDn7D0g1uHqxM8aGgfA9Bx49g==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-24.9.0.tgz", + "integrity": "sha512-Zv9FV9NBRzLuALXjvRijO2351DRQeLYXtpD4xNvfoVFw21IOKNhZAEUKcbiEtjTkm2GsJ3boMVgkaR7rN8qetA==", "dev": true, "requires": { - "@jest/environment": "^26.0.1", - "@jest/fake-timers": "^26.0.1", - "@jest/types": "^26.0.1", - "jest-mock": "^26.0.1", - "jest-util": "^26.0.1", - "jsdom": "^16.2.2" + "@jest/environment": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-util": "^24.9.0", + "jsdom": "^11.5.1" } }, "jest-environment-jsdom-fourteen": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom-fourteen/-/jest-environment-jsdom-fourteen-0.1.0.tgz", - "integrity": "sha512-4vtoRMg7jAstitRzL4nbw83VmGH8Rs13wrND3Ud2o1fczDhMUF32iIrNKwYGgeOPUdfvZU4oy8Bbv+ni1fgVCA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom-fourteen/-/jest-environment-jsdom-fourteen-1.0.1.tgz", + "integrity": "sha512-DojMX1sY+at5Ep+O9yME34CdidZnO3/zfPh8UW+918C5fIZET5vCjfkegixmsi7AtdYfkr4bPlIzmWnlvQkP7Q==", "dev": true, "requires": { - "jest-mock": "^24.5.0", - "jest-util": "^24.5.0", - "jsdom": "^14.0.0" + "@jest/environment": "^24.3.0", + "@jest/fake-timers": "^24.3.0", + "@jest/types": "^24.3.0", + "jest-mock": "^24.0.0", + "jest-util": "^24.0.0", + "jsdom": "^14.1.0" }, "dependencies": { - "@jest/console": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", - "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", - "dev": true, - "requires": { - "@jest/source-map": "^24.9.0", - "chalk": "^2.0.1", - "slash": "^2.0.0" - } - }, - "@jest/fake-timers": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", - "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-mock": "^24.9.0" - } - }, - "@jest/source-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", - "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", - "dev": true, - "requires": { - "callsites": "^3.0.0", - "graceful-fs": "^4.1.15", - "source-map": "^0.6.0" - } - }, - "@jest/test-result": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", - "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", - "dev": true, - "requires": { - "@jest/console": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/istanbul-lib-coverage": "^2.0.0" - } - }, - "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" - } + "acorn": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", + "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", + "dev": true }, - "@types/yargs": { - "version": "13.0.8", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.8.tgz", - "integrity": "sha512-XAvHLwG7UQ+8M4caKIH0ZozIOYay5fQkAgyIXegXT9jPtdIGdhga+sUEdAr1CiG46aB+c64xQEYyEzlwWVTNzA==", + "jsdom": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-14.1.0.tgz", + "integrity": "sha512-O901mfJSuTdwU2w3Sn+74T+RnDVP+FuV5fH8tcPWyqrseRAb0s5xOtPgCFiPOtLcyK7CLIJwPyD83ZqQWvA5ng==", "dev": true, "requires": { - "@types/yargs-parser": "*" + "abab": "^2.0.0", + "acorn": "^6.0.4", + "acorn-globals": "^4.3.0", + "array-equal": "^1.0.0", + "cssom": "^0.3.4", + "cssstyle": "^1.1.1", + "data-urls": "^1.1.0", + "domexception": "^1.0.1", + "escodegen": "^1.11.0", + "html-encoding-sniffer": "^1.0.2", + "nwsapi": "^2.1.3", + "parse5": "5.1.0", + "pn": "^1.1.0", + "request": "^2.88.0", + "request-promise-native": "^1.0.5", + "saxes": "^3.1.9", + "symbol-tree": "^3.2.2", + "tough-cookie": "^2.5.0", + "w3c-hr-time": "^1.0.1", + "w3c-xmlserializer": "^1.1.2", + "webidl-conversions": "^4.0.2", + "whatwg-encoding": "^1.0.5", + "whatwg-mimetype": "^2.3.0", + "whatwg-url": "^7.0.0", + "ws": "^6.1.2", + "xml-name-validator": "^3.0.0" } }, - "acorn": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz", - "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==", + "parse5": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", + "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", "dev": true }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", "dev": true, "requires": { - "color-convert": "^1.9.0" + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" } }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "ws": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", + "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", "dev": true, "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - }, - "cssstyle": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz", - "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==", - "dev": true, - "requires": { - "cssom": "0.3.x" - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "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": { - "is-buffer": "^1.1.5" - } - } - } - }, - "jest-message-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", - "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/stack-utils": "^1.0.1", - "chalk": "^2.0.1", - "micromatch": "^3.1.10", - "slash": "^2.0.0", - "stack-utils": "^1.0.1" - } - }, - "jest-mock": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", - "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0" - } - }, - "jest-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", - "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", - "dev": true, - "requires": { - "@jest/console": "^24.9.0", - "@jest/fake-timers": "^24.9.0", - "@jest/source-map": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "callsites": "^3.0.0", - "chalk": "^2.0.1", - "graceful-fs": "^4.1.15", - "is-ci": "^2.0.0", - "mkdirp": "^0.5.1", - "slash": "^2.0.0", - "source-map": "^0.6.0" - } - }, - "jsdom": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-14.1.0.tgz", - "integrity": "sha512-O901mfJSuTdwU2w3Sn+74T+RnDVP+FuV5fH8tcPWyqrseRAb0s5xOtPgCFiPOtLcyK7CLIJwPyD83ZqQWvA5ng==", - "dev": true, - "requires": { - "abab": "^2.0.0", - "acorn": "^6.0.4", - "acorn-globals": "^4.3.0", - "array-equal": "^1.0.0", - "cssom": "^0.3.4", - "cssstyle": "^1.1.1", - "data-urls": "^1.1.0", - "domexception": "^1.0.1", - "escodegen": "^1.11.0", - "html-encoding-sniffer": "^1.0.2", - "nwsapi": "^2.1.3", - "parse5": "5.1.0", - "pn": "^1.1.0", - "request": "^2.88.0", - "request-promise-native": "^1.0.5", - "saxes": "^3.1.9", - "symbol-tree": "^3.2.2", - "tough-cookie": "^2.5.0", - "w3c-hr-time": "^1.0.1", - "w3c-xmlserializer": "^1.1.2", - "webidl-conversions": "^4.0.2", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^7.0.0", - "ws": "^6.1.2", - "xml-name-validator": "^3.0.0" - } - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "parse5": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.0.tgz", - "integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==", - "dev": true - }, - "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true - }, - "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 - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - }, - "ws": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", - "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0" + "async-limiter": "~1.0.0" } } } }, "jest-environment-node": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-26.0.1.tgz", - "integrity": "sha512-4FRBWcSn5yVo0KtNav7+5NH5Z/tEgDLp7VRQVS5tCouWORxj+nI+1tOLutM07Zb2Qi7ja+HEDoOUkjBSWZg/IQ==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-24.9.0.tgz", + "integrity": "sha512-6d4V2f4nxzIzwendo27Tr0aFm+IXWa0XEUnaH6nU0FMaozxovt+sfRvh4J47wL1OvF83I3SSTu0XK+i4Bqe7uA==", "dev": true, "requires": { - "@jest/environment": "^26.0.1", - "@jest/fake-timers": "^26.0.1", - "@jest/types": "^26.0.1", - "jest-mock": "^26.0.1", - "jest-util": "^26.0.1" + "@jest/environment": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/types": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-util": "^24.9.0" } }, "jest-get-type": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.0.0.tgz", - "integrity": "sha512-zRc1OAPnnws1EVfykXOj19zo2EMw5Hi6HLbFCSjpuJiXtOWAYIjNsHVSbpQ8bDX7L5BGYGI8m+HmKdjHYFF0kg==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", + "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", "dev": true }, "jest-haste-map": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.0.1.tgz", - "integrity": "sha512-J9kBl/EdjmDsvyv7CiyKY5+DsTvVOScenprz/fGqfLg/pm1gdjbwwQ98nW0t+OIt+f+5nAVaElvn/6wP5KO7KA==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.9.0.tgz", + "integrity": "sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ==", "dev": true, "requires": { - "@jest/types": "^26.0.1", - "@types/graceful-fs": "^4.1.2", - "anymatch": "^3.0.3", + "@jest/types": "^24.9.0", + "anymatch": "^2.0.0", "fb-watchman": "^2.0.0", - "fsevents": "^2.1.2", - "graceful-fs": "^4.2.4", - "jest-serializer": "^26.0.0", - "jest-util": "^26.0.1", - "jest-worker": "^26.0.0", - "micromatch": "^4.0.2", + "fsevents": "^1.2.7", + "graceful-fs": "^4.1.15", + "invariant": "^2.2.4", + "jest-serializer": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.9.0", + "micromatch": "^3.1.10", "sane": "^4.0.3", - "walker": "^1.0.7", - "which": "^2.0.2" - }, - "dependencies": { - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } + "walker": "^1.0.7" } }, "jest-jasmine2": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-26.0.1.tgz", - "integrity": "sha512-ILaRyiWxiXOJ+RWTKupzQWwnPaeXPIoLS5uW41h18varJzd9/7I0QJGqg69fhTT1ev9JpSSo9QtalriUN0oqOg==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-24.9.0.tgz", + "integrity": "sha512-Cq7vkAgaYKp+PsX+2/JbTarrk0DmNhsEtqBXNwUHkdlbrTBLtMJINADf2mf5FkowNsq8evbPc07/qFO0AdKTzw==", "dev": true, "requires": { "@babel/traverse": "^7.1.0", - "@jest/environment": "^26.0.1", - "@jest/source-map": "^26.0.0", - "@jest/test-result": "^26.0.1", - "@jest/types": "^26.0.1", - "chalk": "^4.0.0", + "@jest/environment": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", "co": "^4.6.0", - "expect": "^26.0.1", + "expect": "^24.9.0", "is-generator-fn": "^2.0.0", - "jest-each": "^26.0.1", - "jest-matcher-utils": "^26.0.1", - "jest-message-util": "^26.0.1", - "jest-runtime": "^26.0.1", - "jest-snapshot": "^26.0.1", - "jest-util": "^26.0.1", - "pretty-format": "^26.0.1", - "throat": "^5.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", - "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "jest-each": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-snapshot": "^24.9.0", + "jest-util": "^24.9.0", + "pretty-format": "^24.9.0", + "throat": "^4.0.0" } }, "jest-leak-detector": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-26.0.1.tgz", - "integrity": "sha512-93FR8tJhaYIWrWsbmVN1pQ9ZNlbgRpfvrnw5LmgLRX0ckOJ8ut/I35CL7awi2ecq6Ca4lL59bEK9hr7nqoHWPA==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-24.9.0.tgz", + "integrity": "sha512-tYkFIDsiKTGwb2FG1w8hX9V0aUb2ot8zY/2nFg087dUageonw1zrLMP4W6zsRO59dPkTSKie+D4rhMuP9nRmrA==", "dev": true, "requires": { - "jest-get-type": "^26.0.0", - "pretty-format": "^26.0.1" + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" } }, "jest-matcher-utils": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.0.1.tgz", - "integrity": "sha512-PUMlsLth0Azen8Q2WFTwnSkGh2JZ8FYuwijC8NR47vXKpsrKmA1wWvgcj1CquuVfcYiDEdj985u5Wmg7COEARw==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz", + "integrity": "sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA==", "dev": true, "requires": { - "chalk": "^4.0.0", - "jest-diff": "^26.0.1", - "jest-get-type": "^26.0.0", - "pretty-format": "^26.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", - "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "chalk": "^2.0.1", + "jest-diff": "^24.9.0", + "jest-get-type": "^24.9.0", + "pretty-format": "^24.9.0" } }, "jest-message-util": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.0.1.tgz", - "integrity": "sha512-CbK8uQREZ8umUfo8+zgIfEt+W7HAHjQCoRaNs4WxKGhAYBGwEyvxuK81FXa7VeB9pwDEXeeKOB2qcsNVCAvB7Q==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", + "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@jest/types": "^26.0.1", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", "@types/stack-utils": "^1.0.1", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "micromatch": "^4.0.2", - "slash": "^3.0.0", - "stack-utils": "^2.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", - "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true - }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "stack-utils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.2.tgz", - "integrity": "sha512-0H7QK2ECz3fyZMzQ8rH0j2ykpfbnd20BFtfg/SqVC2+sCTtcw0aDTGB7dk+de4U4uUeuz6nOtJcrkFFLG1B0Rg==", - "dev": true, - "requires": { - "escape-string-regexp": "^2.0.0" - } - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "chalk": "^2.0.1", + "micromatch": "^3.1.10", + "slash": "^2.0.0", + "stack-utils": "^1.0.1" } }, "jest-mock": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.0.1.tgz", - "integrity": "sha512-MpYTBqycuPYSY6xKJognV7Ja46/TeRbAZept987Zp+tuJvMN0YBWyyhG9mXyYQaU3SBI0TUlSaO5L3p49agw7Q==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", + "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", "dev": true, "requires": { - "@jest/types": "^26.0.1" + "@jest/types": "^24.9.0" } }, "jest-pnp-resolver": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz", - "integrity": "sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", + "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", "dev": true }, "jest-regex-util": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-26.0.0.tgz", - "integrity": "sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz", + "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==", "dev": true }, "jest-resolve": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.0.1.tgz", - "integrity": "sha512-6jWxk0IKZkPIVTvq6s72RH735P8f9eCJW3IM5CX/SJFeKq1p2cZx0U49wf/SdMlhaB/anann5J2nCJj6HrbezQ==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.9.0.tgz", + "integrity": "sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==", "dev": true, "requires": { - "@jest/types": "^26.0.1", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", + "@jest/types": "^24.9.0", + "browser-resolve": "^1.11.3", + "chalk": "^2.0.1", "jest-pnp-resolver": "^1.2.1", - "jest-util": "^26.0.1", - "read-pkg-up": "^7.0.1", - "resolve": "^1.17.0", - "slash": "^3.0.0" + "realpath-native": "^1.1.0" + } + }, + "jest-resolve-dependencies": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-24.9.0.tgz", + "integrity": "sha512-Fm7b6AlWnYhT0BXy4hXpactHIqER7erNgIsIozDXWl5dVm+k8XdGVe1oTg1JyaFnOxarMEbax3wyRJqGP2Pq+g==", + "dev": true, + "requires": { + "@jest/types": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-snapshot": "^24.9.0" + } + }, + "jest-runner": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-24.9.0.tgz", + "integrity": "sha512-KksJQyI3/0mhcfspnxxEOBueGrd5E4vV7ADQLT9ESaCzz02WnbdbKWIf5Mkaucoaj7obQckYPVX6JJhgUcoWWg==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/environment": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "chalk": "^2.4.2", + "exit": "^0.1.2", + "graceful-fs": "^4.1.15", + "jest-config": "^24.9.0", + "jest-docblock": "^24.3.0", + "jest-haste-map": "^24.9.0", + "jest-jasmine2": "^24.9.0", + "jest-leak-detector": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-resolve": "^24.9.0", + "jest-runtime": "^24.9.0", + "jest-util": "^24.9.0", + "jest-worker": "^24.6.0", + "source-map-support": "^0.5.6", + "throat": "^4.0.0" + } + }, + "jest-runtime": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-24.9.0.tgz", + "integrity": "sha512-8oNqgnmF3v2J6PVRM2Jfuj8oX3syKmaynlDMMKQ4iyzbQzIG6th5ub/lM2bCMTmoTKM3ykcUYI2Pw9xwNtjMnw==", + "dev": true, + "requires": { + "@jest/console": "^24.7.1", + "@jest/environment": "^24.9.0", + "@jest/source-map": "^24.3.0", + "@jest/transform": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/yargs": "^13.0.0", + "chalk": "^2.0.1", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.1.15", + "jest-config": "^24.9.0", + "jest-haste-map": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-mock": "^24.9.0", + "jest-regex-util": "^24.3.0", + "jest-resolve": "^24.9.0", + "jest-snapshot": "^24.9.0", + "jest-util": "^24.9.0", + "jest-validate": "^24.9.0", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "strip-bom": "^3.0.0", + "yargs": "^13.3.0" + } + }, + "jest-serializer": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.9.0.tgz", + "integrity": "sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==", + "dev": true + }, + "jest-snapshot": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.9.0.tgz", + "integrity": "sha512-uI/rszGSs73xCM0l+up7O7a40o90cnrk429LOiK3aeTvfC0HHmldbd81/B7Ix81KSFe1lwkbl7GnBGG4UfuDew==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0", + "@jest/types": "^24.9.0", + "chalk": "^2.0.1", + "expect": "^24.9.0", + "jest-diff": "^24.9.0", + "jest-get-type": "^24.9.0", + "jest-matcher-utils": "^24.9.0", + "jest-message-util": "^24.9.0", + "jest-resolve": "^24.9.0", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "pretty-format": "^24.9.0", + "semver": "^6.2.0" }, "dependencies": { - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", - "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true - }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + } + } + }, + "jest-util": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", + "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", + "dev": true, + "requires": { + "@jest/console": "^24.9.0", + "@jest/fake-timers": "^24.9.0", + "@jest/source-map": "^24.9.0", + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "callsites": "^3.0.0", + "chalk": "^2.0.1", + "graceful-fs": "^4.1.15", + "is-ci": "^2.0.0", + "mkdirp": "^0.5.1", + "slash": "^2.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "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 - }, - "parse-json": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz", - "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1", - "lines-and-columns": "^1.1.6" - } - }, - "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "dependencies": { - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true - } - } - }, - "read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "requires": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - } - }, - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } } } }, - "jest-resolve-dependencies": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-26.0.1.tgz", - "integrity": "sha512-9d5/RS/ft0vB/qy7jct/qAhzJsr6fRQJyGAFigK3XD4hf9kIbEH5gks4t4Z7kyMRhowU6HWm/o8ILqhaHdSqLw==", + "jest-validate": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.9.0.tgz", + "integrity": "sha512-HPIt6C5ACwiqSiwi+OfSSHbK8sG7akG8eATl+IPKaeIjtPOeBUd/g3J7DghugzxrGjI93qS/+RPKe1H6PqvhRQ==", "dev": true, "requires": { - "@jest/types": "^26.0.1", - "jest-regex-util": "^26.0.0", - "jest-snapshot": "^26.0.1" + "@jest/types": "^24.9.0", + "camelcase": "^5.3.1", + "chalk": "^2.0.1", + "jest-get-type": "^24.9.0", + "leven": "^3.1.0", + "pretty-format": "^24.9.0" } }, - "jest-runner": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-26.0.1.tgz", - "integrity": "sha512-CApm0g81b49Znm4cZekYQK67zY7kkB4umOlI2Dx5CwKAzdgw75EN+ozBHRvxBzwo1ZLYZ07TFxkaPm+1t4d8jA==", + "jest-watch-typeahead": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-0.4.2.tgz", + "integrity": "sha512-f7VpLebTdaXs81rg/oj4Vg/ObZy2QtGzAmGLNsqUS5G5KtSN68tFcIsbvNODfNyQxU78g7D8x77o3bgfBTR+2Q==", "dev": true, "requires": { - "@jest/console": "^26.0.1", - "@jest/environment": "^26.0.1", - "@jest/test-result": "^26.0.1", - "@jest/types": "^26.0.1", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.4", - "jest-config": "^26.0.1", - "jest-docblock": "^26.0.0", - "jest-haste-map": "^26.0.1", - "jest-jasmine2": "^26.0.1", - "jest-leak-detector": "^26.0.1", - "jest-message-util": "^26.0.1", - "jest-resolve": "^26.0.1", - "jest-runtime": "^26.0.1", - "jest-util": "^26.0.1", - "jest-worker": "^26.0.0", - "source-map-support": "^0.5.6", - "throat": "^5.0.0" + "ansi-escapes": "^4.2.1", + "chalk": "^2.4.1", + "jest-regex-util": "^24.9.0", + "jest-watcher": "^24.3.0", + "slash": "^3.0.0", + "string-length": "^3.1.0", + "strip-ansi": "^5.0.0" }, "dependencies": { - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true }, - "chalk": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", - "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", + "string-length": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-3.1.0.tgz", + "integrity": "sha512-Ttp5YvkGm5v9Ijagtaz1BnN+k9ObpvS0eIBblPMp2YWL8FBmi9qblQ9fexc2k/CXFgrTIteU3jAw3payCnwSTA==", "dev": true, "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-runtime": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-26.0.1.tgz", - "integrity": "sha512-Ci2QhYFmANg5qaXWf78T2Pfo6GtmIBn2rRaLnklRyEucmPccmCKvS9JPljcmtVamsdMmkyNkVFb9pBTD6si9Lw==", - "dev": true, - "requires": { - "@jest/console": "^26.0.1", - "@jest/environment": "^26.0.1", - "@jest/fake-timers": "^26.0.1", - "@jest/globals": "^26.0.1", - "@jest/source-map": "^26.0.0", - "@jest/test-result": "^26.0.1", - "@jest/transform": "^26.0.1", - "@jest/types": "^26.0.1", - "@types/yargs": "^15.0.0", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.4", - "jest-config": "^26.0.1", - "jest-haste-map": "^26.0.1", - "jest-message-util": "^26.0.1", - "jest-mock": "^26.0.1", - "jest-regex-util": "^26.0.0", - "jest-resolve": "^26.0.1", - "jest-snapshot": "^26.0.1", - "jest-util": "^26.0.1", - "jest-validate": "^26.0.1", - "slash": "^3.0.0", - "strip-bom": "^4.0.0", - "yargs": "^15.3.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", - "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" + "astral-regex": "^1.0.0", + "strip-ansi": "^5.2.0" } } } }, - "jest-serializer": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.0.0.tgz", - "integrity": "sha512-sQGXLdEGWFAE4wIJ2ZaIDb+ikETlUirEOBsLXdoBbeLhTHkZUJwgk3+M8eyFizhM6le43PDCCKPA1hzkSDo4cQ==", + "jest-watcher": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-24.9.0.tgz", + "integrity": "sha512-+/fLOfKPXXYJDYlks62/4R4GoT+GU1tYZed99JSCOsmzkkF7727RqKrjNAxtfO4YpGv11wybgRvCjR73lK2GZw==", "dev": true, "requires": { - "graceful-fs": "^4.2.4" + "@jest/test-result": "^24.9.0", + "@jest/types": "^24.9.0", + "@types/yargs": "^13.0.0", + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.1", + "jest-util": "^24.9.0", + "string-length": "^2.0.0" }, "dependencies": { - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", "dev": true } } }, - "jest-snapshot": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-26.0.1.tgz", - "integrity": "sha512-jxd+cF7+LL+a80qh6TAnTLUZHyQoWwEHSUFJjkw35u3Gx+BZUNuXhYvDqHXr62UQPnWo2P6fvQlLjsU93UKyxA==", + "jest-worker": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", + "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", "dev": true, "requires": { - "@babel/types": "^7.0.0", - "@jest/types": "^26.0.1", - "@types/prettier": "^2.0.0", - "chalk": "^4.0.0", - "expect": "^26.0.1", - "graceful-fs": "^4.2.4", - "jest-diff": "^26.0.1", - "jest-get-type": "^26.0.0", - "jest-matcher-utils": "^26.0.1", - "jest-message-util": "^26.0.1", - "jest-resolve": "^26.0.1", - "make-dir": "^3.0.0", - "natural-compare": "^1.4.0", - "pretty-format": "^26.0.1", - "semver": "^7.3.2" + "merge-stream": "^2.0.0", + "supports-color": "^6.1.0" }, "dependencies": { - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", - "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", - "dev": true - }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", "dev": true, "requires": { - "has-flag": "^4.0.0" + "has-flag": "^3.0.0" } } } }, - "jest-util": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.0.1.tgz", - "integrity": "sha512-byQ3n7ad1BO/WyFkYvlWQHTsomB6GIewBh8tlGtusiylAlaxQ1UpS0XYH0ngOyhZuHVLN79Qvl6/pMiDMSSG1g==", + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", "dev": true, "requires": { - "@jest/types": "^26.0.1", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "is-ci": "^2.0.0", - "make-dir": "^3.0.0" + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "jsdom": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", + "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", + "dev": true, + "requires": { + "abab": "^2.0.0", + "acorn": "^5.5.3", + "acorn-globals": "^4.1.0", + "array-equal": "^1.0.0", + "cssom": ">= 0.3.2 < 0.4.0", + "cssstyle": "^1.0.0", + "data-urls": "^1.0.0", + "domexception": "^1.0.1", + "escodegen": "^1.9.1", + "html-encoding-sniffer": "^1.0.2", + "left-pad": "^1.3.0", + "nwsapi": "^2.0.7", + "parse5": "4.0.0", + "pn": "^1.1.0", + "request": "^2.87.0", + "request-promise-native": "^1.0.5", + "sax": "^1.2.4", + "symbol-tree": "^3.2.2", + "tough-cookie": "^2.3.4", + "w3c-hr-time": "^1.0.1", + "webidl-conversions": "^4.0.2", + "whatwg-encoding": "^1.0.3", + "whatwg-mimetype": "^2.1.0", + "whatwg-url": "^6.4.1", + "ws": "^5.2.0", + "xml-name-validator": "^3.0.0" }, "dependencies": { - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", - "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "acorn": { + "version": "5.7.4", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.4.tgz", + "integrity": "sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg==", "dev": true }, - "has-flag": { + "parse5": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", + "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", "dev": true - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } } } }, - "jest-validate": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-26.0.1.tgz", - "integrity": "sha512-u0xRc+rbmov/VqXnX3DlkxD74rHI/CfS5xaV2VpeaVySjbb1JioNVOyly5b56q2l9ZKe7bVG5qWmjfctkQb0bA==", + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", "dev": true, "requires": { - "@jest/types": "^26.0.1", - "camelcase": "^6.0.0", - "chalk": "^4.0.0", - "jest-get-type": "^26.0.0", - "leven": "^3.1.0", - "pretty-format": "^26.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "jsonify": "~0.0.0" + } + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "json3": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz", + "integrity": "sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==", + "dev": true + }, + "json5": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "jsx-ast-utils": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.4.1.tgz", + "integrity": "sha512-z1xSldJ6imESSzOjd3NNkieVJKRlKYSOtMG8SFyCj2FIrvSaSuli/WjpBkEzCBoR9bYYYFgqJw61Xhu7Lcgk+w==", + "dev": true, + "requires": { + "array-includes": "^3.1.1", + "object.assign": "^4.1.0" + } + }, + "killable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", + "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==", + "dev": true + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true + }, + "last-call-webpack-plugin": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz", + "integrity": "sha512-7KI2l2GIZa9p2spzPIVZBYyNKkN+e/SQPpnjlTiPhdbDW3F86tdKKELxKpzJ5sgU19wQWsACULZmpTPYHeWO5w==", + "dev": true, + "requires": { + "lodash": "^4.17.5", + "webpack-sources": "^1.1.0" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true + }, + "lcid": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", + "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "dev": true, + "requires": { + "invert-kv": "^2.0.0" + } + }, + "left-pad": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", + "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==", + "dev": true + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true + }, + "levenary": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/levenary/-/levenary-1.1.1.tgz", + "integrity": "sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ==", + "dev": true, + "requires": { + "leven": "^3.1.0" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "loader-fs-cache": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/loader-fs-cache/-/loader-fs-cache-1.0.3.tgz", + "integrity": "sha512-ldcgZpjNJj71n+2Mf6yetz+c9bM4xpKtNds4LbqXzU/PTdeAX0g3ytnU1AJMEcTk2Lex4Smpe3Q/eCTsvUBxbA==", + "dev": true, + "requires": { + "find-cache-dir": "^0.1.1", + "mkdirp": "^0.5.1" + }, + "dependencies": { + "find-cache-dir": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-0.1.1.tgz", + "integrity": "sha1-yN765XyKUqinhPnjHFfHQumToLk=", "dev": true, "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" + "commondir": "^1.0.1", + "mkdirp": "^0.5.1", + "pkg-dir": "^1.0.0" } }, - "camelcase": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.0.0.tgz", - "integrity": "sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w==", - "dev": true - }, - "chalk": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", - "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dev": true, "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" } }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true, "requires": { - "color-name": "~1.1.4" + "pinkie-promise": "^2.0.0" } }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "pkg-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", + "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", "dev": true, "requires": { - "has-flag": "^4.0.0" + "find-up": "^1.0.0" } } } }, - "jest-watch-typeahead": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/jest-watch-typeahead/-/jest-watch-typeahead-0.4.0.tgz", - "integrity": "sha512-bJR/HPNgOQnkmttg1OkBIrYFAYuxFxExtgQh67N2qPvaWGVC8TCkedRNPKBfmZfVXFD3u2sCH+9OuS5ApBfCgA==", + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", "dev": true, "requires": { - "ansi-escapes": "^4.2.1", - "chalk": "^2.4.1", - "jest-watcher": "^24.3.0", - "slash": "^3.0.0", - "string-length": "^3.1.0", - "strip-ansi": "^5.0.0" + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" }, "dependencies": { - "@jest/console": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", - "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", - "dev": true, - "requires": { - "@jest/source-map": "^24.9.0", - "chalk": "^2.0.1", - "slash": "^2.0.0" - }, - "dependencies": { - "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true - } - } - }, - "@jest/fake-timers": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", - "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-mock": "^24.9.0" + "minimist": "^1.2.0" } - }, - "@jest/source-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", - "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", - "dev": true, - "requires": { - "callsites": "^3.0.0", - "graceful-fs": "^4.1.15", - "source-map": "^0.6.0" - } - }, - "@jest/test-result": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", - "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", + } + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.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 + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash.escape": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz", + "integrity": "sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg=", + "dev": true + }, + "lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", + "dev": true + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", + "dev": true + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "dev": true + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", + "dev": true + }, + "lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0" + } + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", + "dev": true + }, + "loglevel": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.8.tgz", + "integrity": "sha512-bsU7+gc9AJ2SqpzxwU3+1fedl8zAntbtC5XYlt3s2j1hJcn2PsXSmgN8TaLG/J1/2mod4+cE/3vNL70/c1RNCA==", + "dev": true + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "lower-case": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.1.tgz", + "integrity": "sha512-LiWgfDLLb1dwbFQZsSglpRj+1ctGnayXz3Uv0/WO8n558JycT5fg6zkNcnW0G68Nn0aEldTFeEfmjCfmqry/rQ==", + "dev": true, + "requires": { + "tslib": "^1.10.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + }, + "dependencies": { + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "makeerror": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", + "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", + "dev": true, + "requires": { + "tmpl": "1.0.x" + } + }, + "mamacro": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", + "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==", + "dev": true + }, + "map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dev": true, + "requires": { + "p-defer": "^1.0.0" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "mdn-data": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", + "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==", + "dev": true + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "mem": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", + "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", + "dev": true, + "requires": { + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { - "@jest/console": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/istanbul-lib-coverage": "^2.0.0" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" + "safe-buffer": "~5.1.0" } - }, - "@types/yargs": { - "version": "13.0.8", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.8.tgz", - "integrity": "sha512-XAvHLwG7UQ+8M4caKIH0ZozIOYay5fQkAgyIXegXT9jPtdIGdhga+sUEdAr1CiG46aB+c64xQEYyEzlwWVTNzA==", + } + } + }, + "merge-deep": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/merge-deep/-/merge-deep-3.0.2.tgz", + "integrity": "sha512-T7qC8kg4Zoti1cFd8Cr0M+qaZfOwjlPDEdZIIPPB2JZctjaPM4fX+i7HOId69tAti2fvO6X5ldfYUONDODsrkA==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "clone-deep": "^0.2.4", + "kind-of": "^3.0.2" + }, + "dependencies": { + "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": { - "@types/yargs-parser": "*" - } - }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "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": { - "is-buffer": "^1.1.5" - } - } - } - }, - "jest-message-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", - "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/stack-utils": "^1.0.1", - "chalk": "^2.0.1", - "micromatch": "^3.1.10", - "slash": "^2.0.0", - "stack-utils": "^1.0.1" - }, - "dependencies": { - "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true - } - } - }, - "jest-mock": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", - "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0" - } - }, - "jest-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", - "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", - "dev": true, - "requires": { - "@jest/console": "^24.9.0", - "@jest/fake-timers": "^24.9.0", - "@jest/source-map": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "callsites": "^3.0.0", - "chalk": "^2.0.1", - "graceful-fs": "^4.1.15", - "is-ci": "^2.0.0", - "mkdirp": "^0.5.1", - "slash": "^2.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true - } - } - }, - "jest-watcher": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-24.9.0.tgz", - "integrity": "sha512-+/fLOfKPXXYJDYlks62/4R4GoT+GU1tYZed99JSCOsmzkkF7727RqKrjNAxtfO4YpGv11wybgRvCjR73lK2GZw==", - "dev": true, - "requires": { - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/yargs": "^13.0.0", - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.1", - "jest-util": "^24.9.0", - "string-length": "^2.0.0" - }, - "dependencies": { - "ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true - }, - "string-length": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", - "integrity": "sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=", - "dev": true, - "requires": { - "astral-regex": "^1.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "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 - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - } - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" + "is-buffer": "^1.1.5" } } } }, - "jest-watcher": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-26.0.1.tgz", - "integrity": "sha512-pdZPydsS8475f89kGswaNsN3rhP6lnC3/QDCppP7bg1L9JQz7oU9Mb/5xPETk1RHDCWeqmVC47M4K5RR7ejxFw==", + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "microevent.ts": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/microevent.ts/-/microevent.ts-0.1.1.tgz", + "integrity": "sha512-jo1OfR4TaEwd5HOrt5+tAZ9mqT4jmpNAusXtyfNzqVm9uiSYFZlKM1wYL4oU7azZW/PxQW53wM0S6OR1JHNa2g==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "dev": true, "requires": { - "@jest/test-result": "^26.0.1", - "@jest/types": "^26.0.1", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "jest-util": "^26.0.1", - "string-length": "^4.0.1" + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", "dev": true - }, - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + } + } + }, + "mime": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", + "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", + "dev": true + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==", + "dev": true + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "dev": true, + "requires": { + "mime-db": "1.44.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "mini-css-extract-plugin": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz", + "integrity": "sha512-lp3GeY7ygcgAmVIcRPBVhIkf8Us7FZjA+ILpal44qLdSu11wmjKQ3d9k15lfD7pO4esu9eUIAW7qiYIBppv40A==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "normalize-url": "1.9.1", + "schema-utils": "^1.0.0", + "webpack-sources": "^1.1.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", "dev": true, "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", - "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "string-length": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.1.tgz", - "integrity": "sha512-PKyXUd0LK0ePjSOnWn34V2uD6acUWev9uy0Ft05k0E8xRW+SKcA0F7eMr7h5xlzfn+4O3N+55rduYyet3Jk+jw==", - "dev": true, - "requires": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "jest-worker": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.0.0.tgz", - "integrity": "sha512-pPaYa2+JnwmiZjK9x7p9BoZht+47ecFCDFA/CJxspHzeDvQcfVBLWzCiWyo+EGrSiQMWZtCFo9iSvMZnAAo8vw==", - "dev": true, - "requires": { - "merge-stream": "^2.0.0", - "supports-color": "^7.0.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" } } } }, - "js-levenshtein": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", - "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", "dev": true }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "brace-expansion": "^1.1.7" } }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, - "jsdom": { - "version": "16.2.2", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.2.2.tgz", - "integrity": "sha512-pDFQbcYtKBHxRaP55zGXCJWgFHkDAYbKcsXEK/3Icu9nKYZkutUXfLBwbD+09XDutkYSHcgfQLZ0qvpAAm9mvg==", + "minipass": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", "dev": true, "requires": { - "abab": "^2.0.3", - "acorn": "^7.1.1", - "acorn-globals": "^6.0.0", - "cssom": "^0.4.4", - "cssstyle": "^2.2.0", - "data-urls": "^2.0.0", - "decimal.js": "^10.2.0", - "domexception": "^2.0.1", - "escodegen": "^1.14.1", - "html-encoding-sniffer": "^2.0.1", - "is-potential-custom-element-name": "^1.0.0", - "nwsapi": "^2.2.0", - "parse5": "5.1.1", - "request": "^2.88.2", - "request-promise-native": "^1.0.8", - "saxes": "^5.0.0", - "symbol-tree": "^3.2.4", - "tough-cookie": "^3.0.1", - "w3c-hr-time": "^1.0.2", - "w3c-xmlserializer": "^2.0.0", - "webidl-conversions": "^6.0.0", - "whatwg-encoding": "^1.0.5", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.0.0", - "ws": "^7.2.3", - "xml-name-validator": "^3.0.0" - }, - "dependencies": { - "acorn": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.2.0.tgz", - "integrity": "sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ==", - "dev": true - }, - "acorn-globals": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", - "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", - "dev": true, - "requires": { - "acorn": "^7.1.1", - "acorn-walk": "^7.1.1" - } - }, - "acorn-walk": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.1.1.tgz", - "integrity": "sha512-wdlPY2tm/9XBr7QkKlq0WQVgiuGTX6YWPyRyBviSoScBuLfTVQhvwg6wJ369GJ/1nPfTLMfnrFIfjqVg6d+jQQ==", - "dev": true - }, - "browser-process-hrtime": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", - "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", - "dev": true - }, - "data-urls": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-2.0.0.tgz", - "integrity": "sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==", - "dev": true, - "requires": { - "abab": "^2.0.3", - "whatwg-mimetype": "^2.3.0", - "whatwg-url": "^8.0.0" - } - }, - "domexception": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/domexception/-/domexception-2.0.1.tgz", - "integrity": "sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==", - "dev": true, - "requires": { - "webidl-conversions": "^5.0.0" - }, - "dependencies": { - "webidl-conversions": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", - "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", - "dev": true - } - } - }, - "html-encoding-sniffer": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz", - "integrity": "sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==", - "dev": true, - "requires": { - "whatwg-encoding": "^1.0.5" - } - }, - "parse5": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", - "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==", - "dev": true - }, - "saxes": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz", - "integrity": "sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==", - "dev": true, - "requires": { - "xmlchars": "^2.2.0" - } - }, - "tr46": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-2.0.2.tgz", - "integrity": "sha512-3n1qG+/5kg+jrbTzwAykB5yRYtQCTqOGKq5U5PE3b0a1/mzo6snDhjGS0zJVJunO0NrT3Dg1MLy5TjWP/UJppg==", - "dev": true, - "requires": { - "punycode": "^2.1.1" - } - }, - "w3c-hr-time": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", - "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", - "dev": true, - "requires": { - "browser-process-hrtime": "^1.0.0" - } - }, - "w3c-xmlserializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", - "integrity": "sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==", - "dev": true, - "requires": { - "xml-name-validator": "^3.0.0" - } - }, - "webidl-conversions": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-6.1.0.tgz", - "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==", - "dev": true - }, - "whatwg-url": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.1.0.tgz", - "integrity": "sha512-vEIkwNi9Hqt4TV9RdnaBPNt+E2Sgmo3gePebCRgZ1R7g6d23+53zCTnuB0amKI4AXq6VM8jj2DUAa0S1vjJxkw==", - "dev": true, - "requires": { - "lodash.sortby": "^4.7.0", - "tr46": "^2.0.2", - "webidl-conversions": "^5.0.0" - }, - "dependencies": { - "webidl-conversions": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", - "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", - "dev": true - } - } - } + "yallist": "^4.0.0" } }, - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - }, - "json-parse-better-errors": { + "minipass-collect": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", - "dev": true - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", "dev": true, "requires": { - "jsonify": "~0.0.0" + "minipass": "^3.0.0" } }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "json3": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz", - "integrity": "sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==", - "dev": true - }, - "json5": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", - "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", + "minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", "dev": true, "requires": { - "minimist": "^1.2.0" + "minipass": "^3.0.0" } }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", "dev": true, "requires": { - "graceful-fs": "^4.1.6" + "minipass": "^3.0.0" } }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", "dev": true, "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "jsx-ast-utils": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.2.3.tgz", - "integrity": "sha512-EdIHFMm+1BPynpKOpdPqiOsvnIrInRGJD7bzPZdPkjitQEqpdpUuFpq4T0npZFKTiB3RhWFdGN+oqOJIdhDhQA==", + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + } + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", "dev": true, "requires": { - "array-includes": "^3.0.3", - "object.assign": "^4.1.0" + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } } }, - "killable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", - "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==", - "dev": true + "mixin-object": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", + "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=", + "dev": true, + "requires": { + "for-in": "^0.1.3", + "is-extendable": "^0.1.1" + }, + "dependencies": { + "for-in": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz", + "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=", + "dev": true + } + } }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } }, - "kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "moo": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", + "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==", "dev": true }, - "last-call-webpack-plugin": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz", - "integrity": "sha512-7KI2l2GIZa9p2spzPIVZBYyNKkN+e/SQPpnjlTiPhdbDW3F86tdKKELxKpzJ5sgU19wQWsACULZmpTPYHeWO5w==", + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", "dev": true, "requires": { - "lodash": "^4.17.5", - "webpack-sources": "^1.1.0" + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" } }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, - "lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", + "multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", "dev": true, "requires": { - "invert-kv": "^2.0.0" + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" } }, - "left-pad": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", - "integrity": "sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA==", + "multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", "dev": true }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "nan": { + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", + "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", + "dev": true, + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", "dev": true, "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" } }, - "lines-and-columns": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", - "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, - "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "nearley": { + "version": "2.19.5", + "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.19.5.tgz", + "integrity": "sha512-qoh1ZXXl0Kpn40tFhmgvffUAlbpRMcjLUagNVnT1JmliUIsB4tFabmCNhD97+tkf9FZ/SLhhYzNow0V3GitzDg==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - } + "commander": "^2.19.0", + "moo": "^0.5.0", + "railroad-diagrams": "^1.0.0", + "randexp": "0.4.6", + "semver": "^5.4.1" } }, - "loader-fs-cache": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/loader-fs-cache/-/loader-fs-cache-1.0.2.tgz", - "integrity": "sha512-70IzT/0/L+M20jUlEqZhZyArTU6VKLRTYRDAYN26g4jfzpJqjipLL3/hgYpySqI9PwsVRHHFja0LfEmsx9X2Cw==", + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "no-case": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.3.tgz", + "integrity": "sha512-ehY/mVQCf9BL0gKfsJBvFJen+1V//U+0HQMPrWct40ixE4jnv0bfvxDbWtAHL9EcaPEOJHVVYKoQn1TlZUB8Tw==", "dev": true, "requires": { - "find-cache-dir": "^0.1.1", - "mkdirp": "0.5.1" - }, - "dependencies": { - "find-cache-dir": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-0.1.1.tgz", - "integrity": "sha1-yN765XyKUqinhPnjHFfHQumToLk=", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "mkdirp": "^0.5.1", - "pkg-dir": "^1.0.0" - } - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - }, - "pkg-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", - "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", - "dev": true, - "requires": { - "find-up": "^1.0.0" - } - } + "lower-case": "^2.0.1", + "tslib": "^1.10.0" } }, - "loader-runner": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", - "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "node-forge": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.0.tgz", + "integrity": "sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ==", "dev": true }, - "loader-utils": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", - "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^2.0.0", - "json5": "^1.0.1" + "node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", + "dev": true + }, + "node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "dev": true, + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" }, "dependencies": { - "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { - "minimist": "^1.2.0" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "requires": { + "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } } } } }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "node-modules-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", + "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", + "dev": true + }, + "node-notifier": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.3.tgz", + "integrity": "sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q==", "dev": true, "requires": { - "p-locate": "^4.1.0" + "growly": "^1.3.0", + "is-wsl": "^1.1.0", + "semver": "^5.5.0", + "shellwords": "^0.1.1", + "which": "^1.3.0" } }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", - "dev": true - }, - "lodash.escape": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz", - "integrity": "sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg=", + "node-releases": { + "version": "1.1.60", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.60.tgz", + "integrity": "sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA==", "dev": true }, - "lodash.flattendeep": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", - "dev": true + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } }, - "lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, - "lodash.memoize": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", - "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", "dev": true }, - "lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", - "dev": true + "normalize-url": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", + "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", + "dev": true, + "requires": { + "object-assign": "^4.0.1", + "prepend-http": "^1.0.0", + "query-string": "^4.1.0", + "sort-keys": "^1.0.0" + } }, - "lodash.template": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", - "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", "dev": true, "requires": { - "lodash._reinterpolate": "^3.0.0", - "lodash.templatesettings": "^4.0.0" + "path-key": "^2.0.0" } }, - "lodash.templatesettings": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", - "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", "dev": true, "requires": { - "lodash._reinterpolate": "^3.0.0" + "boolbase": "~1.0.0" } }, - "lodash.uniq": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", "dev": true }, - "loglevel": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.7.tgz", - "integrity": "sha512-cY2eLFrQSAfVPhCgH1s7JI73tMbg9YC3v3+ZHVW67sBS7UxWzNEk/ZBbSfLykBWHp33dqqtOv82gjhKEi81T/A==", + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } + "nwsapi": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", + "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", + "dev": true }, - "lower-case": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", - "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", "dev": true }, - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "requires": { - "yallist": "^3.0.2" - } + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, "requires": { - "semver": "^6.0.0" + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" }, "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "makeerror": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.11.tgz", - "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", - "dev": true, - "requires": { - "tmpl": "1.0.x" - } - }, - "mamacro": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/mamacro/-/mamacro-0.0.3.tgz", - "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==", - "dev": true - }, - "map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "dev": true, - "requires": { - "p-defer": "^1.0.0" - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, - "md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "dev": true, - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "mdn-data": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", - "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==", - "dev": true - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true - }, - "mem": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", - "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", - "dev": true, - "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" - } - }, - "memory-fs": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", - "dev": true, - "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "is-descriptor": "^0.1.0" } }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "merge-deep": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/merge-deep/-/merge-deep-3.0.2.tgz", - "integrity": "sha512-T7qC8kg4Zoti1cFd8Cr0M+qaZfOwjlPDEdZIIPPB2JZctjaPM4fX+i7HOId69tAti2fvO6X5ldfYUONDODsrkA==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "clone-deep": "^0.2.4", - "kind-of": "^3.0.2" - }, - "dependencies": { "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -12546,382 +9795,329 @@ } } }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "object-hash": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.0.3.tgz", + "integrity": "sha512-JPKn0GMu+Fa3zt3Bmr66JhokJU5BaNBIh4ZeTlaCBzrBsOeXzwcKKAK1tbLiPKgvwmPXsDvvLHoWh5Bm7ofIYg==", "dev": true }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "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 }, - "merge2": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.3.0.tgz", - "integrity": "sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==", + "object-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.2.tgz", + "integrity": "sha512-Epah+btZd5wrrfjkJZq1AOB9O6OxUQto45hzFd7lXGrpHPGE0W1k+426yrZV+k6NJOzLNNW/nVsmZdIWsAqoOQ==", "dev": true }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "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 }, - "microevent.ts": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/microevent.ts/-/microevent.ts-0.1.1.tgz", - "integrity": "sha512-jo1OfR4TaEwd5HOrt5+tAZ9mqT4jmpNAusXtyfNzqVm9uiSYFZlKM1wYL4oU7azZW/PxQW53wM0S6OR1JHNa2g==", + "object-path": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.4.tgz", + "integrity": "sha1-NwrnUvvzfePqcKhhwju6iRVpGUk=", "dev": true }, - "micromatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", - "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", "dev": true, "requires": { - "braces": "^3.0.1", - "picomatch": "^2.0.5" + "isobject": "^3.0.0" } }, - "miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", "dev": true, "requires": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" } }, - "mime": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", - "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", - "dev": true - }, - "mime-db": { - "version": "1.43.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", - "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", - "dev": true + "object.entries": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.1.tgz", + "integrity": "sha512-ilqR7BgdyZetJutmDPfXCDffGa0/Yzl2ivVNpbx/g4UeWrCdRnFDUBrKJGLhGieRHDATnyZXWBeCb29k9CJysQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } }, - "mime-types": { - "version": "2.1.26", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", - "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", + "object.fromentries": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.2.tgz", + "integrity": "sha512-r3ZiBH7MQppDJVLx6fhD618GKNG40CZYH9wgwdhKxBDDbQgjeWGGd4AtkZad84d291YxvWe7bJGuE65Anh0dxQ==", "dev": true, "requires": { - "mime-db": "1.43.0" + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" } }, - "mimic-fn": { + "object.getownpropertydescriptors": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", + "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } }, - "mini-css-extract-plugin": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.8.0.tgz", - "integrity": "sha512-MNpRGbNA52q6U92i0qbVpQNsgk7LExy41MdAlG84FeytfDOtRIf/mCHdEgG8rpTKOaNKiqUnZdlptF469hxqOw==", + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", "dev": true, "requires": { - "loader-utils": "^1.1.0", - "normalize-url": "1.9.1", - "schema-utils": "^1.0.0", - "webpack-sources": "^1.1.0" + "isobject": "^3.0.1" } }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true + "object.values": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", + "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } }, - "minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", "dev": true }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "ee-first": "1.1.1" } }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", "dev": true }, - "mississippi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", - "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^3.0.0", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" + "wrappy": "1" } }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "onetime": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", + "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", "dev": true, "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" + "mimic-fn": "^2.1.0" + } + }, + "open": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-7.1.0.tgz", + "integrity": "sha512-lLPI5KgOwEYCDKXf4np7y1PBEkj7HYIyP2DY8mVDRnx0VIIu6bNrRB0R66TuO7Mack6EnTNLm4uvcl1UoklTpA==", + "dev": true, + "requires": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" }, "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", "dev": true, "requires": { - "is-plain-object": "^2.0.4" + "is-docker": "^2.0.0" } } } }, - "mixin-object": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mixin-object/-/mixin-object-2.0.1.tgz", - "integrity": "sha1-T7lJRB2rGCVA8f4DW6YOGUel5X4=", + "opn": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", + "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", "dev": true, "requires": { - "for-in": "^0.1.3", - "is-extendable": "^0.1.1" - }, - "dependencies": { - "for-in": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-0.1.8.tgz", - "integrity": "sha1-2Hc5COMSVhCZUrH9ubP6hn0ndeE=", - "dev": true - } + "is-wsl": "^1.1.0" } }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "optimize-css-assets-webpack-plugin": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.3.tgz", + "integrity": "sha512-q9fbvCRS6EYtUKKSwI87qm2IxlyJK5b4dygW1rKUBT6mMDhdG5e5bZT63v6tnJR9F9FB/H5a0HTmtw+laUBxKA==", "dev": true, "requires": { - "minimist": "0.0.8" - }, - "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - } + "cssnano": "^4.1.10", + "last-call-webpack-plugin": "^3.0.0" } }, - "moo": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", - "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==", - "dev": true + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + } }, - "move-concurrently": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", - "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "original": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", + "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", "dev": true, "requires": { - "aproba": "^1.1.1", - "copy-concurrently": "^1.0.0", - "fs-write-stream-atomic": "^1.0.8", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.3" - }, - "dependencies": { - "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" - } - } + "url-parse": "^1.4.3" } }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", "dev": true }, - "multicast-dns": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", - "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "os-locale": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", + "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", "dev": true, "requires": { - "dns-packet": "^1.3.1", - "thunky": "^1.0.2" + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" } }, - "multicast-dns-service-types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", - "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, - "mute-stream": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", - "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", "dev": true }, - "nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", - "dev": true, - "optional": true - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "p-each-series": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz", + "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", "dev": true, "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "p-reduce": "^1.0.0" } }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", "dev": true }, - "nearley": { - "version": "2.19.1", - "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.19.1.tgz", - "integrity": "sha512-xq47GIUGXxU9vQg7g/y1o1xuKnkO7ev4nRWqftmQrLkfnE/FjRqDaGOUakM8XHPn/6pW3bGjU2wgoJyId90rqg==", + "p-is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", + "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", + "dev": true + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "requires": { - "commander": "^2.19.0", - "moo": "^0.5.0", - "railroad-diagrams": "^1.0.0", - "randexp": "0.4.6", - "semver": "^5.4.1" + "p-try": "^2.0.0" } }, - "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", - "dev": true + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } }, - "neo-async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", - "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", - "dev": true + "p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } }, - "next-tick": { + "p-reduce": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", + "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", "dev": true }, - "no-case": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", - "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "p-retry": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", + "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==", "dev": true, "requires": { - "lower-case": "^1.1.1" + "retry": "^0.12.0" } }, - "node-forge": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.0.tgz", - "integrity": "sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ==", + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, - "node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs=", + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", "dev": true }, - "node-libs-browser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", - "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", "dev": true, "requires": { - "assert": "^1.1.1", - "browserify-zlib": "^0.2.0", - "buffer": "^4.3.0", - "console-browserify": "^1.1.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.11.0", - "domain-browser": "^1.1.1", - "events": "^3.0.0", - "https-browserify": "^1.0.0", - "os-browserify": "^0.3.0", - "path-browserify": "0.0.1", - "process": "^0.11.10", - "punycode": "^1.2.4", - "querystring-es3": "^0.2.0", - "readable-stream": "^2.3.3", - "stream-browserify": "^2.0.1", - "stream-http": "^2.7.2", - "string_decoder": "^1.0.0", - "timers-browserify": "^2.0.4", - "tty-browserify": "0.0.0", - "url": "^0.11.0", - "util": "^0.11.0", - "vm-browserify": "^1.0.1" + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" }, "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - }, "readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", @@ -12935,2082 +10131,1590 @@ "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" - }, - "dependencies": { - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } } }, - "util": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", - "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, "requires": { - "inherits": "2.0.3" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - } + "safe-buffer": "~5.1.0" } } } }, - "node-modules-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", - "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", - "dev": true - }, - "node-notifier": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-7.0.0.tgz", - "integrity": "sha512-y8ThJESxsHcak81PGpzWwQKxzk+5YtP3IxR8AYdpXQ1IB6FmcVzFdZXrkPin49F/DKUCfeeiziB8ptY9npzGuA==", + "param-case": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.3.tgz", + "integrity": "sha512-VWBVyimc1+QrzappRs7waeN2YmoZFCGXWASRYX1/rGHtXqEcrGEIDm+jqIwFa2fRXNgQEwrxaYuIrX0WcAguTA==", "dev": true, - "optional": true, "requires": { - "growly": "^1.3.0", - "is-wsl": "^2.1.1", - "semver": "^7.2.1", - "shellwords": "^0.1.1", - "uuid": "^7.0.3", - "which": "^2.0.2" - }, - "dependencies": { - "semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", - "dev": true, - "optional": true - }, - "uuid": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", - "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", - "dev": true, - "optional": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "optional": true, - "requires": { - "isexe": "^2.0.0" - } - } + "dot-case": "^3.0.3", + "tslib": "^1.10.0" } }, - "node-releases": { - "version": "1.1.49", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.49.tgz", - "integrity": "sha512-xH8t0LS0disN0mtRCh+eByxFPie+msJUBL/lJDBuap53QGiYPa9joh83K4pCZgWJ+2L4b9h88vCVdXQ60NO2bg==", + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, "requires": { - "semver": "^6.3.0" + "callsites": "^3.0.0" }, "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true } } }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "parse-asn1": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz", + "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==", "dev": true, "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" + "asn1.js": "^4.0.0", + "browserify-aes": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" } }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", - "dev": true - }, - "normalize-url": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", - "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", "dev": true, "requires": { - "object-assign": "^4.0.1", - "prepend-http": "^1.0.0", - "query-string": "^4.1.0", - "sort-keys": "^1.0.0" + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" } }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "parse5": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", + "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", "dev": true, "requires": { - "path-key": "^2.0.0" + "@types/node": "*" } }, - "nth-check": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", - "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true + }, + "pascal-case": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.1.tgz", + "integrity": "sha512-XIeHKqIrsquVTQL2crjq3NfJUxmdLasn3TYOU0VBM+UX2a6ztAWBlJQBePLGY7VHW8+2dRadeIPK5+KImwTxQA==", "dev": true, "requires": { - "boolbase": "~1.0.0" + "no-case": "^3.0.3", + "tslib": "^1.10.0" } }, - "num2fraction": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", - "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", "dev": true }, - "number-is-nan": { + "path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, - "nwsapi": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", - "integrity": "sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==", + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", "dev": true }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", "dev": true }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" + "pify": "^3.0.0" }, "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.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": { - "is-buffer": "^1.1.5" - } + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true } } }, - "object-hash": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-1.3.1.tgz", - "integrity": "sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA==", - "dev": true + "pbkdf2": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", + "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } }, - "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==", + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, - "object-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.2.tgz", - "integrity": "sha512-Epah+btZd5wrrfjkJZq1AOB9O6OxUQto45hzFd7lXGrpHPGE0W1k+426yrZV+k6NJOzLNNW/nVsmZdIWsAqoOQ==", + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", "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==", + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true }, - "object-path": { - "version": "0.11.4", - "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.11.4.tgz", - "integrity": "sha1-NwrnUvvzfePqcKhhwju6iRVpGUk=", + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", "dev": true }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dev": true, "requires": { - "isobject": "^3.0.0" + "pinkie": "^2.0.0" } }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "pirates": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", + "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", "dev": true, "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" + "node-modules-regexp": "^1.0.0" } }, - "object.entries": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.1.tgz", - "integrity": "sha512-ilqR7BgdyZetJutmDPfXCDffGa0/Yzl2ivVNpbx/g4UeWrCdRnFDUBrKJGLhGieRHDATnyZXWBeCb29k9CJysQ==", + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", "dev": true, "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1", - "has": "^1.0.3" + "find-up": "^3.0.0" } }, - "object.fromentries": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.2.tgz", - "integrity": "sha512-r3ZiBH7MQppDJVLx6fhD618GKNG40CZYH9wgwdhKxBDDbQgjeWGGd4AtkZad84d291YxvWe7bJGuE65Anh0dxQ==", + "pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", "dev": true, "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1", - "has": "^1.0.3" + "find-up": "^3.0.0" } }, - "object.getownpropertydescriptors": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", - "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - } + "pn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", + "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", + "dev": true }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "pnp-webpack-plugin": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz", + "integrity": "sha512-7Wjy+9E3WwLOEL30D+m8TSTF7qJJUJLONBnwQp0518siuMxUQUbgZwssaFX+QKlZkjHZcw/IpZCt/H0srrntSg==", "dev": true, "requires": { - "isobject": "^3.0.1" + "ts-pnp": "^1.1.6" } }, - "object.values": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", - "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", + "portfinder": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", + "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", "dev": true, "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1", - "function-bind": "^1.1.1", - "has": "^1.0.3" + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.5" + }, + "dependencies": { + "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" + } + }, + "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 + } } }, - "obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", "dev": true }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "postcss": { + "version": "7.0.32", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz", + "integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==", "dev": true, "requires": { - "ee-first": "1.1.1" + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.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 + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, - "on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "postcss-attribute-case-insensitive": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.2.tgz", + "integrity": "sha512-clkFxk/9pcdb4Vkn0hAHq3YnxBQ2p0CGD1dy24jN+reBck+EWxMbxSUqN4Yj7t0w8csl87K6p0gxBe1utkJsYA==", "dev": true, "requires": { - "wrappy": "1" + "postcss": "^7.0.2", + "postcss-selector-parser": "^6.0.2" } }, - "onetime": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", - "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", + "postcss-browser-comments": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-browser-comments/-/postcss-browser-comments-3.0.0.tgz", + "integrity": "sha512-qfVjLfq7HFd2e0HW4s1dvU8X080OZdG46fFbIBFjW7US7YPDcWfRvdElvwMJr2LI6hMmD+7LnH2HcmXTs+uOig==", "dev": true, "requires": { - "mimic-fn": "^2.1.0" + "postcss": "^7" } }, - "open": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/open/-/open-6.4.0.tgz", - "integrity": "sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==", + "postcss-calc": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.2.tgz", + "integrity": "sha512-rofZFHUg6ZIrvRwPeFktv06GdbDYLcGqh9EwiMutZg+a0oePCCw1zHOEiji6LCpyRcjTREtPASuUqeAvYlEVvQ==", "dev": true, "requires": { - "is-wsl": "^1.1.0" - }, - "dependencies": { - "is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", - "dev": true - } + "postcss": "^7.0.27", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.0.2" } }, - "opn": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", - "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", + "postcss-color-functional-notation": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz", + "integrity": "sha512-ZBARCypjEDofW4P6IdPVTLhDNXPRn8T2s1zHbZidW6rPaaZvcnCS2soYFIQJrMZSxiePJ2XIYTlcb2ztr/eT2g==", "dev": true, "requires": { - "is-wsl": "^1.1.0" - }, - "dependencies": { - "is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", - "dev": true - } + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" } }, - "optimize-css-assets-webpack-plugin": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.3.tgz", - "integrity": "sha512-q9fbvCRS6EYtUKKSwI87qm2IxlyJK5b4dygW1rKUBT6mMDhdG5e5bZT63v6tnJR9F9FB/H5a0HTmtw+laUBxKA==", + "postcss-color-gray": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-color-gray/-/postcss-color-gray-5.0.0.tgz", + "integrity": "sha512-q6BuRnAGKM/ZRpfDascZlIZPjvwsRye7UDNalqVz3s7GDxMtqPY6+Q871liNxsonUw8oC61OG+PSaysYpl1bnw==", "dev": true, "requires": { - "cssnano": "^4.1.10", - "last-call-webpack-plugin": "^3.0.0" + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.5", + "postcss-values-parser": "^2.0.0" } }, - "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "postcss-color-hex-alpha": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-5.0.3.tgz", + "integrity": "sha512-PF4GDel8q3kkreVXKLAGNpHKilXsZ6xuu+mOQMHWHLPNyjiUBOr75sp5ZKJfmv1MCus5/DWUGcK9hm6qHEnXYw==", "dev": true, "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" + "postcss": "^7.0.14", + "postcss-values-parser": "^2.0.1" } }, - "original": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", - "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", + "postcss-color-mod-function": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/postcss-color-mod-function/-/postcss-color-mod-function-3.0.3.tgz", + "integrity": "sha512-YP4VG+xufxaVtzV6ZmhEtc+/aTXH3d0JLpnYfxqTvwZPbJhWqp8bSY3nfNzNRFLgB4XSaBA82OE4VjOOKpCdVQ==", "dev": true, "requires": { - "url-parse": "^1.4.3" + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" } }, - "os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", - "dev": true - }, - "os-locale": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "postcss-color-rebeccapurple": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-4.0.1.tgz", + "integrity": "sha512-aAe3OhkS6qJXBbqzvZth2Au4V3KieR5sRQ4ptb2b2O8wgvB3SJBsdG+jsn2BZbbwekDG8nTfcCNKcSfe/lEy8g==", "dev": true, "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" } }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", - "dev": true - }, - "p-each-series": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.1.0.tgz", - "integrity": "sha512-ZuRs1miPT4HrjFa+9fRfOFXxGJfORgelKV9f9nNOWw2gl6gVsRaVDOQP0+MI0G0wGKns1Yacsu0GjOFbTK0JFQ==", - "dev": true - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true - }, - "p-is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", - "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", - "dev": true - }, - "p-limit": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.2.tgz", - "integrity": "sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ==", + "postcss-colormin": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-4.0.3.tgz", + "integrity": "sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw==", "dev": true, "requires": { - "p-try": "^2.0.0" + "browserslist": "^4.0.0", + "color": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "postcss-convert-values": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz", + "integrity": "sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ==", "dev": true, "requires": { - "p-limit": "^2.2.0" + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, - "p-map": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", - "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", - "dev": true - }, - "p-reduce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-1.0.0.tgz", - "integrity": "sha1-GMKw3ZNqRpClKfgjH1ig/bakffo=", - "dev": true - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true + "postcss-custom-media": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-7.0.8.tgz", + "integrity": "sha512-c9s5iX0Ge15o00HKbuRuTqNndsJUbaXdiNsksnVH8H4gdc+zbLzr/UasOwNG6CTDpLFekVY4672eWdiiWu2GUg==", + "dev": true, + "requires": { + "postcss": "^7.0.14" + } }, - "pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true + "postcss-custom-properties": { + "version": "8.0.11", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-8.0.11.tgz", + "integrity": "sha512-nm+o0eLdYqdnJ5abAJeXp4CEU1c1k+eB2yMCvhgzsds/e0umabFrN6HoTy/8Q4K5ilxERdl/JD1LO5ANoYBeMA==", + "dev": true, + "requires": { + "postcss": "^7.0.17", + "postcss-values-parser": "^2.0.1" + } }, - "parallel-transform": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", - "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "postcss-custom-selectors": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-5.1.2.tgz", + "integrity": "sha512-DSGDhqinCqXqlS4R7KGxL1OSycd1lydugJ1ky4iRXPHdBRiozyMHrdu0H3o7qNOCiZwySZTUI5MV0T8QhCLu+w==", "dev": true, "requires": { - "cyclist": "^1.0.1", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" }, "dependencies": { - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "dev": true + }, + "postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" } + } + } + }, + "postcss-dir-pseudo-class": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-5.0.0.tgz", + "integrity": "sha512-3pm4oq8HYWMZePJY+5ANriPs3P07q+LW6FAdTlkFH2XqDdP4HeeJYMOzn0HYLhRSjBO3fhiqSwwU9xEULSrPgw==", + "dev": true, + "requires": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" + }, + "dependencies": { + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "dev": true }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" } } } }, - "param-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", - "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", + "postcss-discard-comments": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz", + "integrity": "sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg==", "dev": true, "requires": { - "no-case": "^2.2.0" + "postcss": "^7.0.0" } }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "postcss-discard-duplicates": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz", + "integrity": "sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ==", "dev": true, "requires": { - "callsites": "^3.0.0" - }, - "dependencies": { - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - } + "postcss": "^7.0.0" } }, - "parse-asn1": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz", - "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==", + "postcss-discard-empty": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz", + "integrity": "sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w==", "dev": true, "requires": { - "asn1.js": "^4.0.0", - "browserify-aes": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" + "postcss": "^7.0.0" } }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "postcss-discard-overridden": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz", + "integrity": "sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg==", "dev": true, "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" + "postcss": "^7.0.0" } }, - "parse5": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", - "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", + "postcss-double-position-gradients": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-1.0.0.tgz", + "integrity": "sha512-G+nV8EnQq25fOI8CH/B6krEohGWnF5+3A6H/+JEpOncu5dCnkS1QQ6+ct3Jkaepw1NGVqqOZH6lqrm244mCftA==", "dev": true, "requires": { - "@types/node": "*" + "postcss": "^7.0.5", + "postcss-values-parser": "^2.0.0" } }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, - "path-browserify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", - "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", - "dev": true + "postcss-env-function": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-2.0.2.tgz", + "integrity": "sha512-rwac4BuZlITeUbiBq60h/xbLzXY43qOsIErngWa4l7Mt+RaSkT7QBjXVGTcBHupykkblHMDrBFh30zchYPaOUw==", + "dev": true, + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + } }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true + "postcss-flexbugs-fixes": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-4.1.0.tgz", + "integrity": "sha512-jr1LHxQvStNNAHlgco6PzY308zvLklh7SJVYuWUwyUQncofaAlD2l+P/gxKHOdqWKe7xJSkVLFF/2Tp+JqMSZA==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } }, - "path-exists": { + "postcss-focus-visible": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", - "dev": true + "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-4.0.0.tgz", + "integrity": "sha512-Z5CkWBw0+idJHSV6+Bgf2peDOFf/x4o+vX/pwcNYrWpXFrSfTkQ3JQ1ojrq9yS+upnAlNRHeg8uEwFTgorjI8g==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + } }, - "path-type": { + "postcss-focus-within": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-3.0.0.tgz", + "integrity": "sha512-W0APui8jQeBKbCGZudW37EeMCjDeVxKgiYfIIEo8Bdh5SpB9sxds/Iq8SEuzS0Q4YFOlG7EPFulbbxujpkrV2w==", "dev": true, "requires": { - "pify": "^3.0.0" + "postcss": "^7.0.2" } }, - "pbkdf2": { - "version": "3.0.17", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", - "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", + "postcss-font-variant": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-4.0.0.tgz", + "integrity": "sha512-M8BFYKOvCrI2aITzDad7kWuXXTm0YhGdP9Q8HanmN4EF1Hmcgs1KK5rSHylt/lUJe8yLxiSwWAHdScoEiIxztg==", "dev": true, "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" + "postcss": "^7.0.2" } }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true + "postcss-gap-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-2.0.0.tgz", + "integrity": "sha512-QZSqDaMgXCHuHTEzMsS2KfVDOq7ZFiknSpkrPJY6jmxbugUPTuSzs/vuE5I3zv0WAS+3vhrlqhijiprnuQfzmg==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + } }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true + "postcss-image-set-function": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-3.0.1.tgz", + "integrity": "sha512-oPTcFFip5LZy8Y/whto91L9xdRHCWEMs3e1MdJxhgt4jy2WYXfhkng59fH5qLXSCPN8k4n94p1Czrfe5IOkKUw==", + "dev": true, + "requires": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + } }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "postcss-initial": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-3.0.2.tgz", + "integrity": "sha512-ugA2wKonC0xeNHgirR4D3VWHs2JcU08WAi1KFLVcnb7IN89phID6Qtg2RIctWbnvp1TM2BOmDtX8GGLCKdR8YA==", "dev": true, "requires": { - "pinkie": "^2.0.0" + "lodash.template": "^4.5.0", + "postcss": "^7.0.2" } }, - "pirates": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", - "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", + "postcss-lab-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-2.0.1.tgz", + "integrity": "sha512-whLy1IeZKY+3fYdqQFuDBf8Auw+qFuVnChWjmxm/UhHWqNHZx+B99EwxTvGYmUBqe3Fjxs4L1BoZTJmPu6usVg==", "dev": true, "requires": { - "node-modules-regexp": "^1.0.0" + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" } }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "postcss-load-config": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.0.tgz", + "integrity": "sha512-4pV3JJVPLd5+RueiVVB+gFOAa7GWc25XQcMp86Zexzke69mKf6Nx9LRcQywdz7yZI9n1udOxmLuAwTBypypF8Q==", "dev": true, "requires": { - "find-up": "^4.0.0" + "cosmiconfig": "^5.0.0", + "import-cwd": "^2.0.0" } }, - "pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz", - "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=", + "postcss-loader": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz", + "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==", "dev": true, "requires": { - "find-up": "^2.1.0" + "loader-utils": "^1.1.0", + "postcss": "^7.0.0", + "postcss-load-config": "^2.0.0", + "schema-utils": "^1.0.0" }, "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - } - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", "dev": true, "requires": { - "p-limit": "^1.1.0" + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true } } }, - "pn": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/pn/-/pn-1.1.0.tgz", - "integrity": "sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA==", - "dev": true + "postcss-logical": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-3.0.0.tgz", + "integrity": "sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA==", + "dev": true, + "requires": { + "postcss": "^7.0.2" + } }, - "pnp-webpack-plugin": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/pnp-webpack-plugin/-/pnp-webpack-plugin-1.5.0.tgz", - "integrity": "sha512-jd9olUr9D7do+RN8Wspzhpxhgp1n6Vd0NtQ4SFkmIACZoEL1nkyAdW9Ygrinjec0vgDcWjscFQQ1gDW8rsfKTg==", + "postcss-media-minmax": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-4.0.0.tgz", + "integrity": "sha512-fo9moya6qyxsjbFAYl97qKO9gyre3qvbMnkOZeZwlsW6XYFsvs2DMGDlchVLfAd8LHPZDxivu/+qW2SMQeTHBw==", "dev": true, "requires": { - "ts-pnp": "^1.1.2" + "postcss": "^7.0.2" } }, - "portfinder": { - "version": "1.0.25", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.25.tgz", - "integrity": "sha512-6ElJnHBbxVA1XSLgBp7G1FiCkQdlqGzuF7DswL5tcea+E8UpuvPU7beVAjjRwCioTS9ZluNbu+ZyRvgTsmqEBg==", + "postcss-merge-longhand": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz", + "integrity": "sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw==", "dev": true, "requires": { - "async": "^2.6.2", - "debug": "^3.1.1", - "mkdirp": "^0.5.1" + "css-color-names": "0.0.4", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "stylehacks": "^4.0.0" }, "dependencies": { - "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" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", "dev": true } } }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "postcss": { - "version": "7.0.26", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.26.tgz", - "integrity": "sha512-IY4oRjpXWYshuTDFxMVkJDtWIk2LhsTlu8bZnbEJA4+bYT16Lvpo8Qv6EvDumhYRgzjZl489pmsY3qVgJQ08nA==", + "postcss-merge-rules": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz", + "integrity": "sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ==", "dev": true, "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "cssnano-util-same-parent": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0", + "vendors": "^1.0.0" }, "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "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 - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" } } } }, - "postcss-attribute-case-insensitive": { + "postcss-minify-font-values": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.2.tgz", - "integrity": "sha512-clkFxk/9pcdb4Vkn0hAHq3YnxBQ2p0CGD1dy24jN+reBck+EWxMbxSUqN4Yj7t0w8csl87K6p0gxBe1utkJsYA==", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz", + "integrity": "sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg==", "dev": true, "requires": { - "postcss": "^7.0.2", - "postcss-selector-parser": "^6.0.2" + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, - "postcss-browser-comments": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-browser-comments/-/postcss-browser-comments-2.0.0.tgz", - "integrity": "sha512-xGG0UvoxwBc4Yx4JX3gc0RuDl1kc4bVihCzzk6UC72YPfq5fu3c717Nu8Un3nvnq1BJ31gBnFXIG/OaUTnpHgA==", + "postcss-minify-gradients": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz", + "integrity": "sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q==", "dev": true, "requires": { - "postcss": "^7.0.2" + "cssnano-util-get-arguments": "^4.0.0", + "is-color-stop": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, - "postcss-calc": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.1.tgz", - "integrity": "sha512-oXqx0m6tb4N3JGdmeMSc/i91KppbYsFZKdH0xMOqK8V1rJlzrKlTdokz8ozUXLVejydRN6u2IddxpcijRj2FqQ==", + "postcss-minify-params": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz", + "integrity": "sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg==", "dev": true, "requires": { - "css-unit-converter": "^1.1.1", - "postcss": "^7.0.5", - "postcss-selector-parser": "^5.0.0-rc.4", - "postcss-value-parser": "^3.3.1" + "alphanum-sort": "^1.0.0", + "browserslist": "^4.0.0", + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "uniqs": "^2.0.0" }, "dependencies": { - "cssesc": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", - "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", "dev": true - }, + } + } + }, + "postcss-minify-selectors": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz", + "integrity": "sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "dependencies": { "postcss-selector-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", - "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", "dev": true, "requires": { - "cssesc": "^2.0.0", + "dot-prop": "^5.2.0", "indexes-of": "^1.0.1", "uniq": "^1.0.1" } } } }, - "postcss-color-functional-notation": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz", - "integrity": "sha512-ZBARCypjEDofW4P6IdPVTLhDNXPRn8T2s1zHbZidW6rPaaZvcnCS2soYFIQJrMZSxiePJ2XIYTlcb2ztr/eT2g==", + "postcss-modules-extract-imports": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", + "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", "dev": true, "requires": { - "postcss": "^7.0.2", - "postcss-values-parser": "^2.0.0" + "postcss": "^7.0.5" } }, - "postcss-color-gray": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-color-gray/-/postcss-color-gray-5.0.0.tgz", - "integrity": "sha512-q6BuRnAGKM/ZRpfDascZlIZPjvwsRye7UDNalqVz3s7GDxMtqPY6+Q871liNxsonUw8oC61OG+PSaysYpl1bnw==", + "postcss-modules-local-by-default": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz", + "integrity": "sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw==", "dev": true, "requires": { - "@csstools/convert-colors": "^1.4.0", - "postcss": "^7.0.5", - "postcss-values-parser": "^2.0.0" + "icss-utils": "^4.1.1", + "postcss": "^7.0.32", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" } }, - "postcss-color-hex-alpha": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-5.0.3.tgz", - "integrity": "sha512-PF4GDel8q3kkreVXKLAGNpHKilXsZ6xuu+mOQMHWHLPNyjiUBOr75sp5ZKJfmv1MCus5/DWUGcK9hm6qHEnXYw==", + "postcss-modules-scope": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz", + "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==", "dev": true, "requires": { - "postcss": "^7.0.14", - "postcss-values-parser": "^2.0.1" + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0" } }, - "postcss-color-mod-function": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/postcss-color-mod-function/-/postcss-color-mod-function-3.0.3.tgz", - "integrity": "sha512-YP4VG+xufxaVtzV6ZmhEtc+/aTXH3d0JLpnYfxqTvwZPbJhWqp8bSY3nfNzNRFLgB4XSaBA82OE4VjOOKpCdVQ==", + "postcss-modules-values": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", + "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", "dev": true, "requires": { - "@csstools/convert-colors": "^1.4.0", - "postcss": "^7.0.2", - "postcss-values-parser": "^2.0.0" + "icss-utils": "^4.0.0", + "postcss": "^7.0.6" } }, - "postcss-color-rebeccapurple": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-4.0.1.tgz", - "integrity": "sha512-aAe3OhkS6qJXBbqzvZth2Au4V3KieR5sRQ4ptb2b2O8wgvB3SJBsdG+jsn2BZbbwekDG8nTfcCNKcSfe/lEy8g==", + "postcss-nesting": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-7.0.1.tgz", + "integrity": "sha512-FrorPb0H3nuVq0Sff7W2rnc3SmIcruVC6YwpcS+k687VxyxO33iE1amna7wHuRVzM8vfiYofXSBHNAZ3QhLvYg==", "dev": true, "requires": { - "postcss": "^7.0.2", - "postcss-values-parser": "^2.0.0" + "postcss": "^7.0.2" } }, - "postcss-colormin": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-4.0.3.tgz", - "integrity": "sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw==", + "postcss-normalize": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize/-/postcss-normalize-8.0.1.tgz", + "integrity": "sha512-rt9JMS/m9FHIRroDDBGSMsyW1c0fkvOJPy62ggxSHUldJO7B195TqFMqIf+lY5ezpDcYOV4j86aUp3/XbxzCCQ==", "dev": true, "requires": { - "browserslist": "^4.0.0", - "color": "^3.0.0", - "has": "^1.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" + "@csstools/normalize.css": "^10.1.0", + "browserslist": "^4.6.2", + "postcss": "^7.0.17", + "postcss-browser-comments": "^3.0.0", + "sanitize.css": "^10.0.0" } }, - "postcss-convert-values": { + "postcss-normalize-charset": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz", - "integrity": "sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ==", - "dev": true, - "requires": { - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - } - }, - "postcss-custom-media": { - "version": "7.0.8", - "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-7.0.8.tgz", - "integrity": "sha512-c9s5iX0Ge15o00HKbuRuTqNndsJUbaXdiNsksnVH8H4gdc+zbLzr/UasOwNG6CTDpLFekVY4672eWdiiWu2GUg==", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz", + "integrity": "sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g==", "dev": true, "requires": { - "postcss": "^7.0.14" + "postcss": "^7.0.0" } }, - "postcss-custom-properties": { - "version": "8.0.11", - "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-8.0.11.tgz", - "integrity": "sha512-nm+o0eLdYqdnJ5abAJeXp4CEU1c1k+eB2yMCvhgzsds/e0umabFrN6HoTy/8Q4K5ilxERdl/JD1LO5ANoYBeMA==", + "postcss-normalize-display-values": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz", + "integrity": "sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ==", "dev": true, "requires": { - "postcss": "^7.0.17", - "postcss-values-parser": "^2.0.1" + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, - "postcss-custom-selectors": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-5.1.2.tgz", - "integrity": "sha512-DSGDhqinCqXqlS4R7KGxL1OSycd1lydugJ1ky4iRXPHdBRiozyMHrdu0H3o7qNOCiZwySZTUI5MV0T8QhCLu+w==", + "postcss-normalize-positions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz", + "integrity": "sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA==", "dev": true, "requires": { - "postcss": "^7.0.2", - "postcss-selector-parser": "^5.0.0-rc.3" + "cssnano-util-get-arguments": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" }, "dependencies": { - "cssesc": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", - "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", "dev": true - }, - "postcss-selector-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", - "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", - "dev": true, - "requires": { - "cssesc": "^2.0.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } } } }, - "postcss-dir-pseudo-class": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-5.0.0.tgz", - "integrity": "sha512-3pm4oq8HYWMZePJY+5ANriPs3P07q+LW6FAdTlkFH2XqDdP4HeeJYMOzn0HYLhRSjBO3fhiqSwwU9xEULSrPgw==", + "postcss-normalize-repeat-style": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz", + "integrity": "sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q==", "dev": true, "requires": { - "postcss": "^7.0.2", - "postcss-selector-parser": "^5.0.0-rc.3" + "cssnano-util-get-arguments": "^4.0.0", + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" }, "dependencies": { - "cssesc": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", - "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", "dev": true - }, - "postcss-selector-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", - "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", - "dev": true, - "requires": { - "cssesc": "^2.0.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } } } }, - "postcss-discard-comments": { + "postcss-normalize-string": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz", - "integrity": "sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg==", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz", + "integrity": "sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA==", "dev": true, "requires": { - "postcss": "^7.0.0" + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, - "postcss-discard-duplicates": { + "postcss-normalize-timing-functions": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz", - "integrity": "sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ==", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz", + "integrity": "sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A==", "dev": true, "requires": { - "postcss": "^7.0.0" + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, - "postcss-discard-empty": { + "postcss-normalize-unicode": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz", - "integrity": "sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w==", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz", + "integrity": "sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg==", "dev": true, "requires": { - "postcss": "^7.0.0" + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, - "postcss-discard-overridden": { + "postcss-normalize-url": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz", - "integrity": "sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg==", - "dev": true, - "requires": { - "postcss": "^7.0.0" - } - }, - "postcss-double-position-gradients": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-1.0.0.tgz", - "integrity": "sha512-G+nV8EnQq25fOI8CH/B6krEohGWnF5+3A6H/+JEpOncu5dCnkS1QQ6+ct3Jkaepw1NGVqqOZH6lqrm244mCftA==", - "dev": true, - "requires": { - "postcss": "^7.0.5", - "postcss-values-parser": "^2.0.0" - } - }, - "postcss-env-function": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-2.0.2.tgz", - "integrity": "sha512-rwac4BuZlITeUbiBq60h/xbLzXY43qOsIErngWa4l7Mt+RaSkT7QBjXVGTcBHupykkblHMDrBFh30zchYPaOUw==", - "dev": true, - "requires": { - "postcss": "^7.0.2", - "postcss-values-parser": "^2.0.0" - } - }, - "postcss-flexbugs-fixes": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-4.1.0.tgz", - "integrity": "sha512-jr1LHxQvStNNAHlgco6PzY308zvLklh7SJVYuWUwyUQncofaAlD2l+P/gxKHOdqWKe7xJSkVLFF/2Tp+JqMSZA==", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz", + "integrity": "sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA==", "dev": true, "requires": { - "postcss": "^7.0.0" + "is-absolute-url": "^2.0.0", + "normalize-url": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "normalize-url": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", + "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==", + "dev": true + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, - "postcss-focus-visible": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-4.0.0.tgz", - "integrity": "sha512-Z5CkWBw0+idJHSV6+Bgf2peDOFf/x4o+vX/pwcNYrWpXFrSfTkQ3JQ1ojrq9yS+upnAlNRHeg8uEwFTgorjI8g==", + "postcss-normalize-whitespace": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz", + "integrity": "sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA==", "dev": true, "requires": { - "postcss": "^7.0.2" + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, - "postcss-focus-within": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-3.0.0.tgz", - "integrity": "sha512-W0APui8jQeBKbCGZudW37EeMCjDeVxKgiYfIIEo8Bdh5SpB9sxds/Iq8SEuzS0Q4YFOlG7EPFulbbxujpkrV2w==", + "postcss-ordered-values": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz", + "integrity": "sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw==", "dev": true, "requires": { - "postcss": "^7.0.2" + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, - "postcss-font-variant": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-4.0.0.tgz", - "integrity": "sha512-M8BFYKOvCrI2aITzDad7kWuXXTm0YhGdP9Q8HanmN4EF1Hmcgs1KK5rSHylt/lUJe8yLxiSwWAHdScoEiIxztg==", + "postcss-overflow-shorthand": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-2.0.0.tgz", + "integrity": "sha512-aK0fHc9CBNx8jbzMYhshZcEv8LtYnBIRYQD5i7w/K/wS9c2+0NSR6B3OVMu5y0hBHYLcMGjfU+dmWYNKH0I85g==", "dev": true, "requires": { "postcss": "^7.0.2" } }, - "postcss-gap-properties": { + "postcss-page-break": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-2.0.0.tgz", - "integrity": "sha512-QZSqDaMgXCHuHTEzMsS2KfVDOq7ZFiknSpkrPJY6jmxbugUPTuSzs/vuE5I3zv0WAS+3vhrlqhijiprnuQfzmg==", + "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-2.0.0.tgz", + "integrity": "sha512-tkpTSrLpfLfD9HvgOlJuigLuk39wVTbbd8RKcy8/ugV2bNBUW3xU+AIqyxhDrQr1VUj1RmyJrBn1YWrqUm9zAQ==", "dev": true, "requires": { "postcss": "^7.0.2" } }, - "postcss-image-set-function": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-3.0.1.tgz", - "integrity": "sha512-oPTcFFip5LZy8Y/whto91L9xdRHCWEMs3e1MdJxhgt4jy2WYXfhkng59fH5qLXSCPN8k4n94p1Czrfe5IOkKUw==", + "postcss-place": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-4.0.1.tgz", + "integrity": "sha512-Zb6byCSLkgRKLODj/5mQugyuj9bvAAw9LqJJjgwz5cYryGeXfFZfSXoP1UfveccFmeq0b/2xxwcTEVScnqGxBg==", "dev": true, "requires": { "postcss": "^7.0.2", "postcss-values-parser": "^2.0.0" } }, - "postcss-initial": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-3.0.2.tgz", - "integrity": "sha512-ugA2wKonC0xeNHgirR4D3VWHs2JcU08WAi1KFLVcnb7IN89phID6Qtg2RIctWbnvp1TM2BOmDtX8GGLCKdR8YA==", + "postcss-preset-env": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-6.7.0.tgz", + "integrity": "sha512-eU4/K5xzSFwUFJ8hTdTQzo2RBLbDVt83QZrAvI07TULOkmyQlnYlpwep+2yIK+K+0KlZO4BvFcleOCCcUtwchg==", "dev": true, "requires": { - "lodash.template": "^4.5.0", - "postcss": "^7.0.2" + "autoprefixer": "^9.6.1", + "browserslist": "^4.6.4", + "caniuse-lite": "^1.0.30000981", + "css-blank-pseudo": "^0.1.4", + "css-has-pseudo": "^0.10.0", + "css-prefers-color-scheme": "^3.1.1", + "cssdb": "^4.4.0", + "postcss": "^7.0.17", + "postcss-attribute-case-insensitive": "^4.0.1", + "postcss-color-functional-notation": "^2.0.1", + "postcss-color-gray": "^5.0.0", + "postcss-color-hex-alpha": "^5.0.3", + "postcss-color-mod-function": "^3.0.3", + "postcss-color-rebeccapurple": "^4.0.1", + "postcss-custom-media": "^7.0.8", + "postcss-custom-properties": "^8.0.11", + "postcss-custom-selectors": "^5.1.2", + "postcss-dir-pseudo-class": "^5.0.0", + "postcss-double-position-gradients": "^1.0.0", + "postcss-env-function": "^2.0.2", + "postcss-focus-visible": "^4.0.0", + "postcss-focus-within": "^3.0.0", + "postcss-font-variant": "^4.0.0", + "postcss-gap-properties": "^2.0.0", + "postcss-image-set-function": "^3.0.1", + "postcss-initial": "^3.0.0", + "postcss-lab-function": "^2.0.1", + "postcss-logical": "^3.0.0", + "postcss-media-minmax": "^4.0.0", + "postcss-nesting": "^7.0.0", + "postcss-overflow-shorthand": "^2.0.0", + "postcss-page-break": "^2.0.0", + "postcss-place": "^4.0.1", + "postcss-pseudo-class-any-link": "^6.0.0", + "postcss-replace-overflow-wrap": "^3.0.0", + "postcss-selector-matches": "^4.0.0", + "postcss-selector-not": "^4.0.0" } }, - "postcss-lab-function": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-2.0.1.tgz", - "integrity": "sha512-whLy1IeZKY+3fYdqQFuDBf8Auw+qFuVnChWjmxm/UhHWqNHZx+B99EwxTvGYmUBqe3Fjxs4L1BoZTJmPu6usVg==", - "dev": true, - "requires": { - "@csstools/convert-colors": "^1.4.0", - "postcss": "^7.0.2", - "postcss-values-parser": "^2.0.0" - } - }, - "postcss-load-config": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.0.tgz", - "integrity": "sha512-4pV3JJVPLd5+RueiVVB+gFOAa7GWc25XQcMp86Zexzke69mKf6Nx9LRcQywdz7yZI9n1udOxmLuAwTBypypF8Q==", - "dev": true, - "requires": { - "cosmiconfig": "^5.0.0", - "import-cwd": "^2.0.0" - } - }, - "postcss-loader": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz", - "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==", - "dev": true, - "requires": { - "loader-utils": "^1.1.0", - "postcss": "^7.0.0", - "postcss-load-config": "^2.0.0", - "schema-utils": "^1.0.0" - } - }, - "postcss-logical": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-3.0.0.tgz", - "integrity": "sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA==", - "dev": true, - "requires": { - "postcss": "^7.0.2" - } - }, - "postcss-media-minmax": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-4.0.0.tgz", - "integrity": "sha512-fo9moya6qyxsjbFAYl97qKO9gyre3qvbMnkOZeZwlsW6XYFsvs2DMGDlchVLfAd8LHPZDxivu/+qW2SMQeTHBw==", - "dev": true, - "requires": { - "postcss": "^7.0.2" - } - }, - "postcss-merge-longhand": { - "version": "4.0.11", - "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz", - "integrity": "sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw==", - "dev": true, - "requires": { - "css-color-names": "0.0.4", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0", - "stylehacks": "^4.0.0" - } - }, - "postcss-merge-rules": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz", - "integrity": "sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ==", + "postcss-pseudo-class-any-link": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-6.0.0.tgz", + "integrity": "sha512-lgXW9sYJdLqtmw23otOzrtbDXofUdfYzNm4PIpNE322/swES3VU9XlXHeJS46zT2onFO7V1QFdD4Q9LiZj8mew==", "dev": true, "requires": { - "browserslist": "^4.0.0", - "caniuse-api": "^3.0.0", - "cssnano-util-same-parent": "^4.0.0", - "postcss": "^7.0.0", - "postcss-selector-parser": "^3.0.0", - "vendors": "^1.0.0" + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" }, "dependencies": { + "cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "dev": true + }, "postcss-selector-parser": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", - "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", "dev": true, "requires": { - "dot-prop": "^5.2.0", + "cssesc": "^2.0.0", "indexes-of": "^1.0.1", "uniq": "^1.0.1" } } } }, - "postcss-minify-font-values": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz", - "integrity": "sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg==", - "dev": true, - "requires": { - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - } - }, - "postcss-minify-gradients": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz", - "integrity": "sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q==", - "dev": true, - "requires": { - "cssnano-util-get-arguments": "^4.0.0", - "is-color-stop": "^1.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - } - }, - "postcss-minify-params": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz", - "integrity": "sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg==", + "postcss-reduce-initial": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz", + "integrity": "sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA==", "dev": true, "requires": { - "alphanum-sort": "^1.0.0", "browserslist": "^4.0.0", - "cssnano-util-get-arguments": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0", - "uniqs": "^2.0.0" + "caniuse-api": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0" } }, - "postcss-minify-selectors": { + "postcss-reduce-transforms": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz", - "integrity": "sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g==", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz", + "integrity": "sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg==", "dev": true, "requires": { - "alphanum-sort": "^1.0.0", + "cssnano-util-get-match": "^4.0.0", "has": "^1.0.0", "postcss": "^7.0.0", - "postcss-selector-parser": "^3.0.0" + "postcss-value-parser": "^3.0.0" }, "dependencies": { - "postcss-selector-parser": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", - "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", - "dev": true, - "requires": { - "dot-prop": "^5.2.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true } } }, - "postcss-modules-extract-imports": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", - "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", - "dev": true, - "requires": { - "postcss": "^7.0.5" - } - }, - "postcss-modules-local-by-default": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-2.0.6.tgz", - "integrity": "sha512-oLUV5YNkeIBa0yQl7EYnxMgy4N6noxmiwZStaEJUSe2xPMcdNc8WmBQuQCx18H5psYbVxz8zoHk0RAAYZXP9gA==", - "dev": true, - "requires": { - "postcss": "^7.0.6", - "postcss-selector-parser": "^6.0.0", - "postcss-value-parser": "^3.3.1" - } - }, - "postcss-modules-scope": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.1.1.tgz", - "integrity": "sha512-OXRUPecnHCg8b9xWvldG/jUpRIGPNRka0r4D4j0ESUU2/5IOnpsjfPPmDprM3Ih8CgZ8FXjWqaniK5v4rWt3oQ==", + "postcss-replace-overflow-wrap": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-3.0.0.tgz", + "integrity": "sha512-2T5hcEHArDT6X9+9dVSPQdo7QHzG4XKclFT8rU5TzJPDN7RIRTbO9c4drUISOVemLj03aezStHCR2AIcr8XLpw==", "dev": true, "requires": { - "postcss": "^7.0.6", - "postcss-selector-parser": "^6.0.0" + "postcss": "^7.0.2" } }, - "postcss-modules-values": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-2.0.0.tgz", - "integrity": "sha512-Ki7JZa7ff1N3EIMlPnGTZfUMe69FFwiQPnVSXC9mnn3jozCRBYIxiZd44yJOV2AmabOo4qFf8s0dC/+lweG7+w==", + "postcss-safe-parser": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-4.0.1.tgz", + "integrity": "sha512-xZsFA3uX8MO3yAda03QrG3/Eg1LN3EPfjjf07vke/46HERLZyHrTsQ9E1r1w1W//fWEhtYNndo2hQplN2cVpCQ==", "dev": true, "requires": { - "icss-replace-symbols": "^1.1.0", - "postcss": "^7.0.6" + "postcss": "^7.0.0" } }, - "postcss-nesting": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-7.0.1.tgz", - "integrity": "sha512-FrorPb0H3nuVq0Sff7W2rnc3SmIcruVC6YwpcS+k687VxyxO33iE1amna7wHuRVzM8vfiYofXSBHNAZ3QhLvYg==", + "postcss-selector-matches": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz", + "integrity": "sha512-LgsHwQR/EsRYSqlwdGzeaPKVT0Ml7LAT6E75T8W8xLJY62CE4S/l03BWIt3jT8Taq22kXP08s2SfTSzaraoPww==", "dev": true, "requires": { + "balanced-match": "^1.0.0", "postcss": "^7.0.2" } }, - "postcss-normalize": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize/-/postcss-normalize-7.0.1.tgz", - "integrity": "sha512-NOp1fwrG+6kVXWo7P9SizCHX6QvioxFD/hZcI2MLxPmVnFJFC0j0DDpIuNw2tUDeCFMni59gCVgeJ1/hYhj2OQ==", + "postcss-selector-not": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-4.0.0.tgz", + "integrity": "sha512-W+bkBZRhqJaYN8XAnbbZPLWMvZD1wKTu0UxtFKdhtGjWYmxhkUneoeOhRJKdAE5V7ZTlnbHfCR+6bNwK9e1dTQ==", "dev": true, "requires": { - "@csstools/normalize.css": "^9.0.1", - "browserslist": "^4.1.1", - "postcss": "^7.0.2", - "postcss-browser-comments": "^2.0.0" + "balanced-match": "^1.0.0", + "postcss": "^7.0.2" } }, - "postcss-normalize-charset": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz", - "integrity": "sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g==", + "postcss-selector-parser": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz", + "integrity": "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==", "dev": true, "requires": { - "postcss": "^7.0.0" + "cssesc": "^3.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" } }, - "postcss-normalize-display-values": { + "postcss-svgo": { "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz", - "integrity": "sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ==", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.2.tgz", + "integrity": "sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw==", "dev": true, "requires": { - "cssnano-util-get-match": "^4.0.0", + "is-svg": "^3.0.0", "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" + "postcss-value-parser": "^3.0.0", + "svgo": "^1.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, - "postcss-normalize-positions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz", - "integrity": "sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA==", + "postcss-unique-selectors": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz", + "integrity": "sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg==", "dev": true, "requires": { - "cssnano-util-get-arguments": "^4.0.0", - "has": "^1.0.0", + "alphanum-sort": "^1.0.0", "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" + "uniqs": "^2.0.0" } }, - "postcss-normalize-repeat-style": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz", - "integrity": "sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q==", + "postcss-value-parser": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", + "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==", + "dev": true + }, + "postcss-values-parser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz", + "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==", "dev": true, "requires": { - "cssnano-util-get-arguments": "^4.0.0", - "cssnano-util-get-match": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - } - }, - "postcss-normalize-string": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz", - "integrity": "sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA==", - "dev": true, - "requires": { - "has": "^1.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" } }, - "postcss-normalize-timing-functions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz", - "integrity": "sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A==", - "dev": true, - "requires": { - "cssnano-util-get-match": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - } + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true }, - "postcss-normalize-unicode": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz", - "integrity": "sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg==", + "prepend-http": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", + "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "dev": true + }, + "pretty-bytes": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.3.0.tgz", + "integrity": "sha512-hjGrh+P926p4R4WbaB6OckyRtO0F0/lQBiT+0gnxjV+5kjPBrfVBFCsCLbMqVQeydvIoouYTCmmEURiH3R1Bdg==", + "dev": true + }, + "pretty-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz", + "integrity": "sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM=", "dev": true, "requires": { - "browserslist": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" + "renderkid": "^2.0.1", + "utila": "~0.4" } }, - "postcss-normalize-url": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz", - "integrity": "sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA==", + "pretty-format": { + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", + "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", "dev": true, "requires": { - "is-absolute-url": "^2.0.0", - "normalize-url": "^3.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" + "@jest/types": "^24.9.0", + "ansi-regex": "^4.0.0", + "ansi-styles": "^3.2.0", + "react-is": "^16.8.4" }, "dependencies": { - "normalize-url": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", - "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==", + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true } } }, - "postcss-normalize-whitespace": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz", - "integrity": "sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA==", - "dev": true, - "requires": { - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - } + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true }, - "postcss-ordered-values": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz", - "integrity": "sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw==", + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "promise": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-8.1.0.tgz", + "integrity": "sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q==", "dev": true, "requires": { - "cssnano-util-get-arguments": "^4.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" + "asap": "~2.0.6" } }, - "postcss-overflow-shorthand": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-2.0.0.tgz", - "integrity": "sha512-aK0fHc9CBNx8jbzMYhshZcEv8LtYnBIRYQD5i7w/K/wS9c2+0NSR6B3OVMu5y0hBHYLcMGjfU+dmWYNKH0I85g==", + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, + "prompts": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.3.2.tgz", + "integrity": "sha512-Q06uKs2CkNYVID0VqwfAl9mipo99zkBv/n2JtWY89Yxa3ZabWSrs0e2KTudKVa3peLUvYXMefDqIleLPVUBZMA==", "dev": true, "requires": { - "postcss": "^7.0.2" + "kleur": "^3.0.3", + "sisteransi": "^1.0.4" } }, - "postcss-page-break": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-2.0.0.tgz", - "integrity": "sha512-tkpTSrLpfLfD9HvgOlJuigLuk39wVTbbd8RKcy8/ugV2bNBUW3xU+AIqyxhDrQr1VUj1RmyJrBn1YWrqUm9zAQ==", - "dev": true, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", "requires": { - "postcss": "^7.0.2" + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" } }, - "postcss-place": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-4.0.1.tgz", - "integrity": "sha512-Zb6byCSLkgRKLODj/5mQugyuj9bvAAw9LqJJjgwz5cYryGeXfFZfSXoP1UfveccFmeq0b/2xxwcTEVScnqGxBg==", + "prop-types-exact": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/prop-types-exact/-/prop-types-exact-1.2.0.tgz", + "integrity": "sha512-K+Tk3Kd9V0odiXFP9fwDHUYRyvK3Nun3GVyPapSIs5OBkITAm15W0CPFD/YKTkMUAbc0b9CUwRQp2ybiBIq+eA==", "dev": true, "requires": { - "postcss": "^7.0.2", - "postcss-values-parser": "^2.0.0" + "has": "^1.0.3", + "object.assign": "^4.1.0", + "reflect.ownkeys": "^0.2.0" } }, - "postcss-preset-env": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-6.7.0.tgz", - "integrity": "sha512-eU4/K5xzSFwUFJ8hTdTQzo2RBLbDVt83QZrAvI07TULOkmyQlnYlpwep+2yIK+K+0KlZO4BvFcleOCCcUtwchg==", + "proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", "dev": true, "requires": { - "autoprefixer": "^9.6.1", - "browserslist": "^4.6.4", - "caniuse-lite": "^1.0.30000981", - "css-blank-pseudo": "^0.1.4", - "css-has-pseudo": "^0.10.0", - "css-prefers-color-scheme": "^3.1.1", - "cssdb": "^4.4.0", - "postcss": "^7.0.17", - "postcss-attribute-case-insensitive": "^4.0.1", - "postcss-color-functional-notation": "^2.0.1", - "postcss-color-gray": "^5.0.0", - "postcss-color-hex-alpha": "^5.0.3", - "postcss-color-mod-function": "^3.0.3", - "postcss-color-rebeccapurple": "^4.0.1", - "postcss-custom-media": "^7.0.8", - "postcss-custom-properties": "^8.0.11", - "postcss-custom-selectors": "^5.1.2", - "postcss-dir-pseudo-class": "^5.0.0", - "postcss-double-position-gradients": "^1.0.0", - "postcss-env-function": "^2.0.2", - "postcss-focus-visible": "^4.0.0", - "postcss-focus-within": "^3.0.0", - "postcss-font-variant": "^4.0.0", - "postcss-gap-properties": "^2.0.0", - "postcss-image-set-function": "^3.0.1", - "postcss-initial": "^3.0.0", - "postcss-lab-function": "^2.0.1", - "postcss-logical": "^3.0.0", - "postcss-media-minmax": "^4.0.0", - "postcss-nesting": "^7.0.0", - "postcss-overflow-shorthand": "^2.0.0", - "postcss-page-break": "^2.0.0", - "postcss-place": "^4.0.1", - "postcss-pseudo-class-any-link": "^6.0.0", - "postcss-replace-overflow-wrap": "^3.0.0", - "postcss-selector-matches": "^4.0.0", - "postcss-selector-not": "^4.0.0" + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" } }, - "postcss-pseudo-class-any-link": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-6.0.0.tgz", - "integrity": "sha512-lgXW9sYJdLqtmw23otOzrtbDXofUdfYzNm4PIpNE322/swES3VU9XlXHeJS46zT2onFO7V1QFdD4Q9LiZj8mew==", + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", "dev": true, "requires": { - "postcss": "^7.0.2", - "postcss-selector-parser": "^5.0.0-rc.3" + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" }, "dependencies": { - "cssesc": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", - "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", "dev": true - }, - "postcss-selector-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", - "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", - "dev": true, - "requires": { - "cssesc": "^2.0.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } } } }, - "postcss-reduce-initial": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz", - "integrity": "sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA==", + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", "dev": true, "requires": { - "browserslist": "^4.0.0", - "caniuse-api": "^3.0.0", - "has": "^1.0.0", - "postcss": "^7.0.0" + "end-of-stream": "^1.1.0", + "once": "^1.3.1" } }, - "postcss-reduce-transforms": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz", - "integrity": "sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg==", + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", "dev": true, "requires": { - "cssnano-util-get-match": "^4.0.0", - "has": "^1.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0" - } - }, - "postcss-replace-overflow-wrap": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-3.0.0.tgz", - "integrity": "sha512-2T5hcEHArDT6X9+9dVSPQdo7QHzG4XKclFT8rU5TzJPDN7RIRTbO9c4drUISOVemLj03aezStHCR2AIcr8XLpw==", - "dev": true, - "requires": { - "postcss": "^7.0.2" - } - }, - "postcss-safe-parser": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-4.0.1.tgz", - "integrity": "sha512-xZsFA3uX8MO3yAda03QrG3/Eg1LN3EPfjjf07vke/46HERLZyHrTsQ9E1r1w1W//fWEhtYNndo2hQplN2cVpCQ==", - "dev": true, - "requires": { - "postcss": "^7.0.0" - } - }, - "postcss-selector-matches": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz", - "integrity": "sha512-LgsHwQR/EsRYSqlwdGzeaPKVT0Ml7LAT6E75T8W8xLJY62CE4S/l03BWIt3jT8Taq22kXP08s2SfTSzaraoPww==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "postcss": "^7.0.2" - } - }, - "postcss-selector-not": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-4.0.0.tgz", - "integrity": "sha512-W+bkBZRhqJaYN8XAnbbZPLWMvZD1wKTu0UxtFKdhtGjWYmxhkUneoeOhRJKdAE5V7ZTlnbHfCR+6bNwK9e1dTQ==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "postcss": "^7.0.2" - } - }, - "postcss-selector-parser": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz", - "integrity": "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==", - "dev": true, - "requires": { - "cssesc": "^3.0.0", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" - } - }, - "postcss-svgo": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.2.tgz", - "integrity": "sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw==", - "dev": true, - "requires": { - "is-svg": "^3.0.0", - "postcss": "^7.0.0", - "postcss-value-parser": "^3.0.0", - "svgo": "^1.0.0" - } - }, - "postcss-unique-selectors": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz", - "integrity": "sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg==", - "dev": true, - "requires": { - "alphanum-sort": "^1.0.0", - "postcss": "^7.0.0", - "uniqs": "^2.0.0" - } - }, - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - }, - "postcss-values-parser": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz", - "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==", - "dev": true, - "requires": { - "flatten": "^1.0.2", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } } }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "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 }, - "prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", "dev": true }, - "pretty-bytes": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.3.0.tgz", - "integrity": "sha512-hjGrh+P926p4R4WbaB6OckyRtO0F0/lQBiT+0gnxjV+5kjPBrfVBFCsCLbMqVQeydvIoouYTCmmEURiH3R1Bdg==", + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "dev": true }, - "pretty-error": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.1.tgz", - "integrity": "sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM=", - "dev": true, - "requires": { - "renderkid": "^2.0.1", - "utila": "~0.4" - } - }, - "pretty-format": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.0.1.tgz", - "integrity": "sha512-SWxz6MbupT3ZSlL0Po4WF/KujhQaVehijR2blyRDCzk9e45EaYMVhMBn49fnRuHxtkSpXTes1GxNpVmH86Bxfw==", + "query-string": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", + "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", "dev": true, "requires": { - "@jest/types": "^26.0.1", - "ansi-regex": "^5.0.0", - "ansi-styles": "^4.0.0", - "react-is": "^16.12.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - } + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" } }, - "private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", - "dev": true - }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", "dev": true }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", "dev": true }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "querystringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz", + "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==", "dev": true }, - "promise": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/promise/-/promise-8.0.3.tgz", - "integrity": "sha512-HeRDUL1RJiLhyA0/grn+PTShlBAcLuh/1BJGtrvjwbvRDCTLLMEz9rOGCV+R3vHY4MixIuoMEd9Yq/XvsTPcjw==", + "raf": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", + "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", "dev": true, "requires": { - "asap": "~2.0.6" + "performance-now": "^2.1.0" } }, - "promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "railroad-diagrams": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", + "integrity": "sha1-635iZ1SN3t+4mcG5Dlc3RVnN234=", "dev": true }, - "prompts": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.3.0.tgz", - "integrity": "sha512-NfbbPPg/74fT7wk2XYQ7hAIp9zJyZp5Fu19iRbORqqy1BhtrkZ0fPafBU+7bmn8ie69DpT0R6QpJIN2oisYjJg==", + "randexp": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", + "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", "dev": true, "requires": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.3" + "discontinuous-range": "1.0.0", + "ret": "~0.1.10" } }, - "prop-types": { - "version": "15.7.2", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", - "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, "requires": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.8.1" + "safe-buffer": "^5.1.0" } }, - "prop-types-exact": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/prop-types-exact/-/prop-types-exact-1.2.0.tgz", - "integrity": "sha512-K+Tk3Kd9V0odiXFP9fwDHUYRyvK3Nun3GVyPapSIs5OBkITAm15W0CPFD/YKTkMUAbc0b9CUwRQp2ybiBIq+eA==", + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", "dev": true, "requires": { - "has": "^1.0.3", - "object.assign": "^4.1.0", - "reflect.ownkeys": "^0.2.0" - } - }, - "proxy-addr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", - "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", - "dev": true, - "requires": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.9.0" - } - }, - "prr": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", - "dev": true - }, - "psl": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz", - "integrity": "sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ==", - "dev": true - }, - "public-encrypt": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", - "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", - "dev": true, - "requires": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - }, - "dependencies": { - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - } - } - }, - "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 - }, - "q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", - "dev": true - }, - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true - }, - "query-string": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", - "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", - "dev": true, - "requires": { - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" - } - }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", - "dev": true - }, - "querystring-es3": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", - "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", - "dev": true - }, - "querystringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz", - "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==", - "dev": true - }, - "raf": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", - "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", - "dev": true, - "requires": { - "performance-now": "^2.1.0" - } - }, - "railroad-diagrams": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", - "integrity": "sha1-635iZ1SN3t+4mcG5Dlc3RVnN234=", - "dev": true - }, - "randexp": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", - "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", - "dev": true, - "requires": { - "discontinuous-range": "1.0.0", - "ret": "~0.1.10" - } - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "randomfill": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", - "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", - "dev": true, - "requires": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" } }, "range-parser": { @@ -15024,2262 +11728,419 @@ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", "dev": true, - "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "dependencies": { - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", - "dev": true - } - } - }, - "react": { - "version": "16.11.0", - "resolved": "https://registry.npmjs.org/react/-/react-16.11.0.tgz", - "integrity": "sha512-M5Y8yITaLmU0ynd0r1Yvfq98Rmll6q8AxaEe88c8e7LxO8fZ2cNgmFt0aGAS9wzf1Ao32NKXtCl+/tVVtkxq6g==", - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2" - } - }, - "react-app-polyfill": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/react-app-polyfill/-/react-app-polyfill-1.0.6.tgz", - "integrity": "sha512-OfBnObtnGgLGfweORmdZbyEz+3dgVePQBb3zipiaDsMHV1NpWm0rDFYIVXFV/AK+x4VIIfWHhrdMIeoTLyRr2g==", - "dev": true, - "requires": { - "core-js": "^3.5.0", - "object-assign": "^4.1.1", - "promise": "^8.0.3", - "raf": "^3.4.1", - "regenerator-runtime": "^0.13.3", - "whatwg-fetch": "^3.0.0" - }, - "dependencies": { - "core-js": { - "version": "3.6.4", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.4.tgz", - "integrity": "sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw==", - "dev": true - } - } - }, - "react-dev-utils": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-9.1.0.tgz", - "integrity": "sha512-X2KYF/lIGyGwP/F/oXgGDF24nxDA2KC4b7AFto+eqzc/t838gpSGiaU8trTqHXOohuLxxc5qi1eDzsl9ucPDpg==", - "dev": true, - "requires": { - "@babel/code-frame": "7.5.5", - "address": "1.1.2", - "browserslist": "4.7.0", - "chalk": "2.4.2", - "cross-spawn": "6.0.5", - "detect-port-alt": "1.1.6", - "escape-string-regexp": "1.0.5", - "filesize": "3.6.1", - "find-up": "3.0.0", - "fork-ts-checker-webpack-plugin": "1.5.0", - "global-modules": "2.0.0", - "globby": "8.0.2", - "gzip-size": "5.1.1", - "immer": "1.10.0", - "inquirer": "6.5.0", - "is-root": "2.1.0", - "loader-utils": "1.2.3", - "open": "^6.3.0", - "pkg-up": "2.0.0", - "react-error-overlay": "^6.0.3", - "recursive-readdir": "2.2.2", - "shell-quote": "1.7.2", - "sockjs-client": "1.4.0", - "strip-ansi": "5.2.0", - "text-table": "0.2.0" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", - "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.0.0" - } - }, - "ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true - }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "browserslist": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.7.0.tgz", - "integrity": "sha512-9rGNDtnj+HaahxiVV38Gn8n8Lr8REKsel68v1sPFfIGEK6uSXTY3h9acgiT1dZVtOOUtifo/Dn8daDQ5dUgVsA==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30000989", - "electron-to-chromium": "^1.3.247", - "node-releases": "^1.1.29" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, - "requires": { - "restore-cursor": "^2.0.0" - } - }, - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "inquirer": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.0.tgz", - "integrity": "sha512-scfHejeG/lVZSpvCXpsB4j/wQNPM5JC8kiElOI0OUTwmc1RTpXr4H32/HOlQHcZiYl2z2VElwuCVDRG8vFmbnA==", - "dev": true, - "requires": { - "ansi-escapes": "^3.2.0", - "chalk": "^2.4.2", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^3.0.3", - "figures": "^2.0.0", - "lodash": "^4.17.12", - "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rxjs": "^6.4.0", - "string-width": "^2.1.0", - "strip-ansi": "^5.1.0", - "through": "^2.3.6" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true - }, - "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", - "dev": true - }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, - "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - } - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "dependencies": { - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - } - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "react-dom": { - "version": "16.11.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.11.0.tgz", - "integrity": "sha512-nrRyIUE1e7j8PaXSPtyRKtz+2y9ubW/ghNgqKFHHAHaeP0fpF5uXR+sq8IMRHC+ZUxw7W9NyCDTBtwWxvkb0iA==", - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.17.0" - } - }, - "react-error-overlay": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.5.tgz", - "integrity": "sha512-+DMR2k5c6BqMDSMF8hLH0vYKtKTeikiFW+fj0LClN+XZg4N9b8QUAdHC62CGWNLTi/gnuuemNcNcTFrCvK1f+A==", - "dev": true - }, - "react-is": { - "version": "16.12.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz", - "integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==" - }, - "react-scripts": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-3.2.0.tgz", - "integrity": "sha512-6LzuKbE2B4eFQG6i1FnTScn9HDcWBfXXnOwW9xKFPJ/E3rK8i1ufbOZ0ocKyRPxJAKdN7iqg3i7lt0+oxkSVOA==", - "dev": true, - "requires": { - "@babel/core": "7.6.0", - "@svgr/webpack": "4.3.2", - "@typescript-eslint/eslint-plugin": "^2.2.0", - "@typescript-eslint/parser": "^2.2.0", - "babel-eslint": "10.0.3", - "babel-jest": "^24.9.0", - "babel-loader": "8.0.6", - "babel-plugin-named-asset-import": "^0.3.4", - "babel-preset-react-app": "^9.0.2", - "camelcase": "^5.2.0", - "case-sensitive-paths-webpack-plugin": "2.2.0", - "css-loader": "2.1.1", - "dotenv": "6.2.0", - "dotenv-expand": "5.1.0", - "eslint": "^6.1.0", - "eslint-config-react-app": "^5.0.2", - "eslint-loader": "3.0.2", - "eslint-plugin-flowtype": "3.13.0", - "eslint-plugin-import": "2.18.2", - "eslint-plugin-jsx-a11y": "6.2.3", - "eslint-plugin-react": "7.14.3", - "eslint-plugin-react-hooks": "^1.6.1", - "file-loader": "3.0.1", - "fs-extra": "7.0.1", - "fsevents": "2.0.7", - "html-webpack-plugin": "4.0.0-beta.5", - "identity-obj-proxy": "3.0.0", - "is-wsl": "^1.1.0", - "jest": "24.9.0", - "jest-environment-jsdom-fourteen": "0.1.0", - "jest-resolve": "24.9.0", - "jest-watch-typeahead": "0.4.0", - "mini-css-extract-plugin": "0.8.0", - "optimize-css-assets-webpack-plugin": "5.0.3", - "pnp-webpack-plugin": "1.5.0", - "postcss-flexbugs-fixes": "4.1.0", - "postcss-loader": "3.0.0", - "postcss-normalize": "7.0.1", - "postcss-preset-env": "6.7.0", - "postcss-safe-parser": "4.0.1", - "react-app-polyfill": "^1.0.4", - "react-dev-utils": "^9.1.0", - "resolve": "1.12.0", - "resolve-url-loader": "3.1.0", - "sass-loader": "7.2.0", - "semver": "6.3.0", - "style-loader": "1.0.0", - "terser-webpack-plugin": "1.4.1", - "ts-pnp": "1.1.4", - "url-loader": "2.1.0", - "webpack": "4.41.0", - "webpack-dev-server": "3.2.1", - "webpack-manifest-plugin": "2.1.1", - "workbox-webpack-plugin": "4.3.1" - }, - "dependencies": { - "@jest/console": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-24.9.0.tgz", - "integrity": "sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ==", - "dev": true, - "requires": { - "@jest/source-map": "^24.9.0", - "chalk": "^2.0.1", - "slash": "^2.0.0" - } - }, - "@jest/core": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-24.9.0.tgz", - "integrity": "sha512-Fogg3s4wlAr1VX7q+rhV9RVnUv5tD7VuWfYy1+whMiWUrvl7U3QJSJyWcDio9Lq2prqYsZaeTv2Rz24pWGkJ2A==", - "dev": true, - "requires": { - "@jest/console": "^24.7.1", - "@jest/reporters": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/transform": "^24.9.0", - "@jest/types": "^24.9.0", - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.1", - "exit": "^0.1.2", - "graceful-fs": "^4.1.15", - "jest-changed-files": "^24.9.0", - "jest-config": "^24.9.0", - "jest-haste-map": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-regex-util": "^24.3.0", - "jest-resolve": "^24.9.0", - "jest-resolve-dependencies": "^24.9.0", - "jest-runner": "^24.9.0", - "jest-runtime": "^24.9.0", - "jest-snapshot": "^24.9.0", - "jest-util": "^24.9.0", - "jest-validate": "^24.9.0", - "jest-watcher": "^24.9.0", - "micromatch": "^3.1.10", - "p-each-series": "^1.0.0", - "realpath-native": "^1.1.0", - "rimraf": "^2.5.4", - "slash": "^2.0.0", - "strip-ansi": "^5.0.0" - } - }, - "@jest/environment": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-24.9.0.tgz", - "integrity": "sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ==", - "dev": true, - "requires": { - "@jest/fake-timers": "^24.9.0", - "@jest/transform": "^24.9.0", - "@jest/types": "^24.9.0", - "jest-mock": "^24.9.0" - } - }, - "@jest/fake-timers": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-24.9.0.tgz", - "integrity": "sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-mock": "^24.9.0" - } - }, - "@jest/reporters": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-24.9.0.tgz", - "integrity": "sha512-mu4X0yjaHrffOsWmVLzitKmmmWSQ3GGuefgNscUSWNiUNcEOSEQk9k3pERKEQVBb0Cnn88+UESIsZEMH3o88Gw==", - "dev": true, - "requires": { - "@jest/environment": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/transform": "^24.9.0", - "@jest/types": "^24.9.0", - "chalk": "^2.0.1", - "exit": "^0.1.2", - "glob": "^7.1.2", - "istanbul-lib-coverage": "^2.0.2", - "istanbul-lib-instrument": "^3.0.1", - "istanbul-lib-report": "^2.0.4", - "istanbul-lib-source-maps": "^3.0.1", - "istanbul-reports": "^2.2.6", - "jest-haste-map": "^24.9.0", - "jest-resolve": "^24.9.0", - "jest-runtime": "^24.9.0", - "jest-util": "^24.9.0", - "jest-worker": "^24.6.0", - "node-notifier": "^5.4.2", - "slash": "^2.0.0", - "source-map": "^0.6.0", - "string-length": "^2.0.0" - } - }, - "@jest/source-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-24.9.0.tgz", - "integrity": "sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg==", - "dev": true, - "requires": { - "callsites": "^3.0.0", - "graceful-fs": "^4.1.15", - "source-map": "^0.6.0" - } - }, - "@jest/test-result": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-24.9.0.tgz", - "integrity": "sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA==", - "dev": true, - "requires": { - "@jest/console": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/istanbul-lib-coverage": "^2.0.0" - } - }, - "@jest/test-sequencer": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-24.9.0.tgz", - "integrity": "sha512-6qqsU4o0kW1dvA95qfNog8v8gkRN9ph6Lz7r96IvZpHdNipP2cBcb07J1Z45mz/VIS01OHJ3pY8T5fUY38tg4A==", - "dev": true, - "requires": { - "@jest/test-result": "^24.9.0", - "jest-haste-map": "^24.9.0", - "jest-runner": "^24.9.0", - "jest-runtime": "^24.9.0" - } - }, - "@jest/transform": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-24.9.0.tgz", - "integrity": "sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ==", - "dev": true, - "requires": { - "@babel/core": "^7.1.0", - "@jest/types": "^24.9.0", - "babel-plugin-istanbul": "^5.1.0", - "chalk": "^2.0.1", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.1.15", - "jest-haste-map": "^24.9.0", - "jest-regex-util": "^24.9.0", - "jest-util": "^24.9.0", - "micromatch": "^3.1.10", - "pirates": "^4.0.1", - "realpath-native": "^1.1.0", - "slash": "^2.0.0", - "source-map": "^0.6.1", - "write-file-atomic": "2.4.1" - } - }, - "@jest/types": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-24.9.0.tgz", - "integrity": "sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^13.0.0" - } - }, - "@types/yargs": { - "version": "13.0.8", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.8.tgz", - "integrity": "sha512-XAvHLwG7UQ+8M4caKIH0ZozIOYay5fQkAgyIXegXT9jPtdIGdhga+sUEdAr1CiG46aB+c64xQEYyEzlwWVTNzA==", - "dev": true, - "requires": { - "@types/yargs-parser": "*" - } - }, - "acorn": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", - "dev": true - }, - "ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true - }, - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } - }, - "babel-jest": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-24.9.0.tgz", - "integrity": "sha512-ntuddfyiN+EhMw58PTNL1ph4C9rECiQXjI4nMMBKBaNjXvqLdkXpPRcMSr4iyBrJg/+wz9brFUD6RhOAT6r4Iw==", - "dev": true, - "requires": { - "@jest/transform": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/babel__core": "^7.1.0", - "babel-plugin-istanbul": "^5.1.0", - "babel-preset-jest": "^24.9.0", - "chalk": "^2.4.2", - "slash": "^2.0.0" - } - }, - "babel-plugin-istanbul": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz", - "integrity": "sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "find-up": "^3.0.0", - "istanbul-lib-instrument": "^3.3.0", - "test-exclude": "^5.2.3" - } - }, - "babel-plugin-jest-hoist": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.9.0.tgz", - "integrity": "sha512-2EMA2P8Vp7lG0RAzr4HXqtYwacfMErOuv1U3wrvxHX6rD1sV6xS3WXG3r8TRQ2r6w8OhvSdWt+z41hQNwNm3Xw==", - "dev": true, - "requires": { - "@types/babel__traverse": "^7.0.6" - } - }, - "babel-preset-jest": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-24.9.0.tgz", - "integrity": "sha512-izTUuhE4TMfTRPF92fFwD2QfdXaZW08qvWTFCI51V8rW5x00UuPgc3ajRoWofXOuxjfcOM5zzSYsQS3H8KGCAg==", - "dev": true, - "requires": { - "@babel/plugin-syntax-object-rest-spread": "^7.0.0", - "babel-plugin-jest-hoist": "^24.9.0" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - }, - "cssstyle": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-1.4.0.tgz", - "integrity": "sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA==", - "dev": true, - "requires": { - "cssom": "0.3.x" - } - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "detect-newline": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", - "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", - "dev": true - }, - "diff-sequences": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-24.9.0.tgz", - "integrity": "sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew==", - "dev": true - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "expect": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-24.9.0.tgz", - "integrity": "sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "ansi-styles": "^3.2.0", - "jest-get-type": "^24.9.0", - "jest-matcher-utils": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-regex-util": "^24.9.0" - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "fsevents": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.0.7.tgz", - "integrity": "sha512-a7YT0SV3RB+DjYcppwVDLtn13UQnmg0SWZS7ezZD0UjnLwXmy8Zm21GMVGLaFGimIqcvyMQaOJBrop8MyOp1kQ==", - "dev": true, - "optional": true - }, - "import-local": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", - "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", - "dev": true, - "requires": { - "pkg-dir": "^3.0.0", - "resolve-cwd": "^2.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "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": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", - "dev": true - }, - "istanbul-lib-coverage": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", - "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", - "dev": true - }, - "istanbul-lib-instrument": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", - "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", - "dev": true, - "requires": { - "@babel/generator": "^7.4.0", - "@babel/parser": "^7.4.3", - "@babel/template": "^7.4.0", - "@babel/traverse": "^7.4.3", - "@babel/types": "^7.4.0", - "istanbul-lib-coverage": "^2.0.5", - "semver": "^6.0.0" - } - }, - "istanbul-lib-report": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", - "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^2.0.5", - "make-dir": "^2.1.0", - "supports-color": "^6.1.0" - }, - "dependencies": { - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "istanbul-lib-source-maps": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", - "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^2.0.5", - "make-dir": "^2.1.0", - "rimraf": "^2.6.3", - "source-map": "^0.6.1" - } - }, - "istanbul-reports": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.7.tgz", - "integrity": "sha512-uu1F/L1o5Y6LzPVSVZXNOoD/KXpJue9aeLRd0sM9uMXfZvzomB0WxVamWb5ue8kA2vVWEmW7EG+A5n3f1kqHKg==", - "dev": true, - "requires": { - "html-escaper": "^2.0.0" - } - }, - "jest": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-24.9.0.tgz", - "integrity": "sha512-YvkBL1Zm7d2B1+h5fHEOdyjCG+sGMz4f8D86/0HiqJ6MB4MnDc8FgP5vdWsGnemOQro7lnYo8UakZ3+5A0jxGw==", - "dev": true, - "requires": { - "import-local": "^2.0.0", - "jest-cli": "^24.9.0" - }, - "dependencies": { - "jest-cli": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-24.9.0.tgz", - "integrity": "sha512-+VLRKyitT3BWoMeSUIHRxV/2g8y9gw91Jh5z2UmXZzkZKpbC08CSehVxgHUwTpy+HwGcns/tqafQDJW7imYvGg==", - "dev": true, - "requires": { - "@jest/core": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "chalk": "^2.0.1", - "exit": "^0.1.2", - "import-local": "^2.0.0", - "is-ci": "^2.0.0", - "jest-config": "^24.9.0", - "jest-util": "^24.9.0", - "jest-validate": "^24.9.0", - "prompts": "^2.0.1", - "realpath-native": "^1.1.0", - "yargs": "^13.3.0" - } - } - } - }, - "jest-changed-files": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-24.9.0.tgz", - "integrity": "sha512-6aTWpe2mHF0DhL28WjdkO8LyGjs3zItPET4bMSeXU6T3ub4FPMw+mcOcbdGXQOAfmLcxofD23/5Bl9Z4AkFwqg==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "execa": "^1.0.0", - "throat": "^4.0.0" - } - }, - "jest-config": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-24.9.0.tgz", - "integrity": "sha512-RATtQJtVYQrp7fvWg6f5y3pEFj9I+H8sWw4aKxnDZ96mob5i5SD6ZEGWgMLXQ4LE8UurrjbdlLWdUeo+28QpfQ==", - "dev": true, - "requires": { - "@babel/core": "^7.1.0", - "@jest/test-sequencer": "^24.9.0", - "@jest/types": "^24.9.0", - "babel-jest": "^24.9.0", - "chalk": "^2.0.1", - "glob": "^7.1.1", - "jest-environment-jsdom": "^24.9.0", - "jest-environment-node": "^24.9.0", - "jest-get-type": "^24.9.0", - "jest-jasmine2": "^24.9.0", - "jest-regex-util": "^24.3.0", - "jest-resolve": "^24.9.0", - "jest-util": "^24.9.0", - "jest-validate": "^24.9.0", - "micromatch": "^3.1.10", - "pretty-format": "^24.9.0", - "realpath-native": "^1.1.0" - } - }, - "jest-diff": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-24.9.0.tgz", - "integrity": "sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==", - "dev": true, - "requires": { - "chalk": "^2.0.1", - "diff-sequences": "^24.9.0", - "jest-get-type": "^24.9.0", - "pretty-format": "^24.9.0" - } - }, - "jest-docblock": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-24.9.0.tgz", - "integrity": "sha512-F1DjdpDMJMA1cN6He0FNYNZlo3yYmOtRUnktrT9Q37njYzC5WEaDdmbynIgy0L/IvXvvgsG8OsqhLPXTpfmZAA==", - "dev": true, - "requires": { - "detect-newline": "^2.1.0" - } - }, - "jest-each": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-24.9.0.tgz", - "integrity": "sha512-ONi0R4BvW45cw8s2Lrx8YgbeXL1oCQ/wIDwmsM3CqM/nlblNCPmnC3IPQlMbRFZu3wKdQ2U8BqM6lh3LJ5Bsog==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "chalk": "^2.0.1", - "jest-get-type": "^24.9.0", - "jest-util": "^24.9.0", - "pretty-format": "^24.9.0" - } - }, - "jest-environment-jsdom": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-24.9.0.tgz", - "integrity": "sha512-Zv9FV9NBRzLuALXjvRijO2351DRQeLYXtpD4xNvfoVFw21IOKNhZAEUKcbiEtjTkm2GsJ3boMVgkaR7rN8qetA==", - "dev": true, - "requires": { - "@jest/environment": "^24.9.0", - "@jest/fake-timers": "^24.9.0", - "@jest/types": "^24.9.0", - "jest-mock": "^24.9.0", - "jest-util": "^24.9.0", - "jsdom": "^11.5.1" - } - }, - "jest-environment-node": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-24.9.0.tgz", - "integrity": "sha512-6d4V2f4nxzIzwendo27Tr0aFm+IXWa0XEUnaH6nU0FMaozxovt+sfRvh4J47wL1OvF83I3SSTu0XK+i4Bqe7uA==", - "dev": true, - "requires": { - "@jest/environment": "^24.9.0", - "@jest/fake-timers": "^24.9.0", - "@jest/types": "^24.9.0", - "jest-mock": "^24.9.0", - "jest-util": "^24.9.0" - } - }, - "jest-get-type": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-24.9.0.tgz", - "integrity": "sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q==", - "dev": true - }, - "jest-haste-map": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-24.9.0.tgz", - "integrity": "sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "anymatch": "^2.0.0", - "fb-watchman": "^2.0.0", - "fsevents": "^1.2.7", - "graceful-fs": "^4.1.15", - "invariant": "^2.2.4", - "jest-serializer": "^24.9.0", - "jest-util": "^24.9.0", - "jest-worker": "^24.9.0", - "micromatch": "^3.1.10", - "sane": "^4.0.3", - "walker": "^1.0.7" - }, - "dependencies": { - "fsevents": { - "version": "1.2.11", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.11.tgz", - "integrity": "sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw==", - "dev": true, - "optional": true, - "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1", - "node-pre-gyp": "*" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "3.2.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.7", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.6.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.6", - "bundled": true, - "dev": true, - "optional": 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" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "bundled": true, - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true, - "optional": true - }, - "minipass": { - "version": "2.9.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.3.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.9.0" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^3.2.6", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.14.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4.4.2" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "npm-normalize-package-bin": "^1.0.1" - } - }, - "npm-normalize-package-bin": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.4.7", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.7.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.7.1", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.13", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "yallist": { - "version": "3.1.1", - "bundled": true, - "dev": true, - "optional": true - } - } - } - } - }, - "jest-jasmine2": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-24.9.0.tgz", - "integrity": "sha512-Cq7vkAgaYKp+PsX+2/JbTarrk0DmNhsEtqBXNwUHkdlbrTBLtMJINADf2mf5FkowNsq8evbPc07/qFO0AdKTzw==", - "dev": true, - "requires": { - "@babel/traverse": "^7.1.0", - "@jest/environment": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "chalk": "^2.0.1", - "co": "^4.6.0", - "expect": "^24.9.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^24.9.0", - "jest-matcher-utils": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-runtime": "^24.9.0", - "jest-snapshot": "^24.9.0", - "jest-util": "^24.9.0", - "pretty-format": "^24.9.0", - "throat": "^4.0.0" - } - }, - "jest-leak-detector": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-24.9.0.tgz", - "integrity": "sha512-tYkFIDsiKTGwb2FG1w8hX9V0aUb2ot8zY/2nFg087dUageonw1zrLMP4W6zsRO59dPkTSKie+D4rhMuP9nRmrA==", - "dev": true, - "requires": { - "jest-get-type": "^24.9.0", - "pretty-format": "^24.9.0" - } - }, - "jest-matcher-utils": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz", - "integrity": "sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA==", - "dev": true, - "requires": { - "chalk": "^2.0.1", - "jest-diff": "^24.9.0", - "jest-get-type": "^24.9.0", - "pretty-format": "^24.9.0" - } - }, - "jest-message-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-24.9.0.tgz", - "integrity": "sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/stack-utils": "^1.0.1", - "chalk": "^2.0.1", - "micromatch": "^3.1.10", - "slash": "^2.0.0", - "stack-utils": "^1.0.1" - } - }, - "jest-mock": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-24.9.0.tgz", - "integrity": "sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0" - } - }, - "jest-regex-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-24.9.0.tgz", - "integrity": "sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA==", - "dev": true - }, - "jest-resolve": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-24.9.0.tgz", - "integrity": "sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "browser-resolve": "^1.11.3", - "chalk": "^2.0.1", - "jest-pnp-resolver": "^1.2.1", - "realpath-native": "^1.1.0" - } - }, - "jest-resolve-dependencies": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-24.9.0.tgz", - "integrity": "sha512-Fm7b6AlWnYhT0BXy4hXpactHIqER7erNgIsIozDXWl5dVm+k8XdGVe1oTg1JyaFnOxarMEbax3wyRJqGP2Pq+g==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "jest-regex-util": "^24.3.0", - "jest-snapshot": "^24.9.0" - } - }, - "jest-runner": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-24.9.0.tgz", - "integrity": "sha512-KksJQyI3/0mhcfspnxxEOBueGrd5E4vV7ADQLT9ESaCzz02WnbdbKWIf5Mkaucoaj7obQckYPVX6JJhgUcoWWg==", - "dev": true, - "requires": { - "@jest/console": "^24.7.1", - "@jest/environment": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "chalk": "^2.4.2", - "exit": "^0.1.2", - "graceful-fs": "^4.1.15", - "jest-config": "^24.9.0", - "jest-docblock": "^24.3.0", - "jest-haste-map": "^24.9.0", - "jest-jasmine2": "^24.9.0", - "jest-leak-detector": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-resolve": "^24.9.0", - "jest-runtime": "^24.9.0", - "jest-util": "^24.9.0", - "jest-worker": "^24.6.0", - "source-map-support": "^0.5.6", - "throat": "^4.0.0" - } - }, - "jest-runtime": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-24.9.0.tgz", - "integrity": "sha512-8oNqgnmF3v2J6PVRM2Jfuj8oX3syKmaynlDMMKQ4iyzbQzIG6th5ub/lM2bCMTmoTKM3ykcUYI2Pw9xwNtjMnw==", - "dev": true, - "requires": { - "@jest/console": "^24.7.1", - "@jest/environment": "^24.9.0", - "@jest/source-map": "^24.3.0", - "@jest/transform": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/yargs": "^13.0.0", - "chalk": "^2.0.1", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.1.15", - "jest-config": "^24.9.0", - "jest-haste-map": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-mock": "^24.9.0", - "jest-regex-util": "^24.3.0", - "jest-resolve": "^24.9.0", - "jest-snapshot": "^24.9.0", - "jest-util": "^24.9.0", - "jest-validate": "^24.9.0", - "realpath-native": "^1.1.0", - "slash": "^2.0.0", - "strip-bom": "^3.0.0", - "yargs": "^13.3.0" - } - }, - "jest-serializer": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-24.9.0.tgz", - "integrity": "sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==", - "dev": true - }, - "jest-snapshot": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-24.9.0.tgz", - "integrity": "sha512-uI/rszGSs73xCM0l+up7O7a40o90cnrk429LOiK3aeTvfC0HHmldbd81/B7Ix81KSFe1lwkbl7GnBGG4UfuDew==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0", - "@jest/types": "^24.9.0", - "chalk": "^2.0.1", - "expect": "^24.9.0", - "jest-diff": "^24.9.0", - "jest-get-type": "^24.9.0", - "jest-matcher-utils": "^24.9.0", - "jest-message-util": "^24.9.0", - "jest-resolve": "^24.9.0", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "pretty-format": "^24.9.0", - "semver": "^6.2.0" - } - }, - "jest-util": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-24.9.0.tgz", - "integrity": "sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg==", - "dev": true, - "requires": { - "@jest/console": "^24.9.0", - "@jest/fake-timers": "^24.9.0", - "@jest/source-map": "^24.9.0", - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "callsites": "^3.0.0", - "chalk": "^2.0.1", - "graceful-fs": "^4.1.15", - "is-ci": "^2.0.0", - "mkdirp": "^0.5.1", - "slash": "^2.0.0", - "source-map": "^0.6.0" - } - }, - "jest-validate": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-24.9.0.tgz", - "integrity": "sha512-HPIt6C5ACwiqSiwi+OfSSHbK8sG7akG8eATl+IPKaeIjtPOeBUd/g3J7DghugzxrGjI93qS/+RPKe1H6PqvhRQ==", - "dev": true, - "requires": { - "@jest/types": "^24.9.0", - "camelcase": "^5.3.1", - "chalk": "^2.0.1", - "jest-get-type": "^24.9.0", - "leven": "^3.1.0", - "pretty-format": "^24.9.0" - } - }, - "jest-watcher": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-24.9.0.tgz", - "integrity": "sha512-+/fLOfKPXXYJDYlks62/4R4GoT+GU1tYZed99JSCOsmzkkF7727RqKrjNAxtfO4YpGv11wybgRvCjR73lK2GZw==", - "dev": true, - "requires": { - "@jest/test-result": "^24.9.0", - "@jest/types": "^24.9.0", - "@types/yargs": "^13.0.0", - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.1", - "jest-util": "^24.9.0", - "string-length": "^2.0.0" - } - }, - "jest-worker": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", - "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", - "dev": true, - "requires": { - "merge-stream": "^2.0.0", - "supports-color": "^6.1.0" - }, - "dependencies": { - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "jsdom": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz", - "integrity": "sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==", - "dev": true, - "requires": { - "abab": "^2.0.0", - "acorn": "^5.5.3", - "acorn-globals": "^4.1.0", - "array-equal": "^1.0.0", - "cssom": ">= 0.3.2 < 0.4.0", - "cssstyle": "^1.0.0", - "data-urls": "^1.0.0", - "domexception": "^1.0.1", - "escodegen": "^1.9.1", - "html-encoding-sniffer": "^1.0.2", - "left-pad": "^1.3.0", - "nwsapi": "^2.0.7", - "parse5": "4.0.0", - "pn": "^1.1.0", - "request": "^2.87.0", - "request-promise-native": "^1.0.5", - "sax": "^1.2.4", - "symbol-tree": "^3.2.2", - "tough-cookie": "^2.3.4", - "w3c-hr-time": "^1.0.1", - "webidl-conversions": "^4.0.2", - "whatwg-encoding": "^1.0.3", - "whatwg-mimetype": "^2.1.0", - "whatwg-url": "^6.4.1", - "ws": "^5.2.0", - "xml-name-validator": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "dependencies": { + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", "dev": true - }, - "node-notifier": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.4.3.tgz", - "integrity": "sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q==", - "dev": true, - "requires": { - "growly": "^1.3.0", - "is-wsl": "^1.1.0", - "semver": "^5.5.0", - "shellwords": "^0.1.1", - "which": "^1.3.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } - } - }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + } + } + }, + "react": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react/-/react-16.13.1.tgz", + "integrity": "sha512-YMZQQq32xHLX0bz5Mnibv1/LHb3Sqzngu7xstSM+vrkE5Kzr9xE0yMByK5kMoTK30YVJE61WfbxIFFvfeDKT1w==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2" + } + }, + "react-app-polyfill": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/react-app-polyfill/-/react-app-polyfill-1.0.6.tgz", + "integrity": "sha512-OfBnObtnGgLGfweORmdZbyEz+3dgVePQBb3zipiaDsMHV1NpWm0rDFYIVXFV/AK+x4VIIfWHhrdMIeoTLyRr2g==", + "dev": true, + "requires": { + "core-js": "^3.5.0", + "object-assign": "^4.1.1", + "promise": "^8.0.3", + "raf": "^3.4.1", + "regenerator-runtime": "^0.13.3", + "whatwg-fetch": "^3.0.0" + } + }, + "react-dev-utils": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-10.2.1.tgz", + "integrity": "sha512-XxTbgJnYZmxuPtY3y/UV0D8/65NKkmaia4rXzViknVnZeVlklSh8u6TnaEYPfAi/Gh1TP4mEOXHI6jQOPbeakQ==", + "dev": true, + "requires": { + "@babel/code-frame": "7.8.3", + "address": "1.1.2", + "browserslist": "4.10.0", + "chalk": "2.4.2", + "cross-spawn": "7.0.1", + "detect-port-alt": "1.1.6", + "escape-string-regexp": "2.0.0", + "filesize": "6.0.1", + "find-up": "4.1.0", + "fork-ts-checker-webpack-plugin": "3.1.1", + "global-modules": "2.0.0", + "globby": "8.0.2", + "gzip-size": "5.1.1", + "immer": "1.10.0", + "inquirer": "7.0.4", + "is-root": "2.1.0", + "loader-utils": "1.2.3", + "open": "^7.0.2", + "pkg-up": "3.1.0", + "react-error-overlay": "^6.0.7", + "recursive-readdir": "2.2.2", + "shell-quote": "1.7.2", + "strip-ansi": "6.0.0", + "text-table": "0.2.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", + "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", "dev": true, "requires": { - "remove-trailing-separator": "^1.0.1" + "@babel/highlight": "^7.8.3" } }, - "p-each-series": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-1.0.0.tgz", - "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", - "dev": true, - "requires": { - "p-reduce": "^1.0.0" - } + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "browserslist": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.10.0.tgz", + "integrity": "sha512-TpfK0TDgv71dzuTsEAlQiHeWQ/tiPqgNZVdv046fvNtBZrjbv2O3TsWCDU0AWGJJKCF/KsjNdLzR9hXOsh/CfA==", "dev": true, "requires": { - "p-limit": "^2.0.0" + "caniuse-lite": "^1.0.30001035", + "electron-to-chromium": "^1.3.378", + "node-releases": "^1.1.52", + "pkg-up": "^3.1.0" } }, - "parse5": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", - "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", - "dev": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "cli-width": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", "dev": true }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "requires": { - "find-up": "^3.0.0" - } - }, - "pretty-format": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", - "integrity": "sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA==", + "cross-spawn": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.1.tgz", + "integrity": "sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg==", "dev": true, "requires": { - "@jest/types": "^24.9.0", - "ansi-regex": "^4.0.0", - "ansi-styles": "^3.2.0", - "react-is": "^16.8.4" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" } }, - "resolve": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", - "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true }, - "resolve-cwd": { + "escape-string-regexp": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", - "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", - "dev": true, - "requires": { - "resolve-from": "^3.0.0" - } + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "requires": { - "glob": "^7.1.3" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" } }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true - }, - "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 - }, - "string-length": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", - "integrity": "sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=", + "inquirer": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.4.tgz", + "integrity": "sha512-Bu5Td5+j11sCkqfqmUTiwv+tWisMtP0L7Q8WrqA2C/BbBhy1YTdFrvjjlrKq8oagA/tLQBski2Gcx/Sqyi2qSQ==", "dev": true, "requires": { - "astral-regex": "^1.0.0", - "strip-ansi": "^4.0.0" + "ansi-escapes": "^4.2.1", + "chalk": "^2.4.2", + "cli-cursor": "^3.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.15", + "mute-stream": "0.0.8", + "run-async": "^2.2.0", + "rxjs": "^6.5.3", + "string-width": "^4.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" }, "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^4.1.0" } } } }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "dev": true, "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "minimist": "^1.2.0" } }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "loader-utils": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", + "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", "dev": true, "requires": { - "ansi-regex": "^4.1.0" + "big.js": "^5.2.2", + "emojis-list": "^2.0.0", + "json5": "^1.0.1" } }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "p-locate": "^4.1.0" } }, - "test-exclude": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", - "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "requires": { - "glob": "^7.1.3", - "minimatch": "^3.0.4", - "read-pkg-up": "^4.0.0", - "require-main-filename": "^2.0.0" + "p-limit": "^2.2.0" } }, - "throat": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", - "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=", + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" + "shebang-regex": "^3.0.0" } }, - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "dev": true, "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" + "ansi-regex": "^5.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + } } }, - "whatwg-url": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", - "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "react-dom": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.13.1.tgz", + "integrity": "sha512-81PIMmVLnCNLO/fFOQxdQkvEq/+Hfpv24XNJfpyZhTRfO0QcmQIF/PgCa1zCOj2w1hrn12MFLyaJ/G0+Mxtfag==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.19.1" + } + }, + "react-error-overlay": { + "version": "6.0.7", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.7.tgz", + "integrity": "sha512-TAv1KJFh3RhqxNvhzxj6LeT5NWklP6rDr2a0jaTfsZ5wSZWHOGeqQyejUp3xxLfPt2UpyJEcVQB/zyPcmonNFA==", + "dev": true + }, + "react-is": { + "version": "16.12.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.12.0.tgz", + "integrity": "sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q==" + }, + "react-scripts": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-3.4.1.tgz", + "integrity": "sha512-JpTdi/0Sfd31mZA6Ukx+lq5j1JoKItX7qqEK4OiACjVQletM1P38g49d9/D0yTxp9FrSF+xpJFStkGgKEIRjlQ==", + "dev": true, + "requires": { + "@babel/core": "7.9.0", + "@svgr/webpack": "4.3.3", + "@typescript-eslint/eslint-plugin": "^2.10.0", + "@typescript-eslint/parser": "^2.10.0", + "babel-eslint": "10.1.0", + "babel-jest": "^24.9.0", + "babel-loader": "8.1.0", + "babel-plugin-named-asset-import": "^0.3.6", + "babel-preset-react-app": "^9.1.2", + "camelcase": "^5.3.1", + "case-sensitive-paths-webpack-plugin": "2.3.0", + "css-loader": "3.4.2", + "dotenv": "8.2.0", + "dotenv-expand": "5.1.0", + "eslint": "^6.6.0", + "eslint-config-react-app": "^5.2.1", + "eslint-loader": "3.0.3", + "eslint-plugin-flowtype": "4.6.0", + "eslint-plugin-import": "2.20.1", + "eslint-plugin-jsx-a11y": "6.2.3", + "eslint-plugin-react": "7.19.0", + "eslint-plugin-react-hooks": "^1.6.1", + "file-loader": "4.3.0", + "fs-extra": "^8.1.0", + "fsevents": "2.1.2", + "html-webpack-plugin": "4.0.0-beta.11", + "identity-obj-proxy": "3.0.0", + "jest": "24.9.0", + "jest-environment-jsdom-fourteen": "1.0.1", + "jest-resolve": "24.9.0", + "jest-watch-typeahead": "0.4.2", + "mini-css-extract-plugin": "0.9.0", + "optimize-css-assets-webpack-plugin": "5.0.3", + "pnp-webpack-plugin": "1.6.4", + "postcss-flexbugs-fixes": "4.1.0", + "postcss-loader": "3.0.0", + "postcss-normalize": "8.0.1", + "postcss-preset-env": "6.7.0", + "postcss-safe-parser": "4.0.1", + "react-app-polyfill": "^1.0.6", + "react-dev-utils": "^10.2.1", + "resolve": "1.15.0", + "resolve-url-loader": "3.1.1", + "sass-loader": "8.0.2", + "semver": "6.3.0", + "style-loader": "0.23.1", + "terser-webpack-plugin": "2.3.5", + "ts-pnp": "1.1.6", + "url-loader": "2.3.0", + "webpack": "4.42.0", + "webpack-dev-server": "3.10.3", + "webpack-manifest-plugin": "2.2.0", + "workbox-webpack-plugin": "4.3.1" + }, + "dependencies": { + "@babel/core": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.9.0.tgz", + "integrity": "sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w==", "dev": true, "requires": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.9.0", + "@babel/helper-module-transforms": "^7.9.0", + "@babel/helpers": "^7.9.0", + "@babel/parser": "^7.9.0", + "@babel/template": "^7.8.6", + "@babel/traverse": "^7.9.0", + "@babel/types": "^7.9.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", "dev": true, "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" + "ms": "^2.1.1" } }, - "write-file-atomic": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.1.tgz", - "integrity": "sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==", + "fsevents": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz", + "integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==", "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } + "optional": true }, - "ws": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", - "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0" - } + "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 }, - "yargs": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", - "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "resolve": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.0.tgz", + "integrity": "sha512-+hTmAldEGE80U2wJJDC1lebb5jWqvTYAfm3YZ1ckk1gBr0MnCqUKlwK1e+anaFljIl+F5tR5IoZcm4ZDA1zMQw==", "dev": true, "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.1" + "path-parse": "^1.0.6" } }, - "yargs-parser": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", - "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true } } }, @@ -17308,9 +12169,9 @@ } }, "react-transition-group": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.3.0.tgz", - "integrity": "sha512-1qRV1ZuVSdxPlPf4O8t7inxUGpdyO5zG9IoNfJxSO0ImU2A1YWkEQvFPuIPZmMLkg5hYs7vv5mMOyfgSkvAwvw==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.1.tgz", + "integrity": "sha512-Djqr7OQ2aPUiYurhPalTrVy9ddmFCCzwhqQmtN+J3+3DzLO209Fdr70QrN8Z3DsglWql6iY1lDWAfpFiBtuKGw==", "requires": { "@babel/runtime": "^7.5.5", "dom-helpers": "^5.0.1", @@ -17337,42 +12198,6 @@ "requires": { "find-up": "^3.0.0", "read-pkg": "^3.0.0" - }, - "dependencies": { - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - } } }, "readable-stream": { @@ -17397,78 +12222,6 @@ "readable-stream": "^2.0.2" }, "dependencies": { - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "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": { - "is-buffer": "^1.1.5" - } - } - } - }, "micromatch": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", @@ -17513,16 +12266,6 @@ "requires": { "safe-buffer": "~5.1.0" } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } } } }, @@ -17551,34 +12294,32 @@ "dev": true }, "regenerate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", + "integrity": "sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A==", "dev": true }, "regenerate-unicode-properties": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz", - "integrity": "sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", + "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", "dev": true, "requires": { "regenerate": "^1.4.0" } }, "regenerator-runtime": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", - "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==" + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" }, "regenerator-transform": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", - "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", + "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", "dev": true, "requires": { - "babel-runtime": "^6.18.0", - "babel-types": "^6.19.0", - "private": "^0.1.6" + "@babel/runtime": "^7.8.4" } }, "regex-not": { @@ -17608,35 +12349,46 @@ } }, "regexpp": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.0.0.tgz", - "integrity": "sha512-Z+hNr7RAVWxznLPuA7DIh8UNX1j9CDrUQxskw9IrBE1Dxue2lyXT+shqEIeLUjrokxIP8CMy1WkjgG3rTsd5/g==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", "dev": true }, "regexpu-core": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", - "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.0.tgz", + "integrity": "sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ==", "dev": true, "requires": { - "regenerate": "^1.2.1", - "regjsgen": "^0.2.0", - "regjsparser": "^0.1.4" + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.2.0", + "regjsgen": "^0.5.1", + "regjsparser": "^0.6.4", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.2.0" } }, "regjsgen": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", + "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==", "dev": true }, "regjsparser": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", - "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.4.tgz", + "integrity": "sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==", "dev": true, "requires": { "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } } }, "relateurl": { @@ -17662,6 +12414,23 @@ "htmlparser2": "^3.3.0", "strip-ansi": "^3.0.0", "utila": "^0.4.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } } }, "repeat-element": { @@ -17702,50 +12471,34 @@ "tough-cookie": "~2.5.0", "tunnel-agent": "^0.6.0", "uuid": "^3.3.2" - }, - "dependencies": { - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - } } }, "request-promise-core": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.3.tgz", - "integrity": "sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", + "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", "dev": true, "requires": { - "lodash": "^4.17.15" + "lodash": "^4.17.19" + }, + "dependencies": { + "lodash": { + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", + "dev": true + } } }, "request-promise-native": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.8.tgz", - "integrity": "sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz", + "integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==", "dev": true, "requires": { - "request-promise-core": "1.1.3", + "request-promise-core": "1.1.4", "stealthy-require": "^1.1.1", "tough-cookie": "^2.3.3" - }, - "dependencies": { - "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "dev": true, - "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - } - } } }, "require-directory": { @@ -17760,12 +12513,6 @@ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, - "require-relative": { - "version": "0.8.7", - "resolved": "https://registry.npmjs.org/require-relative/-/require-relative-0.8.7.tgz", - "integrity": "sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4=", - "dev": true - }, "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -17773,29 +12520,21 @@ "dev": true }, "resolve": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", - "integrity": "sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", "dev": true, "requires": { "path-parse": "^1.0.6" } }, "resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", "dev": true, "requires": { - "resolve-from": "^5.0.0" - }, - "dependencies": { - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - } + "resolve-from": "^3.0.0" } }, "resolve-from": { @@ -17811,73 +12550,53 @@ "dev": true }, "resolve-url-loader": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-3.1.0.tgz", - "integrity": "sha512-2QcrA+2QgVqsMJ1Hn5NnJXIGCX1clQ1F6QJTqOeiaDw9ACo1G2k+8/shq3mtqne03HOFyskAClqfxKyFBriXZg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-3.1.1.tgz", + "integrity": "sha512-K1N5xUjj7v0l2j/3Sgs5b8CjrrgtC70SmdCuZiJ8tSyb5J+uk3FoeZ4b7yTnH6j7ngI+Bc5bldHJIa8hYdu2gQ==", "dev": true, "requires": { "adjust-sourcemap-loader": "2.0.0", - "camelcase": "5.0.0", + "camelcase": "5.3.1", "compose-function": "3.0.3", - "convert-source-map": "1.6.0", + "convert-source-map": "1.7.0", "es6-iterator": "2.0.3", "loader-utils": "1.2.3", - "postcss": "7.0.14", + "postcss": "7.0.21", "rework": "1.0.1", "rework-visit": "1.0.0", "source-map": "0.6.1" }, "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "camelcase": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz", - "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", "dev": true }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "dev": true, "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } + "minimist": "^1.2.0" } }, - "convert-source-map": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", - "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "loader-utils": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", + "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", "dev": true, "requires": { - "safe-buffer": "~5.1.1" + "big.js": "^5.2.2", + "emojis-list": "^2.0.0", + "json5": "^1.0.1" } }, "postcss": { - "version": "7.0.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.14.tgz", - "integrity": "sha512-NsbD6XUUMZvBxtQAJuWDJeeC4QFsmWsfozWxCJPWf3M55K9iu2iMDaKqyoOdTJ1R4usBXuxlVFAIo8rZPQD4Bg==", + "version": "7.0.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.21.tgz", + "integrity": "sha512-uIFtJElxJo29QC753JzhidoAhvp/e/Exezkdhfmt8AymWT6/5B7W1WmponYWkHk2eg6sONyTch0A3nkMPun3SQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -17918,6 +12637,12 @@ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", "dev": true }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "dev": true + }, "rework": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/rework/-/rework-1.0.1.tgz", @@ -17955,9 +12680,9 @@ "dev": true }, "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", "dev": true, "requires": { "glob": "^7.1.3" @@ -17990,13 +12715,10 @@ "dev": true }, "run-async": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true, - "requires": { - "is-promise": "^2.1.0" - } + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true }, "run-queue": { "version": "1.0.3", @@ -18008,9 +12730,9 @@ } }, "rxjs": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz", - "integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==", + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.2.tgz", + "integrity": "sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==", "dev": true, "requires": { "tslib": "^1.9.0" @@ -18052,143 +12774,25 @@ "micromatch": "^3.1.4", "minimist": "^1.1.1", "walker": "~1.0.5" - }, - "dependencies": { - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "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": { - "is-buffer": "^1.1.5" - } - } - } - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - } } }, + "sanitize.css": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/sanitize.css/-/sanitize.css-10.0.0.tgz", + "integrity": "sha512-vTxrZz4dX5W86M6oVWVdOVe72ZiPs41Oi7Z6Km4W5Turyz28mrXSJhhEBZoRtzJWIv3833WKVwLSDWWkEfupMg==", + "dev": true + }, "sass-loader": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-7.2.0.tgz", - "integrity": "sha512-h8yUWaWtsbuIiOCgR9fd9c2lRXZ2uG+h8Dzg/AGNj+Hg/3TO8+BBAW9mEP+mh8ei+qBKqSJ0F1FLlYjNBc61OA==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-8.0.2.tgz", + "integrity": "sha512-7o4dbSK8/Ol2KflEmSco4jTjQoV988bM82P9CZdmo9hR3RLnvNc0ufMNdMrB0caq38JQ/FgF4/7RcbcfKzxoFQ==", "dev": true, "requires": { "clone-deep": "^4.0.1", - "loader-utils": "^1.0.1", - "neo-async": "^2.5.0", - "pify": "^4.0.1", - "semver": "^5.5.0" + "loader-utils": "^1.2.3", + "neo-async": "^2.6.1", + "schema-utils": "^2.6.1", + "semver": "^6.3.0" }, "dependencies": { "clone-deep": { @@ -18202,10 +12806,10 @@ "shallow-clone": "^3.0.0" } }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, "shallow-clone": { @@ -18235,23 +12839,23 @@ } }, "scheduler": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.17.0.tgz", - "integrity": "sha512-7rro8Io3tnCPuY4la/NuI5F2yfESpnfZyT6TtkXnSWVkcu0BCDJ+8gk5ozUaFaxpIyNuWAPXrH0yFcSi28fnDA==", + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", + "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1" } }, "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", + "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", "dev": true, "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" + "@types/json-schema": "^7.0.4", + "ajv": "^6.12.2", + "ajv-keywords": "^3.4.1" } }, "select-hose": { @@ -18311,9 +12915,9 @@ } }, "serialize-javascript": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.9.1.tgz", - "integrity": "sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz", + "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==", "dev": true }, "serve-index": { @@ -18476,10 +13080,20 @@ "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", "dev": true }, + "side-channel": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.2.tgz", + "integrity": "sha512-7rL9YlPHg7Ancea1S96Pa8/QWb4BtXL/TZvS6B8XFetGBeuhAsfmUspK6DokBeZ64+Kj9TCNRD/30pVz1BvQNA==", + "dev": true, + "requires": { + "es-abstract": "^1.17.0-next.1", + "object-inspect": "^1.7.0" + } + }, "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, "simple-swizzle": { @@ -18500,15 +13114,15 @@ } }, "sisteransi": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.4.tgz", - "integrity": "sha512-/ekMoM4NJ59ivGSfKapeG+FWtrmWvA1p6FBZwXrqojw90vJu8lBmrTxCMuBCydKtkaUe2zt4PlxeTKpjwMbyig==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", "dev": true }, "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", "dev": true }, "slice-ansi": { @@ -18522,15 +13136,6 @@ "is-fullwidth-code-point": "^2.0.0" }, "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", @@ -18654,17 +13259,6 @@ "requires": { "faye-websocket": "^0.10.0", "uuid": "^3.0.1" - }, - "dependencies": { - "faye-websocket": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", - "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", - "dev": true, - "requires": { - "websocket-driver": ">=0.5.1" - } - } } }, "sockjs-client": { @@ -18690,6 +13284,15 @@ "ms": "^2.1.1" } }, + "faye-websocket": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.3.tgz", + "integrity": "sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA==", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -18733,9 +13336,9 @@ } }, "source-map-support": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", - "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -18757,9 +13360,9 @@ "dev": true }, "spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", @@ -18767,15 +13370,15 @@ } }, "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", "dev": true }, "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, "requires": { "spdx-exceptions": "^2.1.0", @@ -18789,9 +13392,9 @@ "dev": true }, "spdy": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.1.tgz", - "integrity": "sha512-HeZS3PBdMA+sZSu0qwpCxl3DeALD5ASx8pAX0jZdKXSpPWbQ6SYGnlg3BBmYLx5LtiZrmkAZfErCm2oECBcioA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", "dev": true, "requires": { "debug": "^4.1.0", @@ -18882,12 +13485,13 @@ } }, "ssri": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", - "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-7.1.0.tgz", + "integrity": "sha512-77/WrDZUWocK0mvA5NTRQyveUf+wsrIc6vyrxpS8tVvYBcX215QbafrJR3KtkpskIzoFLqqNuuYQvxaMjXJ/0g==", "dev": true, "requires": { - "figgy-pudding": "^3.5.1" + "figgy-pudding": "^3.5.1", + "minipass": "^3.1.1" } }, "stable": { @@ -19033,28 +13637,28 @@ "dev": true }, "string-length": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-3.1.0.tgz", - "integrity": "sha512-Ttp5YvkGm5v9Ijagtaz1BnN+k9ObpvS0eIBblPMp2YWL8FBmi9qblQ9fexc2k/CXFgrTIteU3jAw3payCnwSTA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-2.0.0.tgz", + "integrity": "sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=", "dev": true, "requires": { "astral-regex": "^1.0.0", - "strip-ansi": "^5.2.0" + "strip-ansi": "^4.0.0" }, "dependencies": { "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^3.0.0" } } } @@ -19070,12 +13674,6 @@ "strip-ansi": "^6.0.0" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, "strip-ansi": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", @@ -19087,6 +13685,20 @@ } } }, + "string.prototype.matchall": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.2.tgz", + "integrity": "sha512-N/jp6O5fMf9os0JU3E72Qhf590RSRZU/ungsL/qJUYVTNv7hTG0P/dbPjxINVN9jpscu3nzYwKESU3P3RY5tOg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0", + "has-symbols": "^1.0.1", + "internal-slot": "^1.0.2", + "regexp.prototype.flags": "^1.3.0", + "side-channel": "^1.0.2" + } + }, "string.prototype.trim": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.1.tgz", @@ -19128,9 +13740,9 @@ }, "dependencies": { "safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true } } @@ -19155,18 +13767,26 @@ } }, "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "^4.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + } } }, "strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true }, "strip-comments": { @@ -19185,36 +13805,31 @@ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, - "strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true - }, "strip-json-comments": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", - "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, "style-loader": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.0.0.tgz", - "integrity": "sha512-B0dOCFwv7/eY31a5PCieNwMgMhVGFe9w+rh7s/Bx8kfFkrth9zfTZquoYvdw8URgiqxObQKcpW51Ugz1HjfdZw==", + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.23.1.tgz", + "integrity": "sha512-XK+uv9kWwhZMZ1y7mysB+zoihsEj4wneFWAS5qoiLwzW0WzSqMrrsIy+a3zkQJq0ipFtBpX5W3MqyRIBF/WFGg==", "dev": true, "requires": { - "loader-utils": "^1.2.3", - "schema-utils": "^2.0.1" + "loader-utils": "^1.1.0", + "schema-utils": "^1.0.0" }, "dependencies": { "schema-utils": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.4.tgz", - "integrity": "sha512-VNjcaUxVnEeun6B2fiiUDjXXBtD4ZSH7pdbfIu1pOFwgptDPLMo/z9jr4sUfsjFVPqDCEin/F7IYlq7/E6yDbQ==", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", "dev": true, "requires": { - "ajv": "^6.10.2", - "ajv-keywords": "^3.4.1" + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" } } } @@ -19244,42 +13859,18 @@ } }, "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - }, - "supports-hyperlinks": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.1.0.tgz", - "integrity": "sha512-zoE5/e+dnEijk6ASB6/qrK+oYdm2do1hjoLWrqUC/8WEIW1gbxFcKuBof7sW8ArN6e+AYvsE8HBGiVRWL/F5CA==", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { - "has-flag": "^4.0.0", - "supports-color": "^7.0.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } + "has-flag": "^3.0.0" } }, "svg-parser": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.3.tgz", - "integrity": "sha512-fnCWiifNhK8i2Z7b9R5tbNahpxrRdAaQbnoxKlT2KrSCj9Kq/yBSgulCRgBJRhy1dPnSY5slg5ehPUnzpEcHlg==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", "dev": true }, "svgo": { @@ -19303,26 +13894,6 @@ "util.promisify": "~1.0.0" }, "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, "css-select": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", @@ -19336,28 +13907,19 @@ } }, "css-what": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.2.1.tgz", - "integrity": "sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.3.0.tgz", + "integrity": "sha512-pv9JPyatiPaQ6pf4OvD/dbfm0o5LviWmwxNWzblYf/1u9QZd0ihV+PMwy5jdQWQ3349kZmKEx9WXuSka2dM4cg==", "dev": true - }, - "domutils": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", - "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", - "dev": true, - "requires": { - "dom-serializer": "0", - "domelementtype": "1" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "dom-serializer": "0", + "domelementtype": "1" } } } @@ -19380,12 +13942,6 @@ "string-width": "^3.0.0" }, "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", @@ -19408,15 +13964,6 @@ "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^5.1.0" } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } } } }, @@ -19426,20 +13973,10 @@ "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", "dev": true }, - "terminal-link": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/terminal-link/-/terminal-link-2.1.1.tgz", - "integrity": "sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==", - "dev": true, - "requires": { - "ansi-escapes": "^4.2.1", - "supports-hyperlinks": "^2.0.0" - } - }, "terser": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.3.tgz", - "integrity": "sha512-Lw+ieAXmY69d09IIc/yqeBqXpEQIpDGZqT34ui1QWXIUpR2RjbqEkT8X7Lgex19hslSqcWM5iMN2kM11eMsESQ==", + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", "dev": true, "requires": { "commander": "^2.20.0", @@ -19456,26 +13993,105 @@ } }, "terser-webpack-plugin": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.1.tgz", - "integrity": "sha512-ZXmmfiwtCLfz8WKZyYUuuHf3dMYEjg8NrjHMb0JqHVHVOSkzp3cW2/XG1fP3tRhqEqSzMwzzRQGtAPbs4Cncxg==", + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-2.3.5.tgz", + "integrity": "sha512-WlWksUoq+E4+JlJ+h+U+QUzXpcsMSSNXkDy9lBVkSqDn1w23Gg29L/ary9GeJVYCGiNJJX7LnVc4bwL1N3/g1w==", "dev": true, "requires": { - "cacache": "^12.0.2", - "find-cache-dir": "^2.1.0", - "is-wsl": "^1.1.0", - "schema-utils": "^1.0.0", - "serialize-javascript": "^1.7.0", + "cacache": "^13.0.1", + "find-cache-dir": "^3.2.0", + "jest-worker": "^25.1.0", + "p-limit": "^2.2.2", + "schema-utils": "^2.6.4", + "serialize-javascript": "^2.1.2", "source-map": "^0.6.1", - "terser": "^4.1.2", - "webpack-sources": "^1.4.0", - "worker-farm": "^1.7.0" + "terser": "^4.4.3", + "webpack-sources": "^1.4.3" }, "dependencies": { - "is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "find-cache-dir": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", + "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jest-worker": { + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-25.5.0.tgz", + "integrity": "sha512-/dsSmUkIy5EBGfv/IjjqmFxrNAUpBERfGs1oHROyD7yxjG/w+t0GOJDX8O1k32ySmd7+a5IhnJU2qQFcJ4n1vw==", + "dev": true, + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, "source-map": { @@ -19483,18 +14099,28 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } } } }, "test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", + "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", "dev": true, "requires": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^2.0.0" } }, "text-table": { @@ -19504,9 +14130,9 @@ "dev": true }, "throat": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", - "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-4.1.0.tgz", + "integrity": "sha1-iQN8vJLFarGJJua6TLsgDhVnKmo=", "dev": true }, "through": { @@ -19593,12 +14219,6 @@ "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", "dev": true }, - "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true - }, "to-object-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", @@ -19632,12 +14252,13 @@ } }, "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", "dev": true, "requires": { - "is-number": "^7.0.0" + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" } }, "toidentifier": { @@ -19647,12 +14268,11 @@ "dev": true }, "tough-cookie": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-3.0.1.tgz", - "integrity": "sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", "dev": true, "requires": { - "ip-regex": "^2.1.0", "psl": "^1.1.28", "punycode": "^2.1.1" } @@ -19667,15 +14287,15 @@ } }, "ts-pnp": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.1.4.tgz", - "integrity": "sha512-1J/vefLC+BWSo+qe8OnJQfWTYRS6ingxjwqmHMqaMxXMj7kFtKLgAaYW3JeX3mktjgUL+etlU8/B4VUAUI9QGw==", + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.1.6.tgz", + "integrity": "sha512-CrG5GqAAzMT7144Cl+UIFP7mz/iIhiy+xQ6GGcnjTezhALT02uPMRw7tgDSESgB5MsfKt55+GPWw4ir1kVtMIQ==", "dev": true }, "tslib": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", - "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", + "integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", "dev": true }, "tsutils": { @@ -19723,12 +14343,6 @@ "prelude-ls": "~1.1.2" } }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - }, "type-fest": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", @@ -19751,39 +14365,6 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, - "typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "requires": { - "is-typedarray": "^1.0.0" - } - }, - "uglify-js": { - "version": "3.4.10", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz", - "integrity": "sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==", - "dev": true, - "requires": { - "commander": "~2.19.0", - "source-map": "~0.6.1" - }, - "dependencies": { - "commander": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", - "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", - "dev": true - }, - "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 - } - } - }, "unicode-canonical-property-names-ecmascript": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", @@ -19801,15 +14382,15 @@ } }, "unicode-match-property-value-ecmascript": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz", - "integrity": "sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", + "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==", "dev": true }, "unicode-property-aliases-ecmascript": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz", - "integrity": "sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", + "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==", "dev": true }, "union-value": { @@ -19918,12 +14499,6 @@ "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", "dev": true }, - "upper-case": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", - "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", - "dev": true - }, "uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", @@ -19958,26 +14533,14 @@ } }, "url-loader": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-2.1.0.tgz", - "integrity": "sha512-kVrp/8VfEm5fUt+fl2E0FQyrpmOYgMEkBsv8+UDP1wFhszECq5JyGF33I7cajlVY90zRZ6MyfgKXngLvHYZX8A==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-2.3.0.tgz", + "integrity": "sha512-goSdg8VY+7nPZKUEChZSEtW5gjbS66USIGCeSJ1OVOJ7Yfuh/36YxCwMi5HVEJh6mqUYOoy3NJ0vlOMrWsSHog==", "dev": true, "requires": { "loader-utils": "^1.2.3", "mime": "^2.4.4", - "schema-utils": "^2.0.0" - }, - "dependencies": { - "schema-utils": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.6.4.tgz", - "integrity": "sha512-VNjcaUxVnEeun6B2fiiUDjXXBtD4ZSH7pdbfIu1pOFwgptDPLMo/z9jr4sUfsjFVPqDCEin/F7IYlq7/E6yDbQ==", - "dev": true, - "requires": { - "ajv": "^6.10.2", - "ajv-keywords": "^3.4.1" - } - } + "schema-utils": "^2.5.0" } }, "url-parse": { @@ -20050,30 +14613,11 @@ "dev": true }, "v8-compile-cache": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", - "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", + "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==", "dev": true }, - "v8-to-istanbul": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-4.1.4.tgz", - "integrity": "sha512-Rw6vJHj1mbdK8edjR7+zuJrpDtKIgNdAvTSAcpYfgMIw+u2dPDntD3dgN4XQFLU2/fvFQdzj+EeSGfd/jnY5fQ==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^1.6.0", - "source-map": "^0.7.3" - }, - "dependencies": { - "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 - } - } - }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -20114,12 +14658,12 @@ "dev": true }, "w3c-hr-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz", - "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", "dev": true, "requires": { - "browser-process-hrtime": "^0.1.2" + "browser-process-hrtime": "^1.0.0" } }, "w3c-xmlserializer": { @@ -20143,14 +14687,136 @@ } }, "watchpack": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", - "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.4.tgz", + "integrity": "sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg==", "dev": true, "requires": { - "chokidar": "^2.0.2", + "chokidar": "^3.4.1", "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0" + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.0" + }, + "dependencies": { + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "optional": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "binary-extensions": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", + "dev": true, + "optional": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "optional": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "chokidar": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.1.tgz", + "integrity": "sha512-TQTJyr2stihpC4Sya9hs2Xh+O2wf+igjL36Y75xx2WdHuiICcn/XJza46Jwt0eT5hVpQOzo3FpY3cj3RVYLX0g==", + "dev": true, + "optional": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.4.0" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "optional": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "dev": true, + "optional": true + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "optional": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "optional": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "optional": true + }, + "readdirp": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", + "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", + "dev": true, + "optional": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "optional": true, + "requires": { + "is-number": "^7.0.0" + } + } + } + }, + "watchpack-chokidar2": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz", + "integrity": "sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA==", + "dev": true, + "optional": true, + "requires": { + "chokidar": "^2.1.8" } }, "wbuf": { @@ -20169,9 +14835,9 @@ "dev": true }, "webpack": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.0.tgz", - "integrity": "sha512-yNV98U4r7wX1VJAj5kyMsu36T8RPPQntcb5fJLOsMz/pt/WrKC0Vp1bAlqPLkA1LegSwQwf6P+kAbyhRKVQ72g==", + "version": "4.42.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.42.0.tgz", + "integrity": "sha512-EzJRHvwQyBiYrYqhyjW9AqM90dE4+s1/XtCfn7uWg6cS72zH+2VPFAlsnW0+W0cDi0XRjNKUMoJtpSi50+Ph6w==", "dev": true, "requires": { "@webassemblyjs/ast": "1.8.5", @@ -20194,44 +14860,38 @@ "node-libs-browser": "^2.2.1", "schema-utils": "^1.0.0", "tapable": "^1.1.3", - "terser-webpack-plugin": "^1.4.1", + "terser-webpack-plugin": "^1.4.3", "watchpack": "^1.6.0", "webpack-sources": "^1.4.1" }, "dependencies": { "acorn": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz", - "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", + "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", "dev": true }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", "dev": true, "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" } }, "eslint-scope": { @@ -20244,78 +14904,56 @@ "estraverse": "^4.1.1" } }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" } }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "serialize-javascript": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.1.0.tgz", + "integrity": "sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg==", "dev": true, "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "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": { - "is-buffer": "^1.1.5" - } - } + "randombytes": "^2.1.0" } }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "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 + }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", "dev": true, "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" + "figgy-pudding": "^3.5.1" } }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "terser-webpack-plugin": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.4.tgz", + "integrity": "sha512-U4mACBHIegmfoEe5fdongHESNJWqsGU+W0S/9+BmYGVQDw1+c2Ow05TpMhxjPK1sRb7cuYq1BPl1e5YHJMTCqA==", "dev": true, "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^3.1.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" } } } @@ -20334,53 +14972,50 @@ } }, "webpack-dev-server": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.2.1.tgz", - "integrity": "sha512-sjuE4mnmx6JOh9kvSbPYw3u/6uxCLHNWfhWaIPwcXWsvWOPN+nc5baq4i9jui3oOBRXGonK9+OI0jVkaz6/rCw==", + "version": "3.10.3", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.10.3.tgz", + "integrity": "sha512-e4nWev8YzEVNdOMcNzNeCN947sWJNd43E5XvsJzbAL08kGc2frm1tQ32hTJslRS+H65LCb/AaUCYU7fjHCpDeQ==", "dev": true, "requires": { "ansi-html": "0.0.7", "bonjour": "^3.5.0", - "chokidar": "^2.0.0", - "compression": "^1.5.2", - "connect-history-api-fallback": "^1.3.0", + "chokidar": "^2.1.8", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", "debug": "^4.1.1", - "del": "^3.0.0", - "express": "^4.16.2", - "html-entities": "^1.2.0", - "http-proxy-middleware": "^0.19.1", + "del": "^4.1.1", + "express": "^4.17.1", + "html-entities": "^1.2.1", + "http-proxy-middleware": "0.19.1", "import-local": "^2.0.0", - "internal-ip": "^4.2.0", + "internal-ip": "^4.3.0", "ip": "^1.1.5", - "killable": "^1.0.0", - "loglevel": "^1.4.1", - "opn": "^5.1.0", - "portfinder": "^1.0.9", + "is-absolute-url": "^3.0.3", + "killable": "^1.0.1", + "loglevel": "^1.6.6", + "opn": "^5.5.0", + "p-retry": "^3.0.1", + "portfinder": "^1.0.25", "schema-utils": "^1.0.0", - "selfsigned": "^1.9.1", - "semver": "^5.6.0", - "serve-index": "^1.7.2", + "selfsigned": "^1.10.7", + "semver": "^6.3.0", + "serve-index": "^1.9.1", "sockjs": "0.3.19", - "sockjs-client": "1.3.0", - "spdy": "^4.0.0", - "strip-ansi": "^3.0.0", + "sockjs-client": "1.4.0", + "spdy": "^4.0.1", + "strip-ansi": "^3.0.1", "supports-color": "^6.1.0", "url": "^0.11.0", - "webpack-dev-middleware": "^3.5.1", + "webpack-dev-middleware": "^3.7.2", "webpack-log": "^2.0.0", - "yargs": "12.0.2" + "ws": "^6.2.1", + "yargs": "12.0.5" }, "dependencies": { "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true }, "cliui": { @@ -20394,6 +15029,12 @@ "wrap-ansi": "^2.0.0" }, "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -20414,39 +15055,17 @@ "ms": "^2.1.1" } }, - "decamelize": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-2.0.0.tgz", - "integrity": "sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg==", - "dev": true, - "requires": { - "xregexp": "4.0.0" - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, "get-caller-file": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", "dev": true }, - "import-local": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", - "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", - "dev": true, - "requires": { - "pkg-dir": "^3.0.0", - "resolve-cwd": "^2.0.0" - } + "is-absolute-url": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", + "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", + "dev": true }, "is-fullwidth-code-point": { "version": "2.0.0", @@ -20454,85 +15073,34 @@ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, "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 }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "requires": { - "find-up": "^3.0.0" - } - }, "require-main-filename": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", "dev": true }, - "resolve-cwd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", - "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", "dev": true, "requires": { - "resolve-from": "^3.0.0" + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" } }, - "sockjs-client": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.3.0.tgz", - "integrity": "sha512-R9jxEzhnnrdxLCNln0xg5uGHqMnkhPSTzUZH2eXcR03S/On9Yvoq2wyUZILRUhZCNVu2PmwWVoyuiPz8th8zbg==", - "dev": true, - "requires": { - "debug": "^3.2.5", - "eventsource": "^1.0.7", - "faye-websocket": "~0.11.1", - "inherits": "^2.0.3", - "json3": "^3.3.2", - "url-parse": "^1.4.3" - }, - "dependencies": { - "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" - } - } - } + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true }, "string-width": { "version": "2.1.1", @@ -20544,6 +15112,12 @@ "strip-ansi": "^4.0.0" }, "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, "strip-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", @@ -20555,6 +15129,15 @@ } } }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, "supports-color": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", @@ -20596,14 +15179,23 @@ } } }, + "ws": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", + "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + }, "yargs": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.2.tgz", - "integrity": "sha512-e7SkEx6N6SIZ5c5H22RTZae61qtn3PYUE8JYbBFlK9sYmh3DMQ6E5ygtaG/2BW0JZi4WGgTR2IV5ChqlqrDGVQ==", + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", "dev": true, "requires": { "cliui": "^4.0.0", - "decamelize": "^2.0.0", + "decamelize": "^1.2.0", "find-up": "^3.0.0", "get-caller-file": "^1.0.1", "os-locale": "^3.0.0", @@ -20613,16 +15205,17 @@ "string-width": "^2.0.0", "which-module": "^2.0.0", "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^10.1.0" + "yargs-parser": "^11.1.1" } }, "yargs-parser": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", - "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", "dev": true, "requires": { - "camelcase": "^4.1.0" + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } } } @@ -20638,15 +15231,28 @@ } }, "webpack-manifest-plugin": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/webpack-manifest-plugin/-/webpack-manifest-plugin-2.1.1.tgz", - "integrity": "sha512-2zqJ6mvc3yoiqfDjghAIpljhLSDh/G7vqGrzYcYqqRCd/ZZZCAuc/YPE5xG0LGpLgDJRhUNV1H+znyyhIxahzA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/webpack-manifest-plugin/-/webpack-manifest-plugin-2.2.0.tgz", + "integrity": "sha512-9S6YyKKKh/Oz/eryM1RyLVDVmy3NSPV0JXMRhZ18fJsq+AwGxUY34X54VNwkzYcEmEkDwNxuEOboCZEebJXBAQ==", "dev": true, "requires": { "fs-extra": "^7.0.0", "lodash": ">=3.5 <5", "object.entries": "^1.1.0", "tapable": "^1.0.0" + }, + "dependencies": { + "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" + } + } } }, "webpack-sources": { @@ -20668,20 +15274,20 @@ } }, "websocket-driver": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.3.tgz", - "integrity": "sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg==", + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", "dev": true, "requires": { - "http-parser-js": ">=0.4.0 <0.4.11", + "http-parser-js": ">=0.5.1", "safe-buffer": ">=5.1.0", "websocket-extensions": ">=0.1.1" } }, "websocket-extensions": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", - "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", "dev": true }, "whatwg-encoding": { @@ -20694,9 +15300,9 @@ } }, "whatwg-fetch": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", - "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.3.1.tgz", + "integrity": "sha512-faXTmGDcLuEPBpJwb5LQfyxvubKiE+RlbmmweFGKjvIPFj4uHTTfdtTIkdTRhC6OSH9S9eyYbx8kZ0UEaQqYTA==", "dev": true }, "whatwg-mimetype": { @@ -20706,9 +15312,9 @@ "dev": true }, "whatwg-url": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", - "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", + "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", "dev": true, "requires": { "lodash.sortby": "^4.7.0", @@ -20934,54 +15540,37 @@ } }, "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", "dev": true, "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" }, "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", "dev": true, "requires": { - "ansi-regex": "^5.0.0" + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" } } } @@ -21002,22 +15591,24 @@ } }, "write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.1.tgz", + "integrity": "sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==", "dev": true, "requires": { + "graceful-fs": "^4.1.11", "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" + "signal-exit": "^3.0.2" } }, "ws": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.0.tgz", - "integrity": "sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w==", - "dev": true + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-5.2.2.tgz", + "integrity": "sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } }, "xml-name-validator": { "version": "3.0.0", @@ -21032,10 +15623,13 @@ "dev": true }, "xregexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz", - "integrity": "sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==", - "dev": true + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.3.0.tgz", + "integrity": "sha512-7jXDIFXh5yJ/orPn4SXjuVrWWoi4Cr8jfV1eHv9CixKSbU+jY4mxfrBwAuDvupPNKpMUY+FeIqsVw/JLT9+B8g==", + "dev": true, + "requires": { + "@babel/runtime-corejs3": "^7.8.3" + } }, "xtend": { "version": "4.0.2", @@ -21050,34 +15644,64 @@ "dev": true }, "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yaml": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz", + "integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==", "dev": true }, "yargs": { - "version": "15.3.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz", - "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==", + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", "dev": true, "requires": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", + "cliui": "^5.0.0", + "find-up": "^3.0.0", "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", - "string-width": "^4.2.0", + "string-width": "^3.0.0", "which-module": "^2.0.0", "y18n": "^4.0.0", - "yargs-parser": "^18.1.1" + "yargs-parser": "^13.1.2" + }, + "dependencies": { + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + } } }, "yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", "dev": true, "requires": { "camelcase": "^5.0.0", diff --git a/e2e/test/jest-react/package.json b/e2e/test/jest-react/package.json index 7e2d40b9a9..df5a044f11 100644 --- a/e2e/test/jest-react/package.json +++ b/e2e/test/jest-react/package.json @@ -12,7 +12,7 @@ "sideEffects": false, "scripts": { "report-coverage": "coveralls < ./coverage/lcov.info", - "test-original": "cross-env BABEL_ENV=test react-scripts test --env=jsdom", + "test-original": "cross-env SKIP_PREFLIGHT_CHECK=true BABEL_ENV=test react-scripts test --env=jsdom", "test": "stryker run", "posttest": "mocha --require ../../tasks/ts-node-register.js verify/*.ts", "cover": "npm test -- --coverage", @@ -52,30 +52,33 @@ }, "homepage": "https://github.com/reactstrap/reactstrap#readme", "dependencies": { - "react": "~16.11.0", - "react-dom": "~16.11.0", + "react": "~16.13.1", + "react-dom": "~16.13.1", "classnames": "~2.2.6", "prop-types": "~15.7.2", - "react-transition-group": "~4.3.0" + "react-transition-group": "~4.4.1" }, "peerDependencies": { - "react": "^16.0.0", - "react-dom": "^16.0.0" + "react": "~16.13.1", + "react-dom": "~16.13.1" }, "devDependencies": { - "babel-plugin-transform-object-rest-spread": "~6.26.0", - "babel-preset-es2015-rollup": "~3.0.0", - "babel-preset-react": "~6.24.1", - "babel-preset-react-app": "~9.0.2", - "enzyme": "~3.10.0", - "enzyme-adapter-react-16": "~1.15.1", - "jest": "^26.0.1", - "react-scripts": "~3.2.0" + "@babel/cli": "~7.10.5", + "@babel/core": "~7.11.4", + "@babel/plugin-proposal-export-default-from": "~7.10.4", + "@babel/plugin-proposal-export-namespace-from": "~7.10.4", + "@babel/plugin-proposal-object-rest-spread": "~7.11.0", + "@babel/plugin-transform-runtime": "~7.11.0", + "@babel/preset-env": "~7.11.0", + "@babel/preset-react": "~7.10.4", + "enzyme": "~3.11.0", + "enzyme-adapter-react-16": "~1.15.2", + "react-scripts": "~3.4.1" }, "localDependencies": { "@stryker-mutator/api": "../../../packages/api", "@stryker-mutator/core": "../../../packages/core", - "@stryker-mutator/javascript-mutator": "../../../packages/javascript-mutator", + "@stryker-mutator/instrumenter": "../../../packages/instrumenter", "@stryker-mutator/jest-runner": "../../../packages/jest-runner", "@stryker-mutator/util": "../../../packages/util" } diff --git a/e2e/test/jest-react/stryker.conf.js b/e2e/test/jest-react/stryker.conf.js index 8df701c6e6..ec44b79df5 100644 --- a/e2e/test/jest-react/stryker.conf.js +++ b/e2e/test/jest-react/stryker.conf.js @@ -1,14 +1,12 @@ module.exports = function (config) { config.set({ testRunner: "jest", - mutator: "javascript", - transpilers: [], - reporters: ["event-recorder"], + reporters: ["event-recorder", "html", "progress", "clear-text"], tempDirName: "stryker-tmp", coverageAnalysis: "off", timeoutMS: 60000, // High timeout to survive high build server load. Mutants created here should never timeout mutate: ["src/{Alert,Badge,Breadcrumb}.js"], - maxConcurrentTestRunners: 2, + concurrency: 2, jest: { projectType: 'create-react-app' } diff --git a/e2e/test/jest-react/verify/verify.ts b/e2e/test/jest-react/verify/verify.ts index be03714c76..e74281d443 100644 --- a/e2e/test/jest-react/verify/verify.ts +++ b/e2e/test/jest-react/verify/verify.ts @@ -4,22 +4,22 @@ describe('After running stryker on jest-react project', () => { it('should report expected scores', async () => { await expectMetricsResult({ metrics: produceMetrics({ - killed: 34, - mutationScore: 64.15, - mutationScoreBasedOnCoveredCode: 64.15, - survived: 19, - totalCovered: 53, - totalDetected: 34, - totalMutants: 53, - totalUndetected: 19, - totalValid: 53 + killed: 33, + timeout: 0, + mutationScore: 67.35, + mutationScoreBasedOnCoveredCode: 67.35, + survived: 16, + totalCovered: 49, + totalDetected: 33, + totalMutants: 49, + totalUndetected: 16, + totalValid: 49 }), }); /* - ---------------|---------|----------|-----------|------------|----------|---------| - File | % score | # killed | # timeout | # survived | # no cov | # error | - ---------------|---------|----------|-----------|------------|----------|---------| - All files | 64.15 | 34 | 0 | 19 | 0 | 0 | - ---------------|---------|----------|-----------|------------|----------|---------|*/ + ---------------|---------|----------|-----------|------------|----------|---------| + File | % score | # killed | # timeout | # survived | # no cov | # error | + ---------------|---------|----------|-----------|------------|----------|---------| + All files | 67.35 | 33 | 0 | 16 | 0 | 0 |*/ }); }); diff --git a/e2e/test/jest-with-ts/package-lock.json b/e2e/test/jest-with-ts/package-lock.json index 63bbf16f22..6605b91632 100644 --- a/e2e/test/jest-with-ts/package-lock.json +++ b/e2e/test/jest-with-ts/package-lock.json @@ -56,6 +56,12 @@ "pretty-format": "^25.2.1" } }, + "@types/node": { + "version": "14.0.27", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.27.tgz", + "integrity": "sha512-kVrqXhbclHNHGu9ztnAwSncIgJv/FaxmzXJvGXNdcCpV1b8u1/Mi6z6m0vwy0LzKeXFTPLH0NzwmoJ3fNCIq0g==", + "dev": true + }, "@types/yargs": { "version": "15.0.4", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.4.tgz", diff --git a/e2e/test/jest-with-ts/package.json b/e2e/test/jest-with-ts/package.json index e987db70fb..7330158540 100644 --- a/e2e/test/jest-with-ts/package.json +++ b/e2e/test/jest-with-ts/package.json @@ -3,12 +3,14 @@ "description": "A test project for using stryker with jest and jest-ts preprocessor. Inspired by the stryker-dashboard source code.", "scripts": { "test": "stryker run", + "test:original": "jest", "posttest": "mocha --require ../../tasks/ts-node-register.js verify/verify.ts" }, "dependencies": { - "azure-storage": "^2.10.3" + "azure-storage": "~2.10.3" }, "devDependencies": { - "@types/jest": "^25.2.1" + "@types/jest": "~25.2.1", + "@types/node": "^14.0.27" } } diff --git a/e2e/test/jest-with-ts/stryker.conf.json b/e2e/test/jest-with-ts/stryker.conf.json index 9587004662..e4b0c67d86 100644 --- a/e2e/test/jest-with-ts/stryker.conf.json +++ b/e2e/test/jest-with-ts/stryker.conf.json @@ -1,16 +1,19 @@ { - "$schema": "https://raw.githubusercontent.com/stryker-mutator/stryker/master/packages/api/schema/stryker-core.json", - "mutator": "typescript", + "$schema": "../../node_modules/@stryker-mutator/core/schema/stryker-schema.json", "mutate": [ "src/data-access/mappers/TableStorageMapper.ts" ], "packageManager": "npm", "testRunner": "jest", "tempDirName": "stryker-tmp", - "transpilers": [], - "maxConcurrentTestRunners": 2, + "concurrency": 2, + "checkers": [ + "typescript" + ], "coverageAnalysis": "off", "reporters": [ - "event-recorder" + "event-recorder", + "progress", + "html" ] } diff --git a/e2e/test/jest-with-ts/tsconfig.json b/e2e/test/jest-with-ts/tsconfig.json index 69ba96b8c4..a4596e57f1 100644 --- a/e2e/test/jest-with-ts/tsconfig.json +++ b/e2e/test/jest-with-ts/tsconfig.json @@ -2,11 +2,13 @@ "compilerOptions": { "target": "es2017", "esModuleInterop": true, + "module": "commonjs", "lib": [ "es2017" ], "types": [ - "jest" + "jest", + "node" ], "strict": true, "typeRoots": [ @@ -14,6 +16,10 @@ ], "outDir": "dist" }, + "include": [ + "src", + "test" + ], // Example pulled from: https://kulshekhar.github.io/ts-jest/user/config/#example "paths": { "@App/*": [ diff --git a/e2e/test/jest-with-ts/verify/verify.ts b/e2e/test/jest-with-ts/verify/verify.ts index c30431acf9..2f9627c016 100644 --- a/e2e/test/jest-with-ts/verify/verify.ts +++ b/e2e/test/jest-with-ts/verify/verify.ts @@ -5,12 +5,12 @@ describe('Verify stryker has ran correctly', () => { it('should report correct score', async () => { await expectMetrics({ ignored: 0, - killed: 12, - mutationScore: 54.55, + killed: 15, + mutationScore: 53.57, noCoverage: 0, - survived: 10, + survived: 13, timeout: 0, - runtimeErrors: 32 + compileErrors: 32 }); }); }); diff --git a/e2e/test/karma-jasmine/stryker.conf.js b/e2e/test/karma-jasmine/stryker.conf.js index f52235eaec..3fb1ecd79d 100644 --- a/e2e/test/karma-jasmine/stryker.conf.js +++ b/e2e/test/karma-jasmine/stryker.conf.js @@ -1,10 +1,9 @@ module.exports = function (config) { config.set({ mutate: ['src/*.js'], - testFramework: 'jasmine', testRunner: 'karma', reporters: ['clear-text', 'html', 'event-recorder'], - maxConcurrentTestRunners: 2, + concurrency: 2, karma: { config: { files: ['src/*.js', 'test/*.js'], @@ -13,7 +12,6 @@ module.exports = function (config) { } } }, - timeoutMS: 60000, - mutator: 'javascript' + timeoutMS: 60000 }); }; diff --git a/e2e/test/karma-mocha/stryker.conf.js b/e2e/test/karma-mocha/stryker.conf.js index 02f4815159..9b998037b8 100644 --- a/e2e/test/karma-mocha/stryker.conf.js +++ b/e2e/test/karma-mocha/stryker.conf.js @@ -1,8 +1,6 @@ module.exports = function (config) { config.set({ mutate: ['src/*.js'], - mutator: 'javascript', - testFramework: 'mocha', testRunner: 'karma', reporters: ['clear-text', 'html', 'event-recorder'], karma: { @@ -12,7 +10,8 @@ module.exports = function (config) { } }, timeoutMS: 60000, - maxConcurrentTestRunners: 2, - coverageAnalysis: 'perTest' + concurrency: 2, + coverageAnalysis: 'perTest', + plugins: ['@stryker-mutator/karma-runner'] }); }; diff --git a/e2e/test/karma-mocha/verify/verify.ts b/e2e/test/karma-mocha/verify/verify.ts index f9dc92bed2..a2f43f76e4 100644 --- a/e2e/test/karma-mocha/verify/verify.ts +++ b/e2e/test/karma-mocha/verify/verify.ts @@ -7,10 +7,10 @@ describe('Verify stryker has ran correctly', () => { metrics: produceMetrics({ killed: 16, mutationScore: 64, - mutationScoreBasedOnCoveredCode: 84.21, - noCoverage: 6, - survived: 3, - totalCovered: 19, + mutationScoreBasedOnCoveredCode: 94.12, + noCoverage: 8, + survived: 1, + totalCovered: 17, totalDetected: 16, totalMutants: 25, totalUndetected: 9, diff --git a/e2e/test/karma-webpack-with-ts/debug.log b/e2e/test/karma-webpack-with-ts/debug.log deleted file mode 100644 index 3819b2e5e2..0000000000 --- a/e2e/test/karma-webpack-with-ts/debug.log +++ /dev/null @@ -1,3 +0,0 @@ -[0508/111601.854:ERROR:process_reader_win.cc(108)] process 23872 not found -[0508/111601.855:ERROR:exception_snapshot_win.cc(98)] thread ID 27616 not found in process -[0508/111601.855:ERROR:scoped_process_suspend.cc(40)] NtResumeProcess: An attempt was made to access an exiting process. (0xc000010a) diff --git a/e2e/test/karma-webpack-with-ts/dist-test/tsconfig.tsbuildinfo b/e2e/test/karma-webpack-with-ts/dist-test/tsconfig.tsbuildinfo deleted file mode 100644 index 9323a67292..0000000000 --- a/e2e/test/karma-webpack-with-ts/dist-test/tsconfig.tsbuildinfo +++ /dev/null @@ -1,542 +0,0 @@ -{ - "program": { - "fileInfos": { - "../../../node_modules/typescript/lib/lib.es6.d.ts": { - "version": "c180f01a2aaac7d733001fa1db20f881dc83cf33096b674a1546ca26762e69da", - "signature": "c180f01a2aaac7d733001fa1db20f881dc83cf33096b674a1546ca26762e69da" - }, - "../../../node_modules/typescript/lib/lib.es5.d.ts": { - "version": "fc43680ad3a1a4ec8c7b8d908af1ec9ddff87845346de5f02c735c9171fa98ea", - "signature": "fc43680ad3a1a4ec8c7b8d908af1ec9ddff87845346de5f02c735c9171fa98ea" - }, - "../../../node_modules/typescript/lib/lib.es2015.d.ts": { - "version": "7994d44005046d1413ea31d046577cdda33b8b2470f30281fd9c8b3c99fe2d96", - "signature": "7994d44005046d1413ea31d046577cdda33b8b2470f30281fd9c8b3c99fe2d96" - }, - "../../../node_modules/typescript/lib/lib.dom.d.ts": { - "version": "d93de5e8a7275cb9d47481410e13b3b1debb997e216490954b5d106e37e086de", - "signature": "d93de5e8a7275cb9d47481410e13b3b1debb997e216490954b5d106e37e086de" - }, - "../../../node_modules/typescript/lib/lib.dom.iterable.d.ts": { - "version": "8329c3401aa8708426c7760f14219170f69a2cb77e4519758cec6f5027270faf", - "signature": "8329c3401aa8708426c7760f14219170f69a2cb77e4519758cec6f5027270faf" - }, - "../../../node_modules/typescript/lib/lib.webworker.importscripts.d.ts": { - "version": "fe4e59403e34c7ff747abe4ff6abbc7718229556d7c1a5b93473fb53156c913b", - "signature": "fe4e59403e34c7ff747abe4ff6abbc7718229556d7c1a5b93473fb53156c913b" - }, - "../../../node_modules/typescript/lib/lib.scripthost.d.ts": { - "version": "b9faa17292f17d2ad75e34fac77dd63a6403af1dba02d39cd0cbb9ffdf3de8b9", - "signature": "b9faa17292f17d2ad75e34fac77dd63a6403af1dba02d39cd0cbb9ffdf3de8b9" - }, - "../../../node_modules/typescript/lib/lib.es2015.core.d.ts": { - "version": "734ddc145e147fbcd55f07d034f50ccff1086f5a880107665ec326fb368876f6", - "signature": "734ddc145e147fbcd55f07d034f50ccff1086f5a880107665ec326fb368876f6" - }, - "../../../node_modules/typescript/lib/lib.es2015.collection.d.ts": { - "version": "4a0862a21f4700de873db3b916f70e41570e2f558da77d2087c9490f5a0615d8", - "signature": "4a0862a21f4700de873db3b916f70e41570e2f558da77d2087c9490f5a0615d8" - }, - "../../../node_modules/typescript/lib/lib.es2015.generator.d.ts": { - "version": "765e0e9c9d74cf4d031ca8b0bdb269a853e7d81eda6354c8510218d03db12122", - "signature": "765e0e9c9d74cf4d031ca8b0bdb269a853e7d81eda6354c8510218d03db12122" - }, - "../../../node_modules/typescript/lib/lib.es2015.iterable.d.ts": { - "version": "285958e7699f1babd76d595830207f18d719662a0c30fac7baca7df7162a9210", - "signature": "285958e7699f1babd76d595830207f18d719662a0c30fac7baca7df7162a9210" - }, - "../../../node_modules/typescript/lib/lib.es2015.promise.d.ts": { - "version": "d4deaafbb18680e3143e8b471acd650ed6f72a408a33137f0a0dd104fbe7f8ca", - "signature": "d4deaafbb18680e3143e8b471acd650ed6f72a408a33137f0a0dd104fbe7f8ca" - }, - "../../../node_modules/typescript/lib/lib.es2015.proxy.d.ts": { - "version": "5e72f949a89717db444e3bd9433468890068bb21a5638d8ab15a1359e05e54fe", - "signature": "5e72f949a89717db444e3bd9433468890068bb21a5638d8ab15a1359e05e54fe" - }, - "../../../node_modules/typescript/lib/lib.es2015.reflect.d.ts": { - "version": "f5b242136ae9bfb1cc99a5971cccc44e99947ae6b5ef6fd8aa54b5ade553b976", - "signature": "f5b242136ae9bfb1cc99a5971cccc44e99947ae6b5ef6fd8aa54b5ade553b976" - }, - "../../../node_modules/typescript/lib/lib.es2015.symbol.d.ts": { - "version": "9ae2860252d6b5f16e2026d8a2c2069db7b2a3295e98b6031d01337b96437230", - "signature": "9ae2860252d6b5f16e2026d8a2c2069db7b2a3295e98b6031d01337b96437230" - }, - "../../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts": { - "version": "3e0a459888f32b42138d5a39f706ff2d55d500ab1031e0988b5568b0f67c2303", - "signature": "3e0a459888f32b42138d5a39f706ff2d55d500ab1031e0988b5568b0f67c2303" - }, - "../node_modules/lit-html/ts3.4/lib/part.d.ts": { - "version": "253da37de7cfd359a21d78dfc11d480ff0abc851c4462c062c0152b08b2add8e", - "signature": "253da37de7cfd359a21d78dfc11d480ff0abc851c4462c062c0152b08b2add8e" - }, - "../node_modules/lit-html/ts3.4/lib/parts.d.ts": { - "version": "8abe19ac9fcee791ac64f4ced6b03f97e3aa3d3c5874f04af8f67a9c3c39d93e", - "signature": "8abe19ac9fcee791ac64f4ced6b03f97e3aa3d3c5874f04af8f67a9c3c39d93e" - }, - "../node_modules/lit-html/ts3.4/lib/template-processor.d.ts": { - "version": "64478db38bbf920d40129431b3d97032253a80bb6cb4183b5497832f8b9e4c7f", - "signature": "64478db38bbf920d40129431b3d97032253a80bb6cb4183b5497832f8b9e4c7f" - }, - "../node_modules/lit-html/ts3.4/lib/template-result.d.ts": { - "version": "cda7233c05b316c43ca4764038a1fb5fb61e0326696173b24bd4d8af8ab415be", - "signature": "cda7233c05b316c43ca4764038a1fb5fb61e0326696173b24bd4d8af8ab415be" - }, - "../node_modules/lit-html/ts3.4/lib/template.d.ts": { - "version": "536402bb8add0a08da6e51ea949412d589942e43a17243e830c95a8022001d58", - "signature": "536402bb8add0a08da6e51ea949412d589942e43a17243e830c95a8022001d58" - }, - "../node_modules/lit-html/ts3.4/lib/template-factory.d.ts": { - "version": "6a486a955ebdf00bbd7f5c155ea1baadb7d3d3914874c456e6a980b7386f6faa", - "signature": "6a486a955ebdf00bbd7f5c155ea1baadb7d3d3914874c456e6a980b7386f6faa" - }, - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts": { - "version": "cc35948605b99c6f32158e69ab1351943e9f305b249af966f7915f6e5abad628", - "signature": "cc35948605b99c6f32158e69ab1351943e9f305b249af966f7915f6e5abad628" - }, - "../node_modules/lit-html/ts3.4/lib/default-template-processor.d.ts": { - "version": "2bb52f7489d930c01dad30a5e32302327302c2dd248e80bc92c9aa48ee8d77c3", - "signature": "2bb52f7489d930c01dad30a5e32302327302c2dd248e80bc92c9aa48ee8d77c3" - }, - "../node_modules/lit-html/ts3.4/lib/directive.d.ts": { - "version": "c60770b91d363b3b14e5a3660e86a363c22800f4b424dfc080ec3975c0c3f78a", - "signature": "c60770b91d363b3b14e5a3660e86a363c22800f4b424dfc080ec3975c0c3f78a" - }, - "../node_modules/lit-html/ts3.4/lib/dom.d.ts": { - "version": "64ce958a702725d89f8c099eeeb8936b3584ea07d1e6ae5187a20a622cf72e94", - "signature": "64ce958a702725d89f8c099eeeb8936b3584ea07d1e6ae5187a20a622cf72e94" - }, - "../node_modules/lit-html/ts3.4/lib/render.d.ts": { - "version": "8c5703f69c2eb261df1f65dc65e84a6ec2d74187bf1dda5e46370adb41d01dd7", - "signature": "8c5703f69c2eb261df1f65dc65e84a6ec2d74187bf1dda5e46370adb41d01dd7" - }, - "../node_modules/lit-html/ts3.4/lib/template-instance.d.ts": { - "version": "d6ec7edc88bb1932615982f19049f4de5b96d7d48cb39557ca82ae1b571d0b55", - "signature": "d6ec7edc88bb1932615982f19049f4de5b96d7d48cb39557ca82ae1b571d0b55" - }, - "../node_modules/lit-html/ts3.4/lit-html.d.ts": { - "version": "410146f72ecc0811e9374ca7ad586b1c81993a32fbd2646245a5f81a45c533fd", - "signature": "410146f72ecc0811e9374ca7ad586b1c81993a32fbd2646245a5f81a45c533fd" - }, - "../node_modules/lit-html/ts3.4/lib/shady-render.d.ts": { - "version": "119731ffdb51d2062a80e60f0009109f27799b12b30f682a5d21fe5d8177d015", - "signature": "119731ffdb51d2062a80e60f0009109f27799b12b30f682a5d21fe5d8177d015" - }, - "../node_modules/lit-element/ts3.4/lib/updating-element.d.ts": { - "version": "1232e7e6b55f64fb09486987cb4aae2d511facc89190916a3077e5196a63d800", - "signature": "1232e7e6b55f64fb09486987cb4aae2d511facc89190916a3077e5196a63d800" - }, - "../node_modules/lit-element/ts3.4/lib/decorators.d.ts": { - "version": "18a2ea2cbd19957f6f593e300f9e1cc5157d302eef6a6902447d30daee3bd8a2", - "signature": "18a2ea2cbd19957f6f593e300f9e1cc5157d302eef6a6902447d30daee3bd8a2" - }, - "../node_modules/lit-element/ts3.4/lib/css-tag.d.ts": { - "version": "4ff2d5ca3abc6ebc0339dd03dfd1ffbe3943c02ea318f9a538c3f3cee2139c24", - "signature": "4ff2d5ca3abc6ebc0339dd03dfd1ffbe3943c02ea318f9a538c3f3cee2139c24" - }, - "../node_modules/lit-element/ts3.4/lit-element.d.ts": { - "version": "0029a8eaa03227915b62bcc8d1e7bf418b3c7ee70225413b67754c870fbf483b", - "signature": "0029a8eaa03227915b62bcc8d1e7bf418b3c7ee70225413b67754c870fbf483b" - }, - "../node_modules/mutation-testing-report-schema/dist/src/api/location.d.ts": { - "version": "c9632b53d68031c62cd80928e33c1c5a3dbd12a887f0a4dc93a63938f29b33f7", - "signature": "c9632b53d68031c62cd80928e33c1c5a3dbd12a887f0a4dc93a63938f29b33f7" - }, - "../node_modules/mutation-testing-report-schema/dist/src/api/mutantresult.d.ts": { - "version": "2b15980867f95cbb691e249b61edae74363bcf5b0b51602c871ce4de93874e51", - "signature": "2b15980867f95cbb691e249b61edae74363bcf5b0b51602c871ce4de93874e51" - }, - "../node_modules/mutation-testing-report-schema/dist/src/api/fileresult.d.ts": { - "version": "9b33b5614147e3b6abc8121781885fd09c293b3baa9008442d61a7a2ac2bc34b", - "signature": "9b33b5614147e3b6abc8121781885fd09c293b3baa9008442d61a7a2ac2bc34b" - }, - "../node_modules/mutation-testing-report-schema/dist/src/api/thresholds.d.ts": { - "version": "0844ea97fc6b9609db75d7efb557f4a43ec7ad5d6854cd9af8c14eaed3ff348f", - "signature": "0844ea97fc6b9609db75d7efb557f4a43ec7ad5d6854cd9af8c14eaed3ff348f" - }, - "../node_modules/mutation-testing-report-schema/dist/src/api/mutationtestresult.d.ts": { - "version": "ba246fb4e9a23e77b31420aace00352b0db3f497d4d8f9290b45d881328ea575", - "signature": "ba246fb4e9a23e77b31420aace00352b0db3f497d4d8f9290b45d881328ea575" - }, - "../node_modules/mutation-testing-report-schema/dist/src/api/index.d.ts": { - "version": "753930e76d5db961b7e5539425d29301be82cf1b964da70d402dd8f7bf3c39b2", - "signature": "753930e76d5db961b7e5539425d29301be82cf1b964da70d402dd8f7bf3c39b2" - }, - "../node_modules/mutation-testing-report-schema/dist/src/index.d.ts": { - "version": "2f63fb9896c604a7c597b5777f39197779e3fd34276c2d56e43e85d159fdd1ad", - "signature": "2f63fb9896c604a7c597b5777f39197779e3fd34276c2d56e43e85d159fdd1ad" - }, - "../node_modules/mutation-testing-metrics/dist/src/api/metrics.d.ts": { - "version": "ed0d126575449c142f09eef7111b9d03354b1e5c4a26b6da7dc0401eef4608ba", - "signature": "ed0d126575449c142f09eef7111b9d03354b1e5c4a26b6da7dc0401eef4608ba" - }, - "../node_modules/mutation-testing-metrics/dist/src/api/metricsresult.d.ts": { - "version": "b188d1930c1461fc91d3627ebaad93e42cfc5715911810881b2ea38d9d876d41", - "signature": "b188d1930c1461fc91d3627ebaad93e42cfc5715911810881b2ea38d9d876d41" - }, - "../node_modules/mutation-testing-metrics/dist/src/calculatemetrics.d.ts": { - "version": "c0527d28327d523b9dee1907a39d123ae3018c8017c223debc4db6556fd14164", - "signature": "c0527d28327d523b9dee1907a39d123ae3018c8017c223debc4db6556fd14164" - }, - "../node_modules/mutation-testing-metrics/dist/src/helpers.d.ts": { - "version": "35bda36c3124dd5c129e2d4e10d4baa431a6ebcd8e22e8df2714f4c39b35030a", - "signature": "35bda36c3124dd5c129e2d4e10d4baa431a6ebcd8e22e8df2714f4c39b35030a" - }, - "../node_modules/mutation-testing-metrics/dist/src/index.d.ts": { - "version": "af12a458eb853611938075ca246b87ef9b4622386bede3b96ace1cb73bafb8f3", - "signature": "af12a458eb853611938075ca246b87ef9b4622386bede3b96ace1cb73bafb8f3" - }, - "../src/components/mutation-test-totals.ts": { - "version": "53ba94396e0ef5f4af4c5fc9f4808e5a961cd1488853a671389b6fe01240b96f", - "signature": "53ba94396e0ef5f4af4c5fc9f4808e5a961cd1488853a671389b6fe01240b96f" - }, - "../test/unit/helpers/customelementfixture.ts": { - "version": "a602fb0422f1067c55d2b9f5dbe10ebdfd97cdf879f1ac150152f32fef6639bf", - "signature": "fcea809ccfacd271ec12408270ad0209e86a4498829e3a2464572cbb4ea03cbc" - }, - "../../../../node_modules/@types/chai/index.d.ts": { - "version": "1df845885d8bd29132f67f47b7a64ec35f4b83962274ee9fb38ae40a82305a72", - "signature": "1df845885d8bd29132f67f47b7a64ec35f4b83962274ee9fb38ae40a82305a72" - }, - "../test/unit/helpers/factory.ts": { - "version": "24ef1ad3dd6b763987043799ae37a7a4f7f6c1d7fc6447ed0aa39b2d15b476d9", - "signature": "1cf6a128f71fbdf0d9c5b947ab4ae50351ae4fe227e82ae4740eacc07868056e" - }, - "../test/unit/components/mutation-test-totals.spec.ts": { - "version": "dae1f7fa971d29f9a3b3bc5091517c08d75957bb252358dab1749d452584e6b8", - "signature": "fb59e3637fe6764eabaeb33a369f1cc7cdfe70ad13fc6c6cc368a4a08f53220f" - }, - "../../../../node_modules/@types/mocha/index.d.ts": { - "version": "f24768499dab9a34c0aff9c9e3fbfe5117001bfabba4a1db01a17df086d6a606", - "signature": "f24768499dab9a34c0aff9c9e3fbfe5117001bfabba4a1db01a17df086d6a606" - }, - "../node_modules/@types/webpack-env/index.d.ts": { - "version": "1db2b55f2381ed9558f93cbf4068096d72e1c8d59bb3a66aafa0fc11c1f17530", - "signature": "1db2b55f2381ed9558f93cbf4068096d72e1c8d59bb3a66aafa0fc11c1f17530" - } - }, - "options": { - "target": 2, - "module": 1, - "strict": true, - "composite": true, - "declaration": true, - "declarationMap": true, - "esModuleInterop": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - "forceConsistentCasingInFileNames": true, - "experimentalDecorators": true, - "sourceMap": true, - "types": [ - "mocha", - "webpack-env" - ], - "outDir": "./", - "configFilePath": "../test/tsconfig.json" - }, - "referencedMap": { - "../node_modules/lit-html/ts3.4/lib/parts.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/part.d.ts", - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/template-processor.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/part.d.ts", - "../node_modules/lit-html/ts3.4/lib/parts.d.ts", - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/template-result.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/template-processor.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/template.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/template-result.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/template-factory.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/template-result.d.ts", - "../node_modules/lit-html/ts3.4/lib/template.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/template-factory.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/default-template-processor.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/part.d.ts", - "../node_modules/lit-html/ts3.4/lib/parts.d.ts", - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts", - "../node_modules/lit-html/ts3.4/lib/template-processor.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/directive.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/part.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/render.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/parts.d.ts", - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/template-instance.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts", - "../node_modules/lit-html/ts3.4/lib/template-processor.d.ts", - "../node_modules/lit-html/ts3.4/lib/template.d.ts" - ], - "../node_modules/lit-html/ts3.4/lit-html.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/template-result.d.ts", - "../node_modules/lit-html/ts3.4/lib/default-template-processor.d.ts", - "../node_modules/lit-html/ts3.4/lib/directive.d.ts", - "../node_modules/lit-html/ts3.4/lib/dom.d.ts", - "../node_modules/lit-html/ts3.4/lib/part.d.ts", - "../node_modules/lit-html/ts3.4/lib/parts.d.ts", - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts", - "../node_modules/lit-html/ts3.4/lib/render.d.ts", - "../node_modules/lit-html/ts3.4/lib/template-factory.d.ts", - "../node_modules/lit-html/ts3.4/lib/template-instance.d.ts", - "../node_modules/lit-html/ts3.4/lib/template-processor.d.ts", - "../node_modules/lit-html/ts3.4/lib/template.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/shady-render.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts", - "../node_modules/lit-html/ts3.4/lit-html.d.ts" - ], - "../node_modules/lit-element/ts3.4/lib/decorators.d.ts": [ - "../node_modules/lit-element/ts3.4/lib/updating-element.d.ts" - ], - "../node_modules/lit-element/ts3.4/lit-element.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/shady-render.d.ts", - "../node_modules/lit-element/ts3.4/lib/updating-element.d.ts", - "../node_modules/lit-element/ts3.4/lib/decorators.d.ts", - "../node_modules/lit-html/ts3.4/lit-html.d.ts", - "../node_modules/lit-element/ts3.4/lib/css-tag.d.ts" - ], - "../node_modules/mutation-testing-report-schema/dist/src/api/mutantresult.d.ts": [ - "../node_modules/mutation-testing-report-schema/dist/src/api/location.d.ts" - ], - "../node_modules/mutation-testing-report-schema/dist/src/api/fileresult.d.ts": [ - "../node_modules/mutation-testing-report-schema/dist/src/api/mutantresult.d.ts" - ], - "../node_modules/mutation-testing-report-schema/dist/src/api/mutationtestresult.d.ts": [ - "../node_modules/mutation-testing-report-schema/dist/src/api/fileresult.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/thresholds.d.ts" - ], - "../node_modules/mutation-testing-report-schema/dist/src/api/index.d.ts": [ - "../node_modules/mutation-testing-report-schema/dist/src/api/fileresult.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/location.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/mutantresult.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/mutationtestresult.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/thresholds.d.ts" - ], - "../node_modules/mutation-testing-report-schema/dist/src/index.d.ts": [ - "../node_modules/mutation-testing-report-schema/dist/src/api/index.d.ts" - ], - "../node_modules/mutation-testing-metrics/dist/src/api/metricsresult.d.ts": [ - "../node_modules/mutation-testing-report-schema/dist/src/index.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/api/metrics.d.ts" - ], - "../node_modules/mutation-testing-metrics/dist/src/calculatemetrics.d.ts": [ - "../node_modules/mutation-testing-report-schema/dist/src/index.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/api/metricsresult.d.ts" - ], - "../node_modules/mutation-testing-metrics/dist/src/helpers.d.ts": [ - "../node_modules/mutation-testing-metrics/dist/src/api/metricsresult.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/index.d.ts" - ], - "../node_modules/mutation-testing-metrics/dist/src/index.d.ts": [ - "../node_modules/mutation-testing-metrics/dist/src/api/metricsresult.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/api/metrics.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/calculatemetrics.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/helpers.d.ts" - ], - "../src/components/mutation-test-totals.ts": [ - "../node_modules/lit-element/ts3.4/lit-element.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/index.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/index.d.ts" - ], - "../test/unit/helpers/customelementfixture.ts": [ - "../node_modules/lit-element/ts3.4/lit-element.d.ts" - ], - "../test/unit/helpers/factory.ts": [ - "../node_modules/mutation-testing-report-schema/dist/src/index.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/index.d.ts" - ], - "../test/unit/components/mutation-test-totals.spec.ts": [ - "../dist/components/mutation-test-totals.d.ts", - "../test/unit/helpers/customelementfixture.ts", - "../../../../node_modules/@types/chai/index.d.ts", - "../test/unit/helpers/factory.ts" - ] - }, - "exportedModulesMap": { - "../node_modules/lit-html/ts3.4/lit-html.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/template-result.d.ts", - "../node_modules/lit-html/ts3.4/lib/default-template-processor.d.ts", - "../node_modules/lit-html/ts3.4/lib/directive.d.ts", - "../node_modules/lit-html/ts3.4/lib/dom.d.ts", - "../node_modules/lit-html/ts3.4/lib/part.d.ts", - "../node_modules/lit-html/ts3.4/lib/parts.d.ts", - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts", - "../node_modules/lit-html/ts3.4/lib/render.d.ts", - "../node_modules/lit-html/ts3.4/lib/template-factory.d.ts", - "../node_modules/lit-html/ts3.4/lib/template-instance.d.ts", - "../node_modules/lit-html/ts3.4/lib/template-processor.d.ts", - "../node_modules/lit-html/ts3.4/lib/template.d.ts" - ], - "../node_modules/lit-element/ts3.4/lit-element.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/shady-render.d.ts", - "../node_modules/lit-element/ts3.4/lib/updating-element.d.ts", - "../node_modules/lit-element/ts3.4/lib/decorators.d.ts", - "../node_modules/lit-html/ts3.4/lit-html.d.ts", - "../node_modules/lit-element/ts3.4/lib/css-tag.d.ts" - ], - "../test/unit/helpers/customelementfixture.ts": [ - "../node_modules/lit-element/ts3.4/lit-element.d.ts" - ], - "../src/components/mutation-test-totals.ts": [ - "../node_modules/lit-element/ts3.4/lit-element.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/index.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/index.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/shady-render.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts", - "../node_modules/lit-html/ts3.4/lit-html.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/directive.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/part.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/default-template-processor.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/part.d.ts", - "../node_modules/lit-html/ts3.4/lib/parts.d.ts", - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts", - "../node_modules/lit-html/ts3.4/lib/template-processor.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/template-processor.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/part.d.ts", - "../node_modules/lit-html/ts3.4/lib/parts.d.ts", - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/template-instance.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts", - "../node_modules/lit-html/ts3.4/lib/template-processor.d.ts", - "../node_modules/lit-html/ts3.4/lib/template.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/template-result.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/template-processor.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/template-factory.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/template-result.d.ts", - "../node_modules/lit-html/ts3.4/lib/template.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/template-factory.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/render.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/parts.d.ts", - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/parts.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/part.d.ts", - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/template.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/template-result.d.ts" - ], - "../node_modules/lit-element/ts3.4/lib/decorators.d.ts": [ - "../node_modules/lit-element/ts3.4/lib/updating-element.d.ts" - ], - "../node_modules/mutation-testing-report-schema/dist/src/api/index.d.ts": [ - "../node_modules/mutation-testing-report-schema/dist/src/api/fileresult.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/location.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/mutantresult.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/mutationtestresult.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/thresholds.d.ts" - ], - "../node_modules/mutation-testing-report-schema/dist/src/index.d.ts": [ - "../node_modules/mutation-testing-report-schema/dist/src/api/index.d.ts" - ], - "../test/unit/helpers/factory.ts": [ - "../node_modules/mutation-testing-report-schema/dist/src/index.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/index.d.ts" - ], - "../node_modules/mutation-testing-metrics/dist/src/helpers.d.ts": [ - "../node_modules/mutation-testing-metrics/dist/src/api/metricsresult.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/index.d.ts" - ], - "../node_modules/mutation-testing-metrics/dist/src/index.d.ts": [ - "../node_modules/mutation-testing-metrics/dist/src/api/metricsresult.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/api/metrics.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/calculatemetrics.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/helpers.d.ts" - ], - "../node_modules/mutation-testing-metrics/dist/src/calculatemetrics.d.ts": [ - "../node_modules/mutation-testing-report-schema/dist/src/index.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/api/metricsresult.d.ts" - ], - "../node_modules/mutation-testing-metrics/dist/src/api/metricsresult.d.ts": [ - "../node_modules/mutation-testing-report-schema/dist/src/index.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/api/metrics.d.ts" - ], - "../node_modules/mutation-testing-report-schema/dist/src/api/mutantresult.d.ts": [ - "../node_modules/mutation-testing-report-schema/dist/src/api/location.d.ts" - ], - "../node_modules/mutation-testing-report-schema/dist/src/api/fileresult.d.ts": [ - "../node_modules/mutation-testing-report-schema/dist/src/api/mutantresult.d.ts" - ], - "../node_modules/mutation-testing-report-schema/dist/src/api/mutationtestresult.d.ts": [ - "../node_modules/mutation-testing-report-schema/dist/src/api/fileresult.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/thresholds.d.ts" - ] - }, - "semanticDiagnosticsPerFile": [ - "../../../node_modules/typescript/lib/lib.es6.d.ts", - "../node_modules/lit-html/ts3.4/lib/part.d.ts", - "../node_modules/lit-html/ts3.4/lib/parts.d.ts", - "../node_modules/lit-html/ts3.4/lib/template-processor.d.ts", - "../node_modules/lit-html/ts3.4/lib/template-result.d.ts", - "../node_modules/lit-html/ts3.4/lib/template.d.ts", - "../node_modules/lit-html/ts3.4/lib/template-factory.d.ts", - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts", - "../node_modules/lit-html/ts3.4/lib/default-template-processor.d.ts", - "../node_modules/lit-html/ts3.4/lib/directive.d.ts", - "../node_modules/lit-html/ts3.4/lib/dom.d.ts", - "../node_modules/lit-html/ts3.4/lib/render.d.ts", - "../node_modules/lit-html/ts3.4/lib/template-instance.d.ts", - "../node_modules/lit-html/ts3.4/lit-html.d.ts", - "../node_modules/lit-html/ts3.4/lib/shady-render.d.ts", - "../node_modules/lit-element/ts3.4/lib/updating-element.d.ts", - "../node_modules/lit-element/ts3.4/lib/decorators.d.ts", - "../node_modules/lit-element/ts3.4/lib/css-tag.d.ts", - "../node_modules/lit-element/ts3.4/lit-element.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/location.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/mutantresult.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/fileresult.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/thresholds.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/mutationtestresult.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/index.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/index.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/api/metrics.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/api/metricsresult.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/calculatemetrics.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/helpers.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/index.d.ts", - "../src/components/mutation-test-totals.ts", - "../test/unit/helpers/customelementfixture.ts", - "../../../../node_modules/@types/chai/index.d.ts", - "../test/unit/helpers/factory.ts", - "../test/unit/components/mutation-test-totals.spec.ts", - "../../../../node_modules/@types/mocha/index.d.ts", - "../node_modules/@types/webpack-env/index.d.ts", - "../../../node_modules/typescript/lib/lib.es2015.d.ts", - "../../../node_modules/typescript/lib/lib.es5.d.ts", - "../../../node_modules/typescript/lib/lib.dom.d.ts", - "../../../node_modules/typescript/lib/lib.dom.iterable.d.ts", - "../../../node_modules/typescript/lib/lib.webworker.importscripts.d.ts", - "../../../node_modules/typescript/lib/lib.scripthost.d.ts", - "../../../node_modules/typescript/lib/lib.es2015.core.d.ts", - "../../../node_modules/typescript/lib/lib.es2015.collection.d.ts", - "../../../node_modules/typescript/lib/lib.es2015.generator.d.ts", - "../../../node_modules/typescript/lib/lib.es2015.iterable.d.ts", - "../../../node_modules/typescript/lib/lib.es2015.promise.d.ts", - "../../../node_modules/typescript/lib/lib.es2015.proxy.d.ts", - "../../../node_modules/typescript/lib/lib.es2015.reflect.d.ts", - "../../../node_modules/typescript/lib/lib.es2015.symbol.d.ts", - "../../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts" - ] - }, - "version": "3.7.2" -} \ No newline at end of file diff --git a/e2e/test/karma-webpack-with-ts/dist-test/unit/components/mutation-test-totals.spec.d.ts b/e2e/test/karma-webpack-with-ts/dist-test/unit/components/mutation-test-totals.spec.d.ts deleted file mode 100644 index 87ff3da57d..0000000000 --- a/e2e/test/karma-webpack-with-ts/dist-test/unit/components/mutation-test-totals.spec.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -export {}; -//# sourceMappingURL=mutation-test-totals.spec.d.ts.map \ No newline at end of file diff --git a/e2e/test/karma-webpack-with-ts/dist-test/unit/components/mutation-test-totals.spec.js b/e2e/test/karma-webpack-with-ts/dist-test/unit/components/mutation-test-totals.spec.js deleted file mode 100644 index f6a3eeacd3..0000000000 --- a/e2e/test/karma-webpack-with-ts/dist-test/unit/components/mutation-test-totals.spec.js +++ /dev/null @@ -1,108 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const mutation_test_totals_1 = require("../../../src/components/mutation-test-totals"); -const CustomElementFixture_1 = require("../helpers/CustomElementFixture"); -const chai_1 = require("chai"); -const factory_1 = require("../helpers/factory"); -describe(mutation_test_totals_1.MutationTestReportTotalsComponent.name, () => { - let sut; - beforeEach(() => __awaiter(void 0, void 0, void 0, function* () { - sut = new CustomElementFixture_1.CustomElementFixture('mutation-test-report-totals'); - yield sut.whenStable(); - })); - afterEach(() => { - sut.dispose(); - }); - it('should not show a table if no data is loaded', () => { - chai_1.expect(sut.$('table')).eq(null); - }); - it('should show a table with a single row for a file result', () => __awaiter(void 0, void 0, void 0, function* () { - sut.element.model = factory_1.createMetricsResult({ - file: factory_1.createFileResult(), - }); - yield sut.whenStable(); - const table = sut.$('table'); - chai_1.expect(table).ok; - chai_1.expect(table.querySelectorAll('thead th')).lengthOf(12); - chai_1.expect(table.querySelectorAll('tbody th, tbody td')).lengthOf(14); - })); - it('should show a table with a 3 rows for a directory result with 2 directories and one file', () => __awaiter(void 0, void 0, void 0, function* () { - const file = factory_1.createMetricsResult({ - name: 'foo.js', - file: factory_1.createFileResult(), - }); - sut.element.model = factory_1.createMetricsResult({ - name: 'bar', - childResults: [file, factory_1.createMetricsResult({ name: 'baz' })], - }); - yield sut.whenStable(); - const table = sut.$('table'); - chai_1.expect(table).ok; - chai_1.expect(table.querySelectorAll('tbody tr')).lengthOf(3); - })); - it('should flatten a row if the directory only has one file', () => __awaiter(void 0, void 0, void 0, function* () { - // Arrange - const file = factory_1.createMetricsResult({ - name: 'foo.js', - file: factory_1.createFileResult(), - }); - sut.element.model = factory_1.createMetricsResult({ - name: 'bar', - childResults: [ - factory_1.createMetricsResult({ - name: 'baz', - childResults: [file], - }), - ], - }); - // Act - yield sut.whenStable(); - // Assert - const table = sut.$('table'); - chai_1.expect(table).ok; - const rows = table.querySelectorAll('tbody tr'); - chai_1.expect(rows).lengthOf(2); - chai_1.expect(rows.item(1).cells.item(1).textContent).eq('baz/foo.js'); - })); - it('should show N/A when no mutation score is available', () => __awaiter(void 0, void 0, void 0, function* () { - sut.element.model = factory_1.createMetricsResult({ - name: 'foo', - }); - sut.element.model.metrics.mutationScore = NaN; - yield sut.whenStable(); - const table = sut.$('table'); - chai_1.expect(table).ok; - chai_1.expect(table.querySelectorAll('td span.font-weight-bold')[0].textContent).contains('N/A'); - })); - it('should show a progress bar when there is a score', () => __awaiter(void 0, void 0, void 0, function* () { - sut.element.model = factory_1.createMetricsResult({ - name: 'foo', - }); - const mutationScore = 50; - sut.element.model.metrics.mutationScore = mutationScore; - yield sut.whenStable(); - const table = sut.$('table'); - chai_1.expect(table).ok; - chai_1.expect(table.querySelectorAll('.progress')[0].textContent).contains(mutationScore); - })); - it('should show no progress bar when score is NaN', () => __awaiter(void 0, void 0, void 0, function* () { - sut.element.model = factory_1.createMetricsResult({ - name: 'foo', - }); - sut.element.model.metrics.mutationScore = NaN; - yield sut.whenStable(); - const table = sut.$('table'); - chai_1.expect(table).ok; - chai_1.expect(table.querySelector('.progress')).null; - })); -}); -//# sourceMappingURL=mutation-test-totals.spec.js.map \ No newline at end of file diff --git a/e2e/test/karma-webpack-with-ts/dist-test/unit/helpers/CustomElementFixture.d.ts b/e2e/test/karma-webpack-with-ts/dist-test/unit/helpers/CustomElementFixture.d.ts deleted file mode 100644 index b5472f8273..0000000000 --- a/e2e/test/karma-webpack-with-ts/dist-test/unit/helpers/CustomElementFixture.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { LitElement } from 'lit-element'; -export declare class CustomElementFixture { - readonly element: TCustomElement; - constructor(nodeName: string); - whenStable(): Promise; - waitFor(action: () => boolean, timeout?: number): Promise; - $(selector: string, inShadow?: boolean): HTMLElement; - $$(selector: string): Element[]; - get style(): CSSStyleDeclaration; - dispose(): void; - catchEvent(eventType: string, act: () => Promise | void): Promise; -} -//# sourceMappingURL=CustomElementFixture.d.ts.map \ No newline at end of file diff --git a/e2e/test/karma-webpack-with-ts/dist-test/unit/helpers/CustomElementFixture.js b/e2e/test/karma-webpack-with-ts/dist-test/unit/helpers/CustomElementFixture.js deleted file mode 100644 index 8e5ab32b3d..0000000000 --- a/e2e/test/karma-webpack-with-ts/dist-test/unit/helpers/CustomElementFixture.js +++ /dev/null @@ -1,74 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -Object.defineProperty(exports, "__esModule", { value: true }); -class CustomElementFixture { - constructor(nodeName) { - this.element = document.createElement(nodeName); - document.body.append(this.element); - } - whenStable() { - return __awaiter(this, void 0, void 0, function* () { - while (!(yield this.element.updateComplete)) - ; - }); - } - waitFor(action, timeout = 500) { - const step = 50; - return new Promise((res, rej) => { - function tick(timeLeft) { - if (action()) { - res(); - } - else if (timeLeft <= 0) { - rej(new Error(`Condition not met in ${timeout} ms: ${action}`)); - } - else { - setTimeout(() => tick(timeLeft - step), step); - } - } - tick(timeout); - }); - } - $(selector, inShadow = true) { - if (inShadow) { - return this.element.shadowRoot.querySelector(selector); - } - else { - return this.element.querySelector(selector); - } - } - $$(selector) { - return [...this.element.shadowRoot.querySelectorAll(selector)]; - } - get style() { - return getComputedStyle(this.element); - } - dispose() { - return this.element.remove(); - } - catchEvent(eventType, act) { - return __awaiter(this, void 0, void 0, function* () { - let actual; - const eventListener = (evt) => (actual = evt); - this.element.addEventListener(eventType, eventListener); - try { - yield act(); - yield this.whenStable(); - } - finally { - this.element.removeEventListener(eventType, eventListener); - } - return actual; - }); - } -} -exports.CustomElementFixture = CustomElementFixture; -//# sourceMappingURL=CustomElementFixture.js.map \ No newline at end of file diff --git a/e2e/test/karma-webpack-with-ts/dist-test/unit/helpers/factory.d.ts b/e2e/test/karma-webpack-with-ts/dist-test/unit/helpers/factory.d.ts deleted file mode 100644 index 3158acef2f..0000000000 --- a/e2e/test/karma-webpack-with-ts/dist-test/unit/helpers/factory.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { MutantResult, FileResult } from 'mutation-testing-report-schema'; -import { Metrics, MetricsResult } from 'mutation-testing-metrics'; -export declare function createMutantResult(overrides?: Partial): MutantResult; -export declare function createFileResult(overrides?: Partial): FileResult; -export declare function createMetricsResult(overrides?: Partial): MetricsResult; -export declare function createMetrics(overrides?: Metrics): Metrics; -//# sourceMappingURL=factory.d.ts.map \ No newline at end of file diff --git a/e2e/test/karma-webpack-with-ts/dist-test/unit/helpers/factory.js b/e2e/test/karma-webpack-with-ts/dist-test/unit/helpers/factory.js deleted file mode 100644 index f205f3730d..0000000000 --- a/e2e/test/karma-webpack-with-ts/dist-test/unit/helpers/factory.js +++ /dev/null @@ -1,62 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -function createMutantResult(overrides) { - const defaults = { - id: '1', - location: { - end: { - column: 3, - line: 1, - }, - start: { - column: 1, - line: 1, - }, - }, - mutatorName: 'bazMutator', - replacement: 'baz', - status: "Killed" /* Killed */, - }; - return Object.assign(Object.assign({}, defaults), overrides); -} -exports.createMutantResult = createMutantResult; -function createFileResult(overrides) { - const defaults = { - language: 'js', - mutants: [createMutantResult()], - source: 'const bar = foo();', - }; - return Object.assign(Object.assign({}, defaults), overrides); -} -exports.createFileResult = createFileResult; -function createMetricsResult(overrides) { - const defaults = { - childResults: [], - metrics: createMetrics(), - name: 'foo', - }; - return Object.assign(Object.assign({}, defaults), overrides); -} -exports.createMetricsResult = createMetricsResult; -function createMetrics(overrides) { - const defaults = { - killed: 0, - survived: 0, - timeout: 0, - compileErrors: 0, - runtimeErrors: 0, - noCoverage: 0, - ignored: 0, - totalCovered: 0, - totalDetected: 0, - totalInvalid: 0, - totalMutants: 0, - totalUndetected: 0, - totalValid: 0, - mutationScore: 0, - mutationScoreBasedOnCoveredCode: 0, - }; - return Object.assign(Object.assign({}, defaults), overrides); -} -exports.createMetrics = createMetrics; -//# sourceMappingURL=factory.js.map \ No newline at end of file diff --git a/e2e/test/karma-webpack-with-ts/dist/components/mutation-test-totals.d.ts b/e2e/test/karma-webpack-with-ts/dist/components/mutation-test-totals.d.ts deleted file mode 100644 index cdb143fc4a..0000000000 --- a/e2e/test/karma-webpack-with-ts/dist/components/mutation-test-totals.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { LitElement } from 'lit-element'; -import { Thresholds } from 'mutation-testing-report-schema'; -import { MetricsResult } from 'mutation-testing-metrics'; -export declare class MutationTestReportTotalsComponent extends LitElement { - model: MetricsResult | undefined; - thresholds: Thresholds | undefined; - currentPath: string[]; - private readonly fileIcon; - private readonly directoryIcon; - render(): import("lit-element").TemplateResult | undefined; - private renderHead; - private renderTableBody; - private renderRow; - private determineColoringClass; -} -//# sourceMappingURL=mutation-test-totals.d.ts.map \ No newline at end of file diff --git a/e2e/test/karma-webpack-with-ts/dist/components/mutation-test-totals.js b/e2e/test/karma-webpack-with-ts/dist/components/mutation-test-totals.js deleted file mode 100644 index 2ae9b67851..0000000000 --- a/e2e/test/karma-webpack-with-ts/dist/components/mutation-test-totals.js +++ /dev/null @@ -1,167 +0,0 @@ -var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { - var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; - if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); - else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; - return c > 3 && r && Object.defineProperty(target, key, r), r; -}; -import { LitElement, html, property, customElement, svg } from 'lit-element'; -import { pathJoin } from '../lib/codeHelpers'; -import { toAbsoluteUrl } from '../lib/htmlHelpers'; -let MutationTestReportTotalsComponent = class MutationTestReportTotalsComponent extends LitElement { - constructor() { - super(...arguments); - this.currentPath = []; - this.fileIcon = svg ``; - this.directoryIcon = svg ``; - } - render() { - if (this.model) { - return html ` - - ${this.renderHead()} ${this.renderTableBody(this.model)} -
- `; - } - else { - return undefined; - } - } - renderHead() { - return html ` - - -
File / Directory
- - -
Mutation score
- - -
# Killed
- - -
# Survived
- - -
# Timeout
- - -
# No coverage
- - -
# Ignored
- - -
# Runtime errors
- - -
# Compile errors
- - -
Total detected
- - -
Total undetected
- - -
Total mutants
- - - `; - } - renderTableBody(model) { - const renderChildren = () => { - if (model.file) { - return undefined; - } - else { - return model.childResults.map((childResult) => { - let fullName = childResult.name; - while (!childResult.file && childResult.childResults.length === 1) { - childResult = childResult.childResults[0]; - fullName = pathJoin(fullName, childResult.name); - } - return this.renderRow(fullName, childResult, pathJoin(...this.currentPath, fullName)); - }); - } - }; - return html ` - - ${this.renderRow(model.name, model, undefined)} ${renderChildren()} - - `; - } - renderRow(name, row, path) { - const { mutationScore } = row.metrics; - const scoreIsPresent = !isNaN(mutationScore); - const coloringClass = this.determineColoringClass(mutationScore); - const mutationScoreRounded = mutationScore.toFixed(2); - const progressBarStyle = `width: ${mutationScore}%`; - return html ` - ${row.file ? this.fileIcon : this.directoryIcon} - ${typeof path === 'string' ? html `${name}` : html `${row.name}`} - - ${scoreIsPresent - ? html `
-
- ${mutationScoreRounded}% -
-
` - : html ` N/A `} - - - ${scoreIsPresent ? mutationScoreRounded : undefined} - - ${row.metrics.killed} - ${row.metrics.survived} - ${row.metrics.timeout} - ${row.metrics.noCoverage} - ${row.metrics.ignored} - ${row.metrics.runtimeErrors} - ${row.metrics.compileErrors} - ${row.metrics.totalDetected} - ${row.metrics.totalUndetected} - ${row.metrics.totalMutants} - `; - } - determineColoringClass(mutationScore) { - if (!isNaN(mutationScore) && this.thresholds) { - if (mutationScore < this.thresholds.low) { - return 'danger'; - } - else if (mutationScore < this.thresholds.high) { - return 'warning'; - } - else { - return 'success'; - } - } - else { - return 'default'; - } - } -}; -__decorate([ - property() -], MutationTestReportTotalsComponent.prototype, "model", void 0); -__decorate([ - property() -], MutationTestReportTotalsComponent.prototype, "thresholds", void 0); -__decorate([ - property() -], MutationTestReportTotalsComponent.prototype, "currentPath", void 0); -MutationTestReportTotalsComponent = __decorate([ - customElement('mutation-test-report-totals') -], MutationTestReportTotalsComponent); -export { MutationTestReportTotalsComponent }; -//# sourceMappingURL=mutation-test-totals.js.map \ No newline at end of file diff --git a/e2e/test/karma-webpack-with-ts/dist/lib/codeHelpers.d.ts b/e2e/test/karma-webpack-with-ts/dist/lib/codeHelpers.d.ts deleted file mode 100644 index 227e85dbbf..0000000000 --- a/e2e/test/karma-webpack-with-ts/dist/lib/codeHelpers.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -export declare function pathJoin(...parts: string[]): string; -//# sourceMappingURL=codeHelpers.d.ts.map \ No newline at end of file diff --git a/e2e/test/karma-webpack-with-ts/dist/lib/codeHelpers.js b/e2e/test/karma-webpack-with-ts/dist/lib/codeHelpers.js deleted file mode 100644 index 37fca1c74d..0000000000 --- a/e2e/test/karma-webpack-with-ts/dist/lib/codeHelpers.js +++ /dev/null @@ -1,4 +0,0 @@ -export function pathJoin(...parts) { - return parts.reduce((prev, current) => (prev.length ? (current ? `${prev}/${current}` : prev) : current), ''); -} -//# sourceMappingURL=codeHelpers.js.map \ No newline at end of file diff --git a/e2e/test/karma-webpack-with-ts/dist/lib/htmlHelpers.d.ts b/e2e/test/karma-webpack-with-ts/dist/lib/htmlHelpers.d.ts deleted file mode 100644 index cc1fec7fe5..0000000000 --- a/e2e/test/karma-webpack-with-ts/dist/lib/htmlHelpers.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -export declare function toAbsoluteUrl(fragment: string): string; -//# sourceMappingURL=htmlHelpers.d.ts.map \ No newline at end of file diff --git a/e2e/test/karma-webpack-with-ts/dist/lib/htmlHelpers.js b/e2e/test/karma-webpack-with-ts/dist/lib/htmlHelpers.js deleted file mode 100644 index 752cb20abf..0000000000 --- a/e2e/test/karma-webpack-with-ts/dist/lib/htmlHelpers.js +++ /dev/null @@ -1,6 +0,0 @@ -export function toAbsoluteUrl(fragment) { - // Use absolute url because of https://github.com/stryker-mutator/mutation-testing-elements/issues/53 - const url = new URL(window.location.href); - return new URL(`#${fragment}`, url).href; -} -//# sourceMappingURL=htmlHelpers.js.map \ No newline at end of file diff --git a/e2e/test/karma-webpack-with-ts/dist/tsconfig.tsbuildinfo b/e2e/test/karma-webpack-with-ts/dist/tsconfig.tsbuildinfo deleted file mode 100644 index 0fd8de576a..0000000000 --- a/e2e/test/karma-webpack-with-ts/dist/tsconfig.tsbuildinfo +++ /dev/null @@ -1,506 +0,0 @@ -{ - "program": { - "fileInfos": { - "../../../node_modules/typescript/lib/lib.es5.d.ts": { - "version": "fc43680ad3a1a4ec8c7b8d908af1ec9ddff87845346de5f02c735c9171fa98ea", - "signature": "fc43680ad3a1a4ec8c7b8d908af1ec9ddff87845346de5f02c735c9171fa98ea" - }, - "../../../node_modules/typescript/lib/lib.es2015.d.ts": { - "version": "7994d44005046d1413ea31d046577cdda33b8b2470f30281fd9c8b3c99fe2d96", - "signature": "7994d44005046d1413ea31d046577cdda33b8b2470f30281fd9c8b3c99fe2d96" - }, - "../../../node_modules/typescript/lib/lib.dom.d.ts": { - "version": "d93de5e8a7275cb9d47481410e13b3b1debb997e216490954b5d106e37e086de", - "signature": "d93de5e8a7275cb9d47481410e13b3b1debb997e216490954b5d106e37e086de" - }, - "../../../node_modules/typescript/lib/lib.dom.iterable.d.ts": { - "version": "8329c3401aa8708426c7760f14219170f69a2cb77e4519758cec6f5027270faf", - "signature": "8329c3401aa8708426c7760f14219170f69a2cb77e4519758cec6f5027270faf" - }, - "../../../node_modules/typescript/lib/lib.es2015.core.d.ts": { - "version": "734ddc145e147fbcd55f07d034f50ccff1086f5a880107665ec326fb368876f6", - "signature": "734ddc145e147fbcd55f07d034f50ccff1086f5a880107665ec326fb368876f6" - }, - "../../../node_modules/typescript/lib/lib.es2015.collection.d.ts": { - "version": "4a0862a21f4700de873db3b916f70e41570e2f558da77d2087c9490f5a0615d8", - "signature": "4a0862a21f4700de873db3b916f70e41570e2f558da77d2087c9490f5a0615d8" - }, - "../../../node_modules/typescript/lib/lib.es2015.generator.d.ts": { - "version": "765e0e9c9d74cf4d031ca8b0bdb269a853e7d81eda6354c8510218d03db12122", - "signature": "765e0e9c9d74cf4d031ca8b0bdb269a853e7d81eda6354c8510218d03db12122" - }, - "../../../node_modules/typescript/lib/lib.es2015.iterable.d.ts": { - "version": "285958e7699f1babd76d595830207f18d719662a0c30fac7baca7df7162a9210", - "signature": "285958e7699f1babd76d595830207f18d719662a0c30fac7baca7df7162a9210" - }, - "../../../node_modules/typescript/lib/lib.es2015.promise.d.ts": { - "version": "d4deaafbb18680e3143e8b471acd650ed6f72a408a33137f0a0dd104fbe7f8ca", - "signature": "d4deaafbb18680e3143e8b471acd650ed6f72a408a33137f0a0dd104fbe7f8ca" - }, - "../../../node_modules/typescript/lib/lib.es2015.proxy.d.ts": { - "version": "5e72f949a89717db444e3bd9433468890068bb21a5638d8ab15a1359e05e54fe", - "signature": "5e72f949a89717db444e3bd9433468890068bb21a5638d8ab15a1359e05e54fe" - }, - "../../../node_modules/typescript/lib/lib.es2015.reflect.d.ts": { - "version": "f5b242136ae9bfb1cc99a5971cccc44e99947ae6b5ef6fd8aa54b5ade553b976", - "signature": "f5b242136ae9bfb1cc99a5971cccc44e99947ae6b5ef6fd8aa54b5ade553b976" - }, - "../../../node_modules/typescript/lib/lib.es2015.symbol.d.ts": { - "version": "9ae2860252d6b5f16e2026d8a2c2069db7b2a3295e98b6031d01337b96437230", - "signature": "9ae2860252d6b5f16e2026d8a2c2069db7b2a3295e98b6031d01337b96437230" - }, - "../../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts": { - "version": "3e0a459888f32b42138d5a39f706ff2d55d500ab1031e0988b5568b0f67c2303", - "signature": "3e0a459888f32b42138d5a39f706ff2d55d500ab1031e0988b5568b0f67c2303" - }, - "../../../node_modules/typescript/lib/lib.es2017.object.d.ts": { - "version": "c2d60b2e558d44384e4704b00e6b3d154334721a911f094d3133c35f0917b408", - "signature": "c2d60b2e558d44384e4704b00e6b3d154334721a911f094d3133c35f0917b408" - }, - "../node_modules/lit-html/ts3.4/lib/part.d.ts": { - "version": "253da37de7cfd359a21d78dfc11d480ff0abc851c4462c062c0152b08b2add8e", - "signature": "253da37de7cfd359a21d78dfc11d480ff0abc851c4462c062c0152b08b2add8e" - }, - "../node_modules/lit-html/ts3.4/lib/parts.d.ts": { - "version": "8abe19ac9fcee791ac64f4ced6b03f97e3aa3d3c5874f04af8f67a9c3c39d93e", - "signature": "8abe19ac9fcee791ac64f4ced6b03f97e3aa3d3c5874f04af8f67a9c3c39d93e" - }, - "../node_modules/lit-html/ts3.4/lib/template-processor.d.ts": { - "version": "64478db38bbf920d40129431b3d97032253a80bb6cb4183b5497832f8b9e4c7f", - "signature": "64478db38bbf920d40129431b3d97032253a80bb6cb4183b5497832f8b9e4c7f" - }, - "../node_modules/lit-html/ts3.4/lib/template-result.d.ts": { - "version": "cda7233c05b316c43ca4764038a1fb5fb61e0326696173b24bd4d8af8ab415be", - "signature": "cda7233c05b316c43ca4764038a1fb5fb61e0326696173b24bd4d8af8ab415be" - }, - "../node_modules/lit-html/ts3.4/lib/template.d.ts": { - "version": "536402bb8add0a08da6e51ea949412d589942e43a17243e830c95a8022001d58", - "signature": "536402bb8add0a08da6e51ea949412d589942e43a17243e830c95a8022001d58" - }, - "../node_modules/lit-html/ts3.4/lib/template-factory.d.ts": { - "version": "6a486a955ebdf00bbd7f5c155ea1baadb7d3d3914874c456e6a980b7386f6faa", - "signature": "6a486a955ebdf00bbd7f5c155ea1baadb7d3d3914874c456e6a980b7386f6faa" - }, - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts": { - "version": "cc35948605b99c6f32158e69ab1351943e9f305b249af966f7915f6e5abad628", - "signature": "cc35948605b99c6f32158e69ab1351943e9f305b249af966f7915f6e5abad628" - }, - "../node_modules/lit-html/ts3.4/lib/default-template-processor.d.ts": { - "version": "2bb52f7489d930c01dad30a5e32302327302c2dd248e80bc92c9aa48ee8d77c3", - "signature": "2bb52f7489d930c01dad30a5e32302327302c2dd248e80bc92c9aa48ee8d77c3" - }, - "../node_modules/lit-html/ts3.4/lib/directive.d.ts": { - "version": "c60770b91d363b3b14e5a3660e86a363c22800f4b424dfc080ec3975c0c3f78a", - "signature": "c60770b91d363b3b14e5a3660e86a363c22800f4b424dfc080ec3975c0c3f78a" - }, - "../node_modules/lit-html/ts3.4/lib/dom.d.ts": { - "version": "64ce958a702725d89f8c099eeeb8936b3584ea07d1e6ae5187a20a622cf72e94", - "signature": "64ce958a702725d89f8c099eeeb8936b3584ea07d1e6ae5187a20a622cf72e94" - }, - "../node_modules/lit-html/ts3.4/lib/render.d.ts": { - "version": "8c5703f69c2eb261df1f65dc65e84a6ec2d74187bf1dda5e46370adb41d01dd7", - "signature": "8c5703f69c2eb261df1f65dc65e84a6ec2d74187bf1dda5e46370adb41d01dd7" - }, - "../node_modules/lit-html/ts3.4/lib/template-instance.d.ts": { - "version": "d6ec7edc88bb1932615982f19049f4de5b96d7d48cb39557ca82ae1b571d0b55", - "signature": "d6ec7edc88bb1932615982f19049f4de5b96d7d48cb39557ca82ae1b571d0b55" - }, - "../node_modules/lit-html/ts3.4/lit-html.d.ts": { - "version": "410146f72ecc0811e9374ca7ad586b1c81993a32fbd2646245a5f81a45c533fd", - "signature": "410146f72ecc0811e9374ca7ad586b1c81993a32fbd2646245a5f81a45c533fd" - }, - "../node_modules/lit-html/ts3.4/lib/shady-render.d.ts": { - "version": "119731ffdb51d2062a80e60f0009109f27799b12b30f682a5d21fe5d8177d015", - "signature": "119731ffdb51d2062a80e60f0009109f27799b12b30f682a5d21fe5d8177d015" - }, - "../node_modules/lit-element/ts3.4/lib/updating-element.d.ts": { - "version": "1232e7e6b55f64fb09486987cb4aae2d511facc89190916a3077e5196a63d800", - "signature": "1232e7e6b55f64fb09486987cb4aae2d511facc89190916a3077e5196a63d800" - }, - "../node_modules/lit-element/ts3.4/lib/decorators.d.ts": { - "version": "18a2ea2cbd19957f6f593e300f9e1cc5157d302eef6a6902447d30daee3bd8a2", - "signature": "18a2ea2cbd19957f6f593e300f9e1cc5157d302eef6a6902447d30daee3bd8a2" - }, - "../node_modules/lit-element/ts3.4/lib/css-tag.d.ts": { - "version": "4ff2d5ca3abc6ebc0339dd03dfd1ffbe3943c02ea318f9a538c3f3cee2139c24", - "signature": "4ff2d5ca3abc6ebc0339dd03dfd1ffbe3943c02ea318f9a538c3f3cee2139c24" - }, - "../node_modules/lit-element/ts3.4/lit-element.d.ts": { - "version": "0029a8eaa03227915b62bcc8d1e7bf418b3c7ee70225413b67754c870fbf483b", - "signature": "0029a8eaa03227915b62bcc8d1e7bf418b3c7ee70225413b67754c870fbf483b" - }, - "../node_modules/mutation-testing-report-schema/dist/src/api/location.d.ts": { - "version": "c9632b53d68031c62cd80928e33c1c5a3dbd12a887f0a4dc93a63938f29b33f7", - "signature": "c9632b53d68031c62cd80928e33c1c5a3dbd12a887f0a4dc93a63938f29b33f7" - }, - "../node_modules/mutation-testing-report-schema/dist/src/api/mutantresult.d.ts": { - "version": "2b15980867f95cbb691e249b61edae74363bcf5b0b51602c871ce4de93874e51", - "signature": "2b15980867f95cbb691e249b61edae74363bcf5b0b51602c871ce4de93874e51" - }, - "../node_modules/mutation-testing-report-schema/dist/src/api/fileresult.d.ts": { - "version": "9b33b5614147e3b6abc8121781885fd09c293b3baa9008442d61a7a2ac2bc34b", - "signature": "9b33b5614147e3b6abc8121781885fd09c293b3baa9008442d61a7a2ac2bc34b" - }, - "../node_modules/mutation-testing-report-schema/dist/src/api/thresholds.d.ts": { - "version": "0844ea97fc6b9609db75d7efb557f4a43ec7ad5d6854cd9af8c14eaed3ff348f", - "signature": "0844ea97fc6b9609db75d7efb557f4a43ec7ad5d6854cd9af8c14eaed3ff348f" - }, - "../node_modules/mutation-testing-report-schema/dist/src/api/mutationtestresult.d.ts": { - "version": "ba246fb4e9a23e77b31420aace00352b0db3f497d4d8f9290b45d881328ea575", - "signature": "ba246fb4e9a23e77b31420aace00352b0db3f497d4d8f9290b45d881328ea575" - }, - "../node_modules/mutation-testing-report-schema/dist/src/api/index.d.ts": { - "version": "753930e76d5db961b7e5539425d29301be82cf1b964da70d402dd8f7bf3c39b2", - "signature": "753930e76d5db961b7e5539425d29301be82cf1b964da70d402dd8f7bf3c39b2" - }, - "../node_modules/mutation-testing-report-schema/dist/src/index.d.ts": { - "version": "2f63fb9896c604a7c597b5777f39197779e3fd34276c2d56e43e85d159fdd1ad", - "signature": "2f63fb9896c604a7c597b5777f39197779e3fd34276c2d56e43e85d159fdd1ad" - }, - "../src/lib/codehelpers.ts": { - "version": "caf5fa9d207fde1615613128109e6f687289d161b5d7538ec7195a00b716f8ab", - "signature": "4e3387c9f7a41f6c7ef530b86d771f3ff4e1e8dfe4f5d56e51a1c51a95df58aa" - }, - "../node_modules/mutation-testing-metrics/dist/src/api/metrics.d.ts": { - "version": "ed0d126575449c142f09eef7111b9d03354b1e5c4a26b6da7dc0401eef4608ba", - "signature": "ed0d126575449c142f09eef7111b9d03354b1e5c4a26b6da7dc0401eef4608ba" - }, - "../node_modules/mutation-testing-metrics/dist/src/api/metricsresult.d.ts": { - "version": "b188d1930c1461fc91d3627ebaad93e42cfc5715911810881b2ea38d9d876d41", - "signature": "b188d1930c1461fc91d3627ebaad93e42cfc5715911810881b2ea38d9d876d41" - }, - "../node_modules/mutation-testing-metrics/dist/src/calculatemetrics.d.ts": { - "version": "c0527d28327d523b9dee1907a39d123ae3018c8017c223debc4db6556fd14164", - "signature": "c0527d28327d523b9dee1907a39d123ae3018c8017c223debc4db6556fd14164" - }, - "../node_modules/mutation-testing-metrics/dist/src/helpers.d.ts": { - "version": "35bda36c3124dd5c129e2d4e10d4baa431a6ebcd8e22e8df2714f4c39b35030a", - "signature": "35bda36c3124dd5c129e2d4e10d4baa431a6ebcd8e22e8df2714f4c39b35030a" - }, - "../node_modules/mutation-testing-metrics/dist/src/index.d.ts": { - "version": "af12a458eb853611938075ca246b87ef9b4622386bede3b96ace1cb73bafb8f3", - "signature": "af12a458eb853611938075ca246b87ef9b4622386bede3b96ace1cb73bafb8f3" - }, - "../src/lib/htmlhelpers.ts": { - "version": "a4b917f9b88a295a2353e736965218dd16ed3bccffac9600ff5d248e4cbbf656", - "signature": "59b15111a96b1fe8f3598b6bc12c4f8a60007310032e7858689a9846a9fb66d6" - }, - "../src/components/mutation-test-totals.ts": { - "version": "e9a51af9fa4230a567b15b43afdb9426042ba0d5bb61e4c09ff08fc59bbc333b", - "signature": "53ba94396e0ef5f4af4c5fc9f4808e5a961cd1488853a671389b6fe01240b96f" - }, - "../node_modules/@types/webpack-env/index.d.ts": { - "version": "1db2b55f2381ed9558f93cbf4068096d72e1c8d59bb3a66aafa0fc11c1f17530", - "signature": "1db2b55f2381ed9558f93cbf4068096d72e1c8d59bb3a66aafa0fc11c1f17530" - } - }, - "options": { - "target": 2, - "module": 5, - "strict": true, - "composite": true, - "declaration": true, - "declarationMap": true, - "esModuleInterop": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - "forceConsistentCasingInFileNames": true, - "experimentalDecorators": true, - "sourceMap": true, - "types": [ - "webpack-env" - ], - "outDir": "./", - "moduleResolution": 2, - "lib": [ - "lib.es5.d.ts", - "lib.es2015.d.ts", - "lib.es2017.object.d.ts", - "lib.dom.d.ts", - "lib.dom.iterable.d.ts" - ], - "configFilePath": "../src/tsconfig.json" - }, - "referencedMap": { - "../node_modules/lit-html/ts3.4/lib/parts.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/part.d.ts", - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/template-processor.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/part.d.ts", - "../node_modules/lit-html/ts3.4/lib/parts.d.ts", - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/template-result.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/template-processor.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/template.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/template-result.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/template-factory.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/template-result.d.ts", - "../node_modules/lit-html/ts3.4/lib/template.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/template-factory.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/default-template-processor.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/part.d.ts", - "../node_modules/lit-html/ts3.4/lib/parts.d.ts", - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts", - "../node_modules/lit-html/ts3.4/lib/template-processor.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/directive.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/part.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/render.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/parts.d.ts", - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/template-instance.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts", - "../node_modules/lit-html/ts3.4/lib/template-processor.d.ts", - "../node_modules/lit-html/ts3.4/lib/template.d.ts" - ], - "../node_modules/lit-html/ts3.4/lit-html.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/template-result.d.ts", - "../node_modules/lit-html/ts3.4/lib/default-template-processor.d.ts", - "../node_modules/lit-html/ts3.4/lib/directive.d.ts", - "../node_modules/lit-html/ts3.4/lib/dom.d.ts", - "../node_modules/lit-html/ts3.4/lib/part.d.ts", - "../node_modules/lit-html/ts3.4/lib/parts.d.ts", - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts", - "../node_modules/lit-html/ts3.4/lib/render.d.ts", - "../node_modules/lit-html/ts3.4/lib/template-factory.d.ts", - "../node_modules/lit-html/ts3.4/lib/template-instance.d.ts", - "../node_modules/lit-html/ts3.4/lib/template-processor.d.ts", - "../node_modules/lit-html/ts3.4/lib/template.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/shady-render.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts", - "../node_modules/lit-html/ts3.4/lit-html.d.ts" - ], - "../node_modules/lit-element/ts3.4/lib/decorators.d.ts": [ - "../node_modules/lit-element/ts3.4/lib/updating-element.d.ts" - ], - "../node_modules/lit-element/ts3.4/lit-element.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/shady-render.d.ts", - "../node_modules/lit-element/ts3.4/lib/updating-element.d.ts", - "../node_modules/lit-element/ts3.4/lib/decorators.d.ts", - "../node_modules/lit-html/ts3.4/lit-html.d.ts", - "../node_modules/lit-element/ts3.4/lib/css-tag.d.ts" - ], - "../node_modules/mutation-testing-report-schema/dist/src/api/mutantresult.d.ts": [ - "../node_modules/mutation-testing-report-schema/dist/src/api/location.d.ts" - ], - "../node_modules/mutation-testing-report-schema/dist/src/api/fileresult.d.ts": [ - "../node_modules/mutation-testing-report-schema/dist/src/api/mutantresult.d.ts" - ], - "../node_modules/mutation-testing-report-schema/dist/src/api/mutationtestresult.d.ts": [ - "../node_modules/mutation-testing-report-schema/dist/src/api/fileresult.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/thresholds.d.ts" - ], - "../node_modules/mutation-testing-report-schema/dist/src/api/index.d.ts": [ - "../node_modules/mutation-testing-report-schema/dist/src/api/fileresult.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/location.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/mutantresult.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/mutationtestresult.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/thresholds.d.ts" - ], - "../node_modules/mutation-testing-report-schema/dist/src/index.d.ts": [ - "../node_modules/mutation-testing-report-schema/dist/src/api/index.d.ts" - ], - "../node_modules/mutation-testing-metrics/dist/src/api/metricsresult.d.ts": [ - "../node_modules/mutation-testing-report-schema/dist/src/index.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/api/metrics.d.ts" - ], - "../node_modules/mutation-testing-metrics/dist/src/calculatemetrics.d.ts": [ - "../node_modules/mutation-testing-report-schema/dist/src/index.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/api/metricsresult.d.ts" - ], - "../node_modules/mutation-testing-metrics/dist/src/helpers.d.ts": [ - "../node_modules/mutation-testing-metrics/dist/src/api/metricsresult.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/index.d.ts" - ], - "../node_modules/mutation-testing-metrics/dist/src/index.d.ts": [ - "../node_modules/mutation-testing-metrics/dist/src/api/metricsresult.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/api/metrics.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/calculatemetrics.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/helpers.d.ts" - ], - "../src/components/mutation-test-totals.ts": [ - "../node_modules/lit-element/ts3.4/lit-element.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/index.d.ts", - "../src/lib/codehelpers.ts", - "../node_modules/mutation-testing-metrics/dist/src/index.d.ts", - "../src/lib/htmlhelpers.ts" - ] - }, - "exportedModulesMap": { - "../node_modules/lit-html/ts3.4/lit-html.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/template-result.d.ts", - "../node_modules/lit-html/ts3.4/lib/default-template-processor.d.ts", - "../node_modules/lit-html/ts3.4/lib/directive.d.ts", - "../node_modules/lit-html/ts3.4/lib/dom.d.ts", - "../node_modules/lit-html/ts3.4/lib/part.d.ts", - "../node_modules/lit-html/ts3.4/lib/parts.d.ts", - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts", - "../node_modules/lit-html/ts3.4/lib/render.d.ts", - "../node_modules/lit-html/ts3.4/lib/template-factory.d.ts", - "../node_modules/lit-html/ts3.4/lib/template-instance.d.ts", - "../node_modules/lit-html/ts3.4/lib/template-processor.d.ts", - "../node_modules/lit-html/ts3.4/lib/template.d.ts" - ], - "../node_modules/lit-element/ts3.4/lit-element.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/shady-render.d.ts", - "../node_modules/lit-element/ts3.4/lib/updating-element.d.ts", - "../node_modules/lit-element/ts3.4/lib/decorators.d.ts", - "../node_modules/lit-html/ts3.4/lit-html.d.ts", - "../node_modules/lit-element/ts3.4/lib/css-tag.d.ts" - ], - "../src/components/mutation-test-totals.ts": [ - "../node_modules/lit-element/ts3.4/lit-element.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/index.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/index.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/shady-render.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts", - "../node_modules/lit-html/ts3.4/lit-html.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/directive.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/part.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/default-template-processor.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/part.d.ts", - "../node_modules/lit-html/ts3.4/lib/parts.d.ts", - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts", - "../node_modules/lit-html/ts3.4/lib/template-processor.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/template-processor.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/part.d.ts", - "../node_modules/lit-html/ts3.4/lib/parts.d.ts", - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/template-instance.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts", - "../node_modules/lit-html/ts3.4/lib/template-processor.d.ts", - "../node_modules/lit-html/ts3.4/lib/template.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/template-result.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/template-processor.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/template-factory.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/template-result.d.ts", - "../node_modules/lit-html/ts3.4/lib/template.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/template-factory.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/render.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/parts.d.ts", - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/parts.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/part.d.ts", - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts" - ], - "../node_modules/lit-html/ts3.4/lib/template.d.ts": [ - "../node_modules/lit-html/ts3.4/lib/template-result.d.ts" - ], - "../node_modules/lit-element/ts3.4/lib/decorators.d.ts": [ - "../node_modules/lit-element/ts3.4/lib/updating-element.d.ts" - ], - "../node_modules/mutation-testing-report-schema/dist/src/api/index.d.ts": [ - "../node_modules/mutation-testing-report-schema/dist/src/api/fileresult.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/location.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/mutantresult.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/mutationtestresult.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/thresholds.d.ts" - ], - "../node_modules/mutation-testing-report-schema/dist/src/index.d.ts": [ - "../node_modules/mutation-testing-report-schema/dist/src/api/index.d.ts" - ], - "../node_modules/mutation-testing-metrics/dist/src/helpers.d.ts": [ - "../node_modules/mutation-testing-metrics/dist/src/api/metricsresult.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/index.d.ts" - ], - "../node_modules/mutation-testing-metrics/dist/src/index.d.ts": [ - "../node_modules/mutation-testing-metrics/dist/src/api/metricsresult.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/api/metrics.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/calculatemetrics.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/helpers.d.ts" - ], - "../node_modules/mutation-testing-metrics/dist/src/calculatemetrics.d.ts": [ - "../node_modules/mutation-testing-report-schema/dist/src/index.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/api/metricsresult.d.ts" - ], - "../node_modules/mutation-testing-metrics/dist/src/api/metricsresult.d.ts": [ - "../node_modules/mutation-testing-report-schema/dist/src/index.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/api/metrics.d.ts" - ], - "../node_modules/mutation-testing-report-schema/dist/src/api/mutantresult.d.ts": [ - "../node_modules/mutation-testing-report-schema/dist/src/api/location.d.ts" - ], - "../node_modules/mutation-testing-report-schema/dist/src/api/fileresult.d.ts": [ - "../node_modules/mutation-testing-report-schema/dist/src/api/mutantresult.d.ts" - ], - "../node_modules/mutation-testing-report-schema/dist/src/api/mutationtestresult.d.ts": [ - "../node_modules/mutation-testing-report-schema/dist/src/api/fileresult.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/thresholds.d.ts" - ] - }, - "semanticDiagnosticsPerFile": [ - "../node_modules/lit-html/ts3.4/lib/part.d.ts", - "../node_modules/lit-html/ts3.4/lib/parts.d.ts", - "../node_modules/lit-html/ts3.4/lib/template-processor.d.ts", - "../node_modules/lit-html/ts3.4/lib/template-result.d.ts", - "../node_modules/lit-html/ts3.4/lib/template.d.ts", - "../node_modules/lit-html/ts3.4/lib/template-factory.d.ts", - "../node_modules/lit-html/ts3.4/lib/render-options.d.ts", - "../node_modules/lit-html/ts3.4/lib/default-template-processor.d.ts", - "../node_modules/lit-html/ts3.4/lib/directive.d.ts", - "../node_modules/lit-html/ts3.4/lib/dom.d.ts", - "../node_modules/lit-html/ts3.4/lib/render.d.ts", - "../node_modules/lit-html/ts3.4/lib/template-instance.d.ts", - "../node_modules/lit-html/ts3.4/lit-html.d.ts", - "../node_modules/lit-html/ts3.4/lib/shady-render.d.ts", - "../node_modules/lit-element/ts3.4/lib/updating-element.d.ts", - "../node_modules/lit-element/ts3.4/lib/decorators.d.ts", - "../node_modules/lit-element/ts3.4/lib/css-tag.d.ts", - "../node_modules/lit-element/ts3.4/lit-element.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/location.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/mutantresult.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/fileresult.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/thresholds.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/mutationtestresult.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/api/index.d.ts", - "../node_modules/mutation-testing-report-schema/dist/src/index.d.ts", - "../src/lib/codehelpers.ts", - "../node_modules/mutation-testing-metrics/dist/src/api/metrics.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/api/metricsresult.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/calculatemetrics.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/helpers.d.ts", - "../node_modules/mutation-testing-metrics/dist/src/index.d.ts", - "../src/lib/htmlhelpers.ts", - "../src/components/mutation-test-totals.ts", - "../node_modules/@types/webpack-env/index.d.ts", - "../../../node_modules/typescript/lib/lib.es2015.d.ts", - "../../../node_modules/typescript/lib/lib.es5.d.ts", - "../../../node_modules/typescript/lib/lib.dom.d.ts", - "../../../node_modules/typescript/lib/lib.dom.iterable.d.ts", - "../../../node_modules/typescript/lib/lib.es2015.core.d.ts", - "../../../node_modules/typescript/lib/lib.es2015.collection.d.ts", - "../../../node_modules/typescript/lib/lib.es2015.generator.d.ts", - "../../../node_modules/typescript/lib/lib.es2015.iterable.d.ts", - "../../../node_modules/typescript/lib/lib.es2015.promise.d.ts", - "../../../node_modules/typescript/lib/lib.es2015.proxy.d.ts", - "../../../node_modules/typescript/lib/lib.es2015.reflect.d.ts", - "../../../node_modules/typescript/lib/lib.es2015.symbol.d.ts", - "../../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts", - "../../../node_modules/typescript/lib/lib.es2017.object.d.ts" - ] - }, - "version": "3.7.2" -} \ No newline at end of file diff --git a/e2e/test/karma-webpack-with-ts/package.json b/e2e/test/karma-webpack-with-ts/package.json index aa4c852f29..38ea1382aa 100644 --- a/e2e/test/karma-webpack-with-ts/package.json +++ b/e2e/test/karma-webpack-with-ts/package.json @@ -3,14 +3,15 @@ "description": "A test project for karma with the karma-webpack plugin and the ts-loader.", "scripts": { "test": "stryker run", + "test:unit": "karma start", "posttest": "mocha --require ../../tasks/ts-node-register.js verify/verify.ts" }, "dependencies": { - "lit-element": "^2.3.1", + "lit-element": "~2.3.1", "mutation-testing-metrics": "~1.4.0", "mutation-testing-report-schema": "~1.4.0" }, "devDependencies": { - "@types/webpack-env": "^1.15.2" + "@types/webpack-env": "~1.15.2" } } diff --git a/e2e/test/karma-webpack-with-ts/src/components/mutation-test-totals.ts b/e2e/test/karma-webpack-with-ts/src/components/mutation-test-totals.ts index da0b981901..213aa476d2 100644 --- a/e2e/test/karma-webpack-with-ts/src/components/mutation-test-totals.ts +++ b/e2e/test/karma-webpack-with-ts/src/components/mutation-test-totals.ts @@ -30,7 +30,7 @@ export class MutationTestReportTotalsComponent extends LitElement { } } - private renderHead() { + public renderHead() { return html` diff --git a/e2e/test/karma-webpack-with-ts/stryker.conf.json b/e2e/test/karma-webpack-with-ts/stryker.conf.json index 372c51dfd6..ddfbf370ec 100644 --- a/e2e/test/karma-webpack-with-ts/stryker.conf.json +++ b/e2e/test/karma-webpack-with-ts/stryker.conf.json @@ -1,19 +1,25 @@ { - "$schema": "https://raw.githubusercontent.com/stryker-mutator/stryker/master/packages/api/schema/stryker-core.json", - "mutator": "typescript", + "$schema": "../../node_modules/@stryker-mutator/core/schema/stryker-schema.json", "mutate": [ "src/components/mutation-test-totals.ts" ], "packageManager": "npm", "testRunner": "karma", - "maxConcurrentTestRunners": 2, - "coverageAnalysis": "off", + "concurrency": 2, + "coverageAnalysis": "perTest", "reporters": [ + "html", + "clear-text", + "progress", "event-recorder" ], "karma": { "configFile": "karma.conf.js", "projectType": "custom" }, - "tsconfigFile": "tsconfig.json" + "tsconfigFile": "tsconfig.json", + "logLevel": "info", + "plugins": [ + "@stryker-mutator/karma-runner" + ] } diff --git a/e2e/test/karma-webpack-with-ts/verify/verify.ts b/e2e/test/karma-webpack-with-ts/verify/verify.ts index 80b560d532..50df95cd92 100644 --- a/e2e/test/karma-webpack-with-ts/verify/verify.ts +++ b/e2e/test/karma-webpack-with-ts/verify/verify.ts @@ -1,13 +1,17 @@ -import { readMutationTestResult } from '../../../helpers'; -import { expect } from 'chai'; +import { expectMetrics } from '../../../helpers'; describe('Verify stryker has ran correctly', () => { it('should report correct score', async () => { - // TODO: After these results should be much better after we've implemented mutation switching - const result = await readMutationTestResult(); - expect(result.metrics.mutationScore, 'mutationScore').greaterThan(10); - expect(result.metrics.timeout, 'timeout').gte(1); - expect(result.metrics.killed, 'killed').gte(5); + await expectMetrics({ + mutationScore: 51.67, + compileErrors: 0, + ignored: 0, + killed: 30, + noCoverage: 15, + runtimeErrors: 0, + timeout: 1, + survived: 14 + }); }); }); diff --git a/e2e/test/mocha-javascript/.mocharc.jsonc b/e2e/test/mocha-javascript/.mocharc.jsonc new file mode 100644 index 0000000000..3c2e5a6a9d --- /dev/null +++ b/e2e/test/mocha-javascript/.mocharc.jsonc @@ -0,0 +1,4 @@ +{ + "require": "./test/helpers/testSetup.js", + "spec": ["test/unit/*.js"] +} \ No newline at end of file diff --git a/e2e/test/mocha-javascript/package-lock.json b/e2e/test/mocha-javascript/package-lock.json new file mode 100644 index 0000000000..3900182e5c --- /dev/null +++ b/e2e/test/mocha-javascript/package-lock.json @@ -0,0 +1,5 @@ +{ + "name": "mocha-mocha", + "version": "0.0.0", + "lockfileVersion": 1 +} diff --git a/e2e/test/mocha-javascript/package.json b/e2e/test/mocha-javascript/package.json new file mode 100644 index 0000000000..bd278bd1fd --- /dev/null +++ b/e2e/test/mocha-javascript/package.json @@ -0,0 +1,15 @@ +{ + "name": "mocha-javascript", + "version": "0.0.0", + "private": true, + "description": "A module to perform an integration test", + "main": "index.js", + "scripts": { + "pretest": "rimraf \"reports\"", + "test": "stryker run", + "test:unit": "mocha", + "posttest": "mocha --no-config --require ../../tasks/ts-node-register.js verify/*.ts" + }, + "author": "", + "license": "ISC" +} diff --git a/e2e/test/mocha-javascript/src/Add.js b/e2e/test/mocha-javascript/src/Add.js new file mode 100644 index 0000000000..580a6015b2 --- /dev/null +++ b/e2e/test/mocha-javascript/src/Add.js @@ -0,0 +1,27 @@ +#! /usr/bin/env node +module.exports.add = function(num1, num2) { + return num1 + num2; +}; + +module.exports.addOne = function(number) { + number++; + return number; +}; + +module.exports.negate = function(number) { + return -number; +}; + +module.exports.notCovered = function(number) { + return number > 10; +}; + +module.exports.isNegativeNumber = function(number) { + var isNegative = false; + if(number < 0){ + isNegative = true; + } + return isNegative; +}; + + diff --git a/e2e/test/mocha-javascript/src/Circle.js b/e2e/test/mocha-javascript/src/Circle.js new file mode 100644 index 0000000000..c1660c2d3f --- /dev/null +++ b/e2e/test/mocha-javascript/src/Circle.js @@ -0,0 +1,8 @@ +module.exports.getCircumference = function(radius) { + //Function to test multiple math mutations in a single function. + return 2 * Math.PI * radius; +}; + +module.exports.untestedFunction = function() { + var i = 5 / 2 * 3; +}; diff --git a/e2e/test/mocha-javascript/src/IsEven.js b/e2e/test/mocha-javascript/src/IsEven.js new file mode 100644 index 0000000000..e3c376a3b3 --- /dev/null +++ b/e2e/test/mocha-javascript/src/IsEven.js @@ -0,0 +1,18 @@ + +module.exports.isEven = function(number) { + // Note: Implemented with a case switch statement, in order to reproduce this issue: + // https://github.com/stryker-mutator/stryker/issues/2469#issuecomment-690303849 + let mod2 = number % 2; + let isEven; + switch(mod2) { + case 0: { + isEven = true; + break; + } + case 1: { + isEven = false; + break; + } + } + return isEven; +} diff --git "a/e2e/test/mocha-javascript/src/\360\237\220\261\342\200\215\360\237\221\223ninja.cat.js" "b/e2e/test/mocha-javascript/src/\360\237\220\261\342\200\215\360\237\221\223ninja.cat.js" new file mode 100644 index 0000000000..e521df326a --- /dev/null +++ "b/e2e/test/mocha-javascript/src/\360\237\220\261\342\200\215\360\237\221\223ninja.cat.js" @@ -0,0 +1,4 @@ + +module.exports = function ninjaCatSays(toSay) { + return `🐱‍👓 ${toSay}`; +} diff --git a/e2e/test/mocha-javascript/stryker.conf.json b/e2e/test/mocha-javascript/stryker.conf.json new file mode 100644 index 0000000000..d864973ed7 --- /dev/null +++ b/e2e/test/mocha-javascript/stryker.conf.json @@ -0,0 +1,10 @@ +{ + "$schema": "../../node_modules/@stryker-mutator/core/schema/stryker-schema.json", + "testRunner": "mocha", + "concurrency": 2, + "coverageAnalysis": "perTest", + "reporters": ["clear-text", "html", "event-recorder"], + "plugins": [ + "@stryker-mutator/mocha-runner" + ] +} diff --git a/e2e/test/mocha-javascript/test/helpers/testSetup.js b/e2e/test/mocha-javascript/test/helpers/testSetup.js new file mode 100644 index 0000000000..993b68e6fc --- /dev/null +++ b/e2e/test/mocha-javascript/test/helpers/testSetup.js @@ -0,0 +1,5 @@ +exports.mochaHooks = { + beforeAll() { + global.expect = require('chai').expect; + } +} diff --git a/e2e/test/mocha-mocha/test/unit/AddSpec.js b/e2e/test/mocha-javascript/test/unit/Add.spec.js similarity index 100% rename from e2e/test/mocha-mocha/test/unit/AddSpec.js rename to e2e/test/mocha-javascript/test/unit/Add.spec.js diff --git a/e2e/test/mocha-javascript/test/unit/Circle.spec.js b/e2e/test/mocha-javascript/test/unit/Circle.spec.js new file mode 100644 index 0000000000..84dfb2942f --- /dev/null +++ b/e2e/test/mocha-javascript/test/unit/Circle.spec.js @@ -0,0 +1,18 @@ +var circleModule = require('../../src/Circle'); +var getCircumference = circleModule.getCircumference; + +describe('Circle', function() { + it('should have a circumference of 2PI when the radius is 1', function() { + var radius = 1; + var expectedCircumference = 2 * Math.PI; + + var circumference = getCircumference(radius); + + expect(circumference).to.be.equal(expectedCircumference); + }); + + it('should skip this test', function() { + getCircumference(2); + this.skip(); + }); +}); diff --git a/e2e/test/mocha-javascript/test/unit/IsEven.spec.js b/e2e/test/mocha-javascript/test/unit/IsEven.spec.js new file mode 100644 index 0000000000..bc6bfae79b --- /dev/null +++ b/e2e/test/mocha-javascript/test/unit/IsEven.spec.js @@ -0,0 +1,13 @@ +const { isEven } = require('../../src/IsEven'); +const { expect } = require('chai'); + +describe('isEven', () => { + + it('should be false for 1', () => { + expect(isEven(1)).false; + }); + + it('should be true for 2', () => { + expect(isEven(2)).true + }); +}); diff --git a/e2e/test/mocha-javascript/test/unit/ninjaCat.spec.js b/e2e/test/mocha-javascript/test/unit/ninjaCat.spec.js new file mode 100644 index 0000000000..7228b111c5 --- /dev/null +++ b/e2e/test/mocha-javascript/test/unit/ninjaCat.spec.js @@ -0,0 +1,10 @@ +const ninjaCatSays = require('../../src/🐱‍👓ninja.cat'); +const { expect } = require('chai'); + +describe('🐱‍👓', () => { + describe('ninjaCatSays', () => { + it('should speak', () => { + expect(ninjaCatSays('ATTACK!')).eq('🐱‍👓 ATTACK!') + }); + }); +}); diff --git a/e2e/test/mocha-javascript/verify/verify.ts b/e2e/test/mocha-javascript/verify/verify.ts new file mode 100644 index 0000000000..819a4a7b0e --- /dev/null +++ b/e2e/test/mocha-javascript/verify/verify.ts @@ -0,0 +1,29 @@ +import { expectMetricsResult, produceMetrics } from '../../../helpers'; +import fs from 'fs'; +import { expect } from 'chai'; + +describe('Verify stryker has ran correctly', () => { + + it('should report correct score', async () => { + await expectMetricsResult({ + + metrics: produceMetrics({ + killed: 26, + mutationScore: 74.29, + mutationScoreBasedOnCoveredCode: 96.3, + noCoverage: 8, + survived: 1, + totalCovered: 27, + totalDetected: 26, + totalMutants: 35, + totalUndetected: 9, + totalValid: 35 + }) + }); + }); + + it('should delete the ".stryker-tmp" dir after the successful run', () => { + expect(fs.existsSync('.stryker-tmp'), 'Expected the `.stryker-tmp` dir have been deleted.').false; + }); + +}); diff --git a/e2e/test/mocha-mocha/package.json b/e2e/test/mocha-mocha/package.json deleted file mode 100644 index 5bbb7d327d..0000000000 --- a/e2e/test/mocha-mocha/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "mocha-mocha", - "version": "0.0.0", - "private": true, - "description": "A module to perform an integration test", - "main": "index.js", - "scripts": { - "pretest": "rimraf \"reports\"", - "test": "stryker run stryker.conf.js", - "posttest": "mocha --require ../../tasks/ts-node-register.js verify/*.ts" - }, - "author": "", - "license": "ISC" -} diff --git a/e2e/test/mocha-mocha/stryker.conf.js b/e2e/test/mocha-mocha/stryker.conf.js deleted file mode 100644 index 474169a2fe..0000000000 --- a/e2e/test/mocha-mocha/stryker.conf.js +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = function (config) { - config.set({ - mutate: ['src/*.js'], - testFramework: 'mocha', - testRunner: 'mocha', - reporters: ['clear-text', 'html', 'event-recorder'], - maxConcurrentTestRunners: 2, - }); -}; diff --git a/e2e/test/mocha-mocha/verify/verify.ts b/e2e/test/mocha-mocha/verify/verify.ts deleted file mode 100644 index 56dfdf40d8..0000000000 --- a/e2e/test/mocha-mocha/verify/verify.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { expect } from 'chai'; -import * as fs from 'fs'; -import { expectMetricsResult, produceMetrics } from '../../../helpers'; - -describe('Verify stryker has ran correctly', () => { - - function expectExists(fileName: string) { - expect(fs.existsSync(fileName), `Missing ${fileName}!`).true; - } - - it('should report correct score', async () => { - await expectMetricsResult({ - metrics: produceMetrics({ - killed: 16, - mutationScore: 64, - mutationScoreBasedOnCoveredCode: 64, - survived: 9, - totalCovered: 25, - totalDetected: 16, - totalMutants: 25, - totalUndetected: 9, - totalValid: 25 - }) - }); - }); - - it('should report html files', () => { - expectExists('reports/mutation/html/index.html'); - expectExists('reports/mutation/html/mutation-test-elements.js'); - expectExists('reports/mutation/html/stryker-80x80.png'); - expectExists('reports/mutation/html/bind-mutation-test-report.js'); - }); -}); diff --git a/e2e/test/mocha-old-version/package-lock.json b/e2e/test/mocha-old-version/package-lock.json new file mode 100644 index 0000000000..f1338631ac --- /dev/null +++ b/e2e/test/mocha-old-version/package-lock.json @@ -0,0 +1,196 @@ +{ + "name": "mocha-old-version", + "version": "0.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "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" + } + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", + "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", + "dev": true, + "requires": { + "browser-stdout": "1.3.1", + "commander": "2.15.1", + "debug": "3.1.0", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.5", + "he": "1.1.1", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "supports-color": "5.4.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + } + } +} diff --git a/e2e/test/mocha-old-version/package.json b/e2e/test/mocha-old-version/package.json new file mode 100644 index 0000000000..4c1ba9a491 --- /dev/null +++ b/e2e/test/mocha-old-version/package.json @@ -0,0 +1,24 @@ +{ + "name": "mocha-old-version", + "version": "0.0.0", + "private": true, + "description": "A test package for mocha 5", + "main": "index.js", + "scripts": { + "pretest": "rimraf \"reports\"", + "test": "stryker run", + "posttest": "mocha --no-config --require ../../tasks/ts-node-register.js verify/*.ts" + }, + "localDependencies": { + "@stryker-mutator/api": "../../../packages/api", + "@stryker-mutator/core": "../../../packages/core", + "@stryker-mutator/instrumenter": "../../../packages/instrumenter", + "@stryker-mutator/mocha-runner": "../../../packages/mocha-runner", + "@stryker-mutator/util": "../../../packages/util" + }, + "author": "", + "license": "ISC", + "devDependencies": { + "mocha": "~5.2.0" + } +} diff --git a/e2e/test/mocha-old-version/src/add.js b/e2e/test/mocha-old-version/src/add.js new file mode 100644 index 0000000000..c76f6add0d --- /dev/null +++ b/e2e/test/mocha-old-version/src/add.js @@ -0,0 +1,6 @@ +module.exports.add = function(num1, num2) { + return num1 + num2; +}; + + + diff --git a/e2e/test/mocha-old-version/stryker.conf.json b/e2e/test/mocha-old-version/stryker.conf.json new file mode 100644 index 0000000000..19964caca3 --- /dev/null +++ b/e2e/test/mocha-old-version/stryker.conf.json @@ -0,0 +1,14 @@ +{ + "$schema": "../../node_modules/@stryker-mutator/core/schema/stryker-schema.json", + "testRunner": "mocha", + "concurrency": 1, + "coverageAnalysis": "off", + "reporters": ["clear-text", "html", "event-recorder"], + "mochaOptions": { + "spec": ["test/**/*.js"] + }, + "fileLogLevel": "info", + "plugins": [ + "@stryker-mutator/mocha-runner" + ] +} diff --git a/e2e/test/mocha-old-version/test/unit/add.spec.js b/e2e/test/mocha-old-version/test/unit/add.spec.js new file mode 100644 index 0000000000..746f6a6a58 --- /dev/null +++ b/e2e/test/mocha-old-version/test/unit/add.spec.js @@ -0,0 +1,10 @@ +const { add } = require('../../src/add'); +const { expect } = require('chai'); + +describe('add', () => { + + it('2 + 3 = 5', () => { + expect(add(2, 3)).to.be.equal(5); + }); + +}); diff --git a/e2e/test/mocha-old-version/verify/verify.ts b/e2e/test/mocha-old-version/verify/verify.ts new file mode 100644 index 0000000000..5b0cd6bc49 --- /dev/null +++ b/e2e/test/mocha-old-version/verify/verify.ts @@ -0,0 +1,17 @@ +import { promises as fs } from 'fs'; +import { expect } from 'chai'; +import { it } from 'mocha'; + +describe('Verify stryker runs with mocha < 6', () => { + + let strykerLog: string; + + before(async () => { + strykerLog = await fs.readFile('./stryker.log', 'utf8'); + }); + + it('should warn about old mocha version', async () => { + expect(strykerLog).contains('DEPRECATED: Mocha < 6 detected. Please upgrade to at least Mocha version 6. Stryker will drop support for Mocha < 6 in V5'); + }); + +}); diff --git a/e2e/test/mocha-ts-node/.mocharc.js b/e2e/test/mocha-ts-node/.mocharc.js new file mode 100644 index 0000000000..ed4b48d6a1 --- /dev/null +++ b/e2e/test/mocha-ts-node/.mocharc.js @@ -0,0 +1,4 @@ +module.exports = { + require: require.resolve('ts-node/register'), + spec: 'test/**/*.ts' +} diff --git a/e2e/test/mocha-ts-node/package.json b/e2e/test/mocha-ts-node/package.json index 2b76b3468d..e8733b167a 100644 --- a/e2e/test/mocha-ts-node/package.json +++ b/e2e/test/mocha-ts-node/package.json @@ -3,10 +3,6 @@ "description": "A test for mocha using ts-node (no transpiler) using mocha package config", "scripts": { "test": "stryker run", - "posttest": "mocha --no-package --require \"ts-node/register\" verify/verify.ts" - }, - "mocha": { - "require": "ts-node/register", - "spec": "test/**/*.ts" + "posttest": "mocha --no-package --no-config --require \"../../tasks/ts-node-register.js\" verify/verify.ts" } } diff --git a/e2e/test/mocha-ts-node/stryker.conf.json b/e2e/test/mocha-ts-node/stryker.conf.json index bd18c03bdb..1b0d58c7f8 100644 --- a/e2e/test/mocha-ts-node/stryker.conf.json +++ b/e2e/test/mocha-ts-node/stryker.conf.json @@ -1,16 +1,14 @@ { - "$schema": "https://raw.githubusercontent.com/stryker-mutator/stryker/master/packages/api/schema/stryker-core.json", - "mutator": "typescript", - "mutate": [ - "{src,lib}/**/*.ts?(x)" - ], + "$schema": "../../node_modules/@stryker-mutator/core/schema/stryker-schema.json", "packageManager": "npm", "testRunner": "mocha", - "maxConcurrentTestRunners": 2, - "coverageAnalysis": "off", - "reporters": ["event-recorder"], - "mocha": { - "package": "package.json" - }, - "tsconfigFile": "tsconfig.json" + "concurrency": 1, + "coverageAnalysis": "perTest", + "reporters": ["event-recorder", "html", "progress", "clear-text"], + "checkers": ["typescript"], + "tsconfigFile": "tsconfig.json", + "plugins": [ + "@stryker-mutator/mocha-runner", + "@stryker-mutator/typescript-checker" + ] } diff --git a/e2e/test/mocha-ts-node/tsconfig.json b/e2e/test/mocha-ts-node/tsconfig.json index b0fd819ba6..9425ec6af1 100644 --- a/e2e/test/mocha-ts-node/tsconfig.json +++ b/e2e/test/mocha-ts-node/tsconfig.json @@ -1,6 +1,8 @@ { "compilerOptions": { "lib": ["ES2017"], - "target": "ES2017" - } + "target": "ES2017", + "types": ["mocha", "node"] + }, + "include": ["src", "test"] } diff --git a/e2e/test/mocha-ts-node/verify/verify.ts b/e2e/test/mocha-ts-node/verify/verify.ts index 958b64edf0..b7f82f66fb 100644 --- a/e2e/test/mocha-ts-node/verify/verify.ts +++ b/e2e/test/mocha-ts-node/verify/verify.ts @@ -10,7 +10,7 @@ describe('Verify stryker has ran correctly', () => { noCoverage: 0, survived: 0, timeout: 0, - runtimeErrors: 1 + compileErrors: 1 }); }); }); diff --git a/e2e/test/mono-schema/package.json b/e2e/test/mono-schema/package.json index 16c593215b..df192db005 100644 --- a/e2e/test/mono-schema/package.json +++ b/e2e/test/mono-schema/package.json @@ -2,6 +2,6 @@ "name": "mono-schema", "description": "A test for the 'mono-schema'. A json schema that got merged from all the objects and put into @stryker-mutator/core/schema", "scripts": { - "test": "mocha --require \"ts-node/register\" verify/verify.ts" + "test": "mocha --require \"../../tasks/ts-node-register.js\" verify/verify.ts" } } diff --git a/e2e/test/mono-schema/test/invalid.json b/e2e/test/mono-schema/test/invalid.json index 317deee6fb..52145eecff 100644 --- a/e2e/test/mono-schema/test/invalid.json +++ b/e2e/test/mono-schema/test/invalid.json @@ -1,27 +1,13 @@ { "$schema": "../../../node_modules/@stryker-mutator/core/schema/stryker-schema.json", "allowConsoleColors": true, - "babel": { - "options": { - "compact": "invalid" - } - }, "jest": { "config": "" }, - "wct": { - "configFile": {} - }, "jasmineConfigFile": false, - "webpack": { - "configFile": [] - }, "karma": { "ngConfig": { "testArguments": "--test test" } - }, - "tsconfig": { - "moduleResolution": "invalid" } } diff --git a/e2e/test/mono-schema/verify/verify.ts b/e2e/test/mono-schema/verify/verify.ts index ae04d70dcb..bdf452128f 100644 --- a/e2e/test/mono-schema/verify/verify.ts +++ b/e2e/test/mono-schema/verify/verify.ts @@ -27,21 +27,12 @@ describe('The Stryker meta schema', () => { expect(validator(valid), ajv.errorsText(validator.errors)).true; }); - it('should invalidate a invalid schema', async () => { + it('should invalidate an invalid schema', async () => { expect(validator(invalid)).false; expect(validator.errors).deep.eq(expectedErrors); }); const expectedErrors = [ - { - keyword: 'enum', - dataPath: '.babel.options.compact', - schemaPath: 'http://json.schemastore.org/babelrc/properties/compact/enum', - params: { - allowedValues: ['auto', true, false], - }, - message: 'should be equal to one of the allowed values', - }, { keyword: 'type', dataPath: '.jasmineConfigFile', @@ -69,51 +60,5 @@ describe('The Stryker meta schema', () => { }, message: 'should be object', }, - { - keyword: 'enum', - dataPath: '.tsconfig.moduleResolution', - schemaPath: - 'http://json.schemastore.org/tsconfig#/definitions/compilerOptionsDefinition/properties/compilerOptions/properties/moduleResolution/anyOf/0/enum', - params: { - allowedValues: ['Classic', 'Node'], - }, - message: 'should be equal to one of the allowed values', - }, - { - keyword: 'pattern', - dataPath: '.tsconfig.moduleResolution', - schemaPath: - 'http://json.schemastore.org/tsconfig#/definitions/compilerOptionsDefinition/properties/compilerOptions/properties/moduleResolution/anyOf/1/pattern', - params: { - pattern: '^(([Nn]ode)|([Cc]lassic))$', - }, - message: 'should match pattern "^(([Nn]ode)|([Cc]lassic))$"', - }, - { - keyword: 'anyOf', - dataPath: '.tsconfig.moduleResolution', - schemaPath: - 'http://json.schemastore.org/tsconfig#/definitions/compilerOptionsDefinition/properties/compilerOptions/properties/moduleResolution/anyOf', - params: {}, - message: 'should match some schema in anyOf', - }, - { - keyword: 'type', - dataPath: '.wct.configFile', - schemaPath: '#/properties/wct/properties/configFile/type', - params: { - type: 'string', - }, - message: 'should be string', - }, - { - keyword: 'type', - dataPath: '.webpack.configFile', - schemaPath: '#/properties/webpack/properties/configFile/type', - params: { - type: 'string', - }, - message: 'should be string', - }, ]; }); diff --git a/e2e/test/plugin-options-validation/package.json b/e2e/test/plugin-options-validation/package.json index 07ff9e9ca6..faafbf1ba5 100644 --- a/e2e/test/plugin-options-validation/package.json +++ b/e2e/test/plugin-options-validation/package.json @@ -3,6 +3,6 @@ "scripts": { "pretest": "rimraf stryker.log", "test": "stryker run --fileLogLevel info stryker-error-in-plugin-options.conf.json || exit 0", - "posttest": "mocha --require \"ts-node/register\" verify/verify.ts" + "posttest": "mocha --require \"../../tasks/ts-node-register.js\" verify/verify.ts" } } diff --git a/e2e/test/plugin-options-validation/stryker-error-in-plugin-options.conf.json b/e2e/test/plugin-options-validation/stryker-error-in-plugin-options.conf.json index 26f3aa9e92..fe93388355 100644 --- a/e2e/test/plugin-options-validation/stryker-error-in-plugin-options.conf.json +++ b/e2e/test/plugin-options-validation/stryker-error-in-plugin-options.conf.json @@ -1,21 +1,12 @@ { - "$schema": "https://raw.githubusercontent.com/stryker-mutator/stryker/master/packages/api/schema/stryker-core.json", + "$schema": "../../node_modules/@stryker-mutator/core/schema/stryker-schema.json", "mochaOptions": { "spec": "this should have been an array" }, - "tsconfigFile": 42, - "babel": { - "extensions": "should be an array" - }, "jasmineConfigFile": { "should": "be a string" }, "karma": { "projectType": "Project type not supported" - }, - "webpack": { - "configFile": [ - "should be a string" - ] } } diff --git a/e2e/test/plugin-options-validation/verify/verify.ts b/e2e/test/plugin-options-validation/verify/verify.ts index bbe8a2c848..f2d22e412c 100644 --- a/e2e/test/plugin-options-validation/verify/verify.ts +++ b/e2e/test/plugin-options-validation/verify/verify.ts @@ -6,11 +6,8 @@ describe('Verify errors', () => { it('should report the expected errors', async () => { const logFile = await readLogFile(); expect(logFile).includes('Config option "mochaOptions.spec" has the wrong type'); - expect(logFile).includes('Config option "tsconfigFile" has the wrong type'); - expect(logFile).includes('Config option "babel.extensions" has the wrong type'); expect(logFile).includes('Config option "jasmineConfigFile" has the wrong type'); expect(logFile).not.includes('Config option "karma.projectType" has the wrong type'); expect(logFile).includes('Config option "karma.projectType" should be one of the allowed values'); - expect(logFile).includes('Config option "webpack.configFile" has the wrong type'); }); }); diff --git a/e2e/test/polymer-project/.gitignore b/e2e/test/polymer-project/.gitignore deleted file mode 100644 index c91f6ddc06..0000000000 --- a/e2e/test/polymer-project/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -bower_components* -bower-*.json -node_modules -*.d.ts -*.tgz diff --git a/e2e/test/polymer-project/package-lock.json b/e2e/test/polymer-project/package-lock.json deleted file mode 100644 index b2caba9615..0000000000 --- a/e2e/test/polymer-project/package-lock.json +++ /dev/null @@ -1,9813 +0,0 @@ -{ - "name": "polymer-project", - "version": "3.0.1", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@babel/code-frame": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", - "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.0.0" - } - }, - "@babel/core": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.5.5.tgz", - "integrity": "sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.5.5", - "@babel/helpers": "^7.5.5", - "@babel/parser": "^7.5.5", - "@babel/template": "^7.4.4", - "@babel/traverse": "^7.5.5", - "@babel/types": "^7.5.5", - "convert-source-map": "^1.1.0", - "debug": "^4.1.0", - "json5": "^2.1.0", - "lodash": "^4.17.13", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "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 - } - } - }, - "@babel/generator": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.5.5.tgz", - "integrity": "sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ==", - "dev": true, - "requires": { - "@babel/types": "^7.5.5", - "jsesc": "^2.5.1", - "lodash": "^4.17.13", - "source-map": "^0.5.0", - "trim-right": "^1.0.1" - }, - "dependencies": { - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - } - } - }, - "@babel/helper-annotate-as-pure": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz", - "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.1.0.tgz", - "integrity": "sha512-qNSR4jrmJ8M1VMM9tibvyRAHXQs2PmaksQF7c1CGJNipfe3D8p+wgNwgso/P2A2r2mdgBWAXljNWR0QRZAMW8w==", - "dev": true, - "requires": { - "@babel/helper-explode-assignable-expression": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-call-delegate": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.4.4.tgz", - "integrity": "sha512-l79boDFJ8S1c5hvQvG+rc+wHw6IuH7YldmRKsYtpbawsxURu/paVy57FZMomGK22/JckepaikOkY0MoAmdyOlQ==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.4.4", - "@babel/traverse": "^7.4.4", - "@babel/types": "^7.4.4" - } - }, - "@babel/helper-define-map": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.5.5.tgz", - "integrity": "sha512-fTfxx7i0B5NJqvUOBBGREnrqbTxRh7zinBANpZXAVDlsZxYdclDp467G1sQ8VZYMnAURY3RpBUAgOYT9GfzHBg==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/types": "^7.5.5", - "lodash": "^4.17.13" - }, - "dependencies": { - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - } - } - }, - "@babel/helper-explode-assignable-expression": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.1.0.tgz", - "integrity": "sha512-NRQpfHrJ1msCHtKjbzs9YcMmJZOg6mQMmGRB+hbamEdG5PNpaSm95275VD92DvJKuyl0s2sFiDmMZ+EnnvufqA==", - "dev": true, - "requires": { - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-function-name": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", - "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.0.0", - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", - "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.4.4.tgz", - "integrity": "sha512-VYk2/H/BnYbZDDg39hr3t2kKyifAm1W6zHRfhx8jGjIHpQEBv9dry7oQ2f3+J703TLu69nYdxsovl0XYfcnK4w==", - "dev": true, - "requires": { - "@babel/types": "^7.4.4" - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.5.5.tgz", - "integrity": "sha512-5qZ3D1uMclSNqYcXqiHoA0meVdv+xUEex9em2fqMnrk/scphGlGgg66zjMrPJESPwrFJ6sbfFQYUSa0Mz7FabA==", - "dev": true, - "requires": { - "@babel/types": "^7.5.5" - } - }, - "@babel/helper-module-imports": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", - "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-module-transforms": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz", - "integrity": "sha512-jBeCvETKuJqeiaCdyaheF40aXnnU1+wkSiUs/IQg3tB85up1LyL8x77ClY8qJpuRJUcXQo+ZtdNESmZl4j56Pw==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-simple-access": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/template": "^7.4.4", - "@babel/types": "^7.5.5", - "lodash": "^4.17.13" - }, - "dependencies": { - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - } - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.0.0.tgz", - "integrity": "sha512-u8nd9NQePYNQV8iPWu/pLLYBqZBa4ZaY1YWRFMuxrid94wKI1QNt67NEZ7GAe5Kc/0LLScbim05xZFWkAdrj9g==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", - "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", - "dev": true - }, - "@babel/helper-regex": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.5.5.tgz", - "integrity": "sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw==", - "dev": true, - "requires": { - "lodash": "^4.17.13" - }, - "dependencies": { - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - } - } - }, - "@babel/helper-remap-async-to-generator": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz", - "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-wrap-function": "^7.1.0", - "@babel/template": "^7.1.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-replace-supers": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.5.5.tgz", - "integrity": "sha512-XvRFWrNnlsow2u7jXDuH4jDDctkxbS7gXssrP4q2nUD606ukXHRvydj346wmNg+zAgpFx4MWf4+usfC93bElJg==", - "dev": true, - "requires": { - "@babel/helper-member-expression-to-functions": "^7.5.5", - "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/traverse": "^7.5.5", - "@babel/types": "^7.5.5" - } - }, - "@babel/helper-simple-access": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz", - "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==", - "dev": true, - "requires": { - "@babel/template": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", - "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", - "dev": true, - "requires": { - "@babel/types": "^7.4.4" - } - }, - "@babel/helper-wrap-function": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz", - "integrity": "sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/template": "^7.1.0", - "@babel/traverse": "^7.1.0", - "@babel/types": "^7.2.0" - } - }, - "@babel/helpers": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.5.5.tgz", - "integrity": "sha512-nRq2BUhxZFnfEn/ciJuhklHvFOqjJUD5wpx+1bxUF2axL9C+v4DE/dmp5sT2dKnpOs4orZWzpAZqlCy8QqE/7g==", - "dev": true, - "requires": { - "@babel/template": "^7.4.4", - "@babel/traverse": "^7.5.5", - "@babel/types": "^7.5.5" - } - }, - "@babel/highlight": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", - "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "@babel/parser": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.5.5.tgz", - "integrity": "sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g==", - "dev": true - }, - "@babel/plugin-external-helpers": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-external-helpers/-/plugin-external-helpers-7.2.0.tgz", - "integrity": "sha512-QFmtcCShFkyAsNtdCM3lJPmRe1iB+vPZymlB4LnDIKEBj2yKQLQKtoxXxJ8ePT5fwMl4QGg303p4mB0UsSI2/g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-proposal-async-generator-functions": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz", - "integrity": "sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.1.0", - "@babel/plugin-syntax-async-generators": "^7.2.0" - } - }, - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.5.5.tgz", - "integrity": "sha512-F2DxJJSQ7f64FyTVl5cw/9MWn6naXGdk3Q3UhDbFEEHv+EilCPoeRD3Zh/Utx1CJz4uyKlQ4uH+bJPbEhMV7Zw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-object-rest-spread": "^7.2.0" - } - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz", - "integrity": "sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-syntax-dynamic-import": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz", - "integrity": "sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-syntax-import-meta": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.2.0.tgz", - "integrity": "sha512-Hq6kFSZD7+PHkmBN8bCpHR6J8QEoCuEV/B38AIQscYjgMZkGlXB7cHNFzP5jR4RCh5545yP1ujHdmO7hAgKtBA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz", - "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-arrow-functions": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz", - "integrity": "sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-async-to-generator": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.5.0.tgz", - "integrity": "sha512-mqvkzwIGkq0bEF1zLRRiTdjfomZJDV33AH3oQzHVGkI2VzEmXLpKKOBvEVaFZBJdN0XTyH38s9j/Kiqr68dggg==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.1.0" - } - }, - "@babel/plugin-transform-block-scoped-functions": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz", - "integrity": "sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-block-scoping": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.5.5.tgz", - "integrity": "sha512-82A3CLRRdYubkG85lKwhZB0WZoHxLGsJdux/cOVaJCJpvYFl1LVzAIFyRsa7CvXqW8rBM4Zf3Bfn8PHt5DP0Sg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "lodash": "^4.17.13" - }, - "dependencies": { - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - } - } - }, - "@babel/plugin-transform-classes": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.5.5.tgz", - "integrity": "sha512-U2htCNK/6e9K7jGyJ++1p5XRU+LJjrwtoiVn9SzRlDT2KubcZ11OOwy3s24TjHxPgxNwonCYP7U2K51uVYCMDg==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-define-map": "^7.5.5", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-optimise-call-expression": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.5.5", - "@babel/helper-split-export-declaration": "^7.4.4", - "globals": "^11.1.0" - } - }, - "@babel/plugin-transform-computed-properties": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz", - "integrity": "sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-destructuring": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.5.0.tgz", - "integrity": "sha512-YbYgbd3TryYYLGyC7ZR+Tq8H/+bCmwoaxHfJHupom5ECstzbRLTch6gOQbhEY9Z4hiCNHEURgq06ykFv9JZ/QQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-duplicate-keys": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz", - "integrity": "sha512-igcziksHizyQPlX9gfSjHkE2wmoCH3evvD2qR5w29/Dk0SMKE/eOI7f1HhBdNhR/zxJDqrgpoDTq5YSLH/XMsQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-exponentiation-operator": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz", - "integrity": "sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==", - "dev": true, - "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-for-of": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz", - "integrity": "sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-function-name": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.4.4.tgz", - "integrity": "sha512-iU9pv7U+2jC9ANQkKeNF6DrPy4GBa4NWQtl6dHB4Pb3izX2JOEvDTFarlNsBj/63ZEzNNIAMs3Qw4fNCcSOXJA==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-instanceof": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-instanceof/-/plugin-transform-instanceof-7.5.5.tgz", - "integrity": "sha512-95lPQPIwKKa9J2aRrhttOnoheWtwZQnIxK7w7HaLDtRP7jMunUkoHZ7IdXWBHk6z3yaecMZbGJVR/Co8vrnOrA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-literals": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz", - "integrity": "sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-modules-amd": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz", - "integrity": "sha512-n20UsQMKnWrltocZZm24cRURxQnWIvsABPJlw/fvoy9c6AgHZzoelAIzajDHAQrDpuKFFPPcFGd7ChsYuIUMpg==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0", - "babel-plugin-dynamic-import-node": "^2.3.0" - } - }, - "@babel/plugin-transform-object-super": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz", - "integrity": "sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.5.5" - } - }, - "@babel/plugin-transform-parameters": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz", - "integrity": "sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw==", - "dev": true, - "requires": { - "@babel/helper-call-delegate": "^7.4.4", - "@babel/helper-get-function-arity": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-regenerator": { - "version": "7.4.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.4.5.tgz", - "integrity": "sha512-gBKRh5qAaCWntnd09S8QC7r3auLCqq5DI6O0DlfoyDjslSBVqBibrMdsqO+Uhmx3+BlOmE/Kw1HFxmGbv0N9dA==", - "dev": true, - "requires": { - "regenerator-transform": "^0.14.0" - } - }, - "@babel/plugin-transform-shorthand-properties": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz", - "integrity": "sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-spread": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.2.2.tgz", - "integrity": "sha512-KWfky/58vubwtS0hLqEnrWJjsMGaOeSBn90Ezn5Jeg9Z8KKHmELbP1yGylMlm5N6TPKeY9A2+UaSYLdxahg01w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-sticky-regex": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz", - "integrity": "sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0" - } - }, - "@babel/plugin-transform-template-literals": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz", - "integrity": "sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-typeof-symbol": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz", - "integrity": "sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0" - } - }, - "@babel/plugin-transform-unicode-regex": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.4.4.tgz", - "integrity": "sha512-il+/XdNw01i93+M9J9u4T7/e/Ue/vWfNZE4IRUQjplu2Mqb/AFTDimkw2tdEdSH50wuQXZAbXSql0UphQke+vA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.4.4", - "regexpu-core": "^4.5.4" - } - }, - "@babel/template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", - "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.4.4", - "@babel/types": "^7.4.4" - } - }, - "@babel/traverse": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.5.5.tgz", - "integrity": "sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.5.5", - "@babel/helper-function-name": "^7.1.0", - "@babel/helper-split-export-declaration": "^7.4.4", - "@babel/parser": "^7.5.5", - "@babel/types": "^7.5.5", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.13" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "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 - } - } - }, - "@babel/types": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.5.5.tgz", - "integrity": "sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw==", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "lodash": "^4.17.13", - "to-fast-properties": "^2.0.0" - }, - "dependencies": { - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - } - } - }, - "@mrmlnc/readdir-enhanced": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", - "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", - "dev": true, - "requires": { - "call-me-maybe": "^1.0.1", - "glob-to-regexp": "^0.3.0" - } - }, - "@nodelib/fs.stat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", - "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", - "dev": true - }, - "@polymer/esm-amd-loader": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@polymer/esm-amd-loader/-/esm-amd-loader-1.0.4.tgz", - "integrity": "sha512-h+hqYkL+tQV/y2ESD5gFXMl5z4cC+XY1jTlBeGSBaTcj3VbB5OBEScbvRXm63NcEbBneQQYbHfBAXAkF9i9wIA==", - "dev": true - }, - "@polymer/font-roboto": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@polymer/font-roboto/-/font-roboto-3.0.2.tgz", - "integrity": "sha512-tx5TauYSmzsIvmSqepUPDYbs4/Ejz2XbZ1IkD7JEGqkdNUJlh+9KU85G56Tfdk/xjEZ8zorFfN09OSwiMrIQWA==" - }, - "@polymer/iron-a11y-keys-behavior": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@polymer/iron-a11y-keys-behavior/-/iron-a11y-keys-behavior-3.0.1.tgz", - "integrity": "sha512-lnrjKq3ysbBPT/74l0Fj0U9H9C35Tpw2C/tpJ8a+5g8Y3YJs1WSZYnEl1yOkw6sEyaxOq/1DkzH0+60gGu5/PQ==", - "requires": { - "@polymer/polymer": "^3.0.0" - } - }, - "@polymer/iron-behaviors": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@polymer/iron-behaviors/-/iron-behaviors-3.0.1.tgz", - "integrity": "sha512-IMEwcv1lhf1HSQxuyWOUIL0lOBwmeaoSTpgCJeP9IBYnuB1SPQngmfRuHKgK6/m9LQ9F9miC7p3HeQQUdKAE0w==", - "requires": { - "@polymer/iron-a11y-keys-behavior": "^3.0.0-pre.26", - "@polymer/polymer": "^3.0.0" - } - }, - "@polymer/iron-checked-element-behavior": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@polymer/iron-checked-element-behavior/-/iron-checked-element-behavior-3.0.1.tgz", - "integrity": "sha512-aDr0cbCNVq49q+pOqa6CZutFh+wWpwPMLpEth9swx+GkAj+gCURhuQkaUYhIo5f2egDbEioR1aeHMnPlU9dQZA==", - "requires": { - "@polymer/iron-form-element-behavior": "^3.0.0-pre.26", - "@polymer/iron-validatable-behavior": "^3.0.0-pre.26", - "@polymer/polymer": "^3.0.0" - } - }, - "@polymer/iron-demo-helpers": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@polymer/iron-demo-helpers/-/iron-demo-helpers-3.1.0.tgz", - "integrity": "sha512-C+U9ghRnjluJNLIga7r30YGNuQeCu7E7mOOcjgWOL/bMfWvrnbr2TcYoO4DXHO6NdUfV6daGtRA1VwG3d8H39g==", - "dev": true, - "requires": { - "@polymer/font-roboto": "^3.0.0-pre.25", - "@polymer/iron-flex-layout": "^3.0.0-pre.25", - "@polymer/iron-location": "^3.0.0-pre.25", - "@polymer/marked-element": "^3.0.0-pre.25", - "@polymer/polymer": "^3.0.0", - "@polymer/prism-element": "^3.0.0-pre.25" - } - }, - "@polymer/iron-flex-layout": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@polymer/iron-flex-layout/-/iron-flex-layout-3.0.1.tgz", - "integrity": "sha512-7gB869czArF+HZcPTVSgvA7tXYFze9EKckvM95NB7SqYF+NnsQyhoXgKnpFwGyo95lUjUW9TFDLUwDXnCYFtkw==", - "requires": { - "@polymer/polymer": "^3.0.0" - } - }, - "@polymer/iron-form-element-behavior": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@polymer/iron-form-element-behavior/-/iron-form-element-behavior-3.0.1.tgz", - "integrity": "sha512-G/e2KXyL5AY7mMjmomHkGpgS0uAf4ovNpKhkuUTRnMuMJuf589bKqE85KN4ovE1Tzhv2hJoh/igyD6ekHiYU1A==", - "requires": { - "@polymer/polymer": "^3.0.0" - } - }, - "@polymer/iron-icon": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@polymer/iron-icon/-/iron-icon-3.0.1.tgz", - "integrity": "sha512-QLPwirk+UPZNaLnMew9VludXA4CWUCenRewgEcGYwdzVgDPCDbXxy6vRJjmweZobMQv/oVLppT2JZtJFnPxX6g==", - "dev": true, - "requires": { - "@polymer/iron-flex-layout": "^3.0.0-pre.26", - "@polymer/iron-meta": "^3.0.0-pre.26", - "@polymer/polymer": "^3.0.0" - } - }, - "@polymer/iron-icons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@polymer/iron-icons/-/iron-icons-3.0.1.tgz", - "integrity": "sha512-xtEI8erH2GIBiF3QxEMyW81XuVjguu6Le5WjEEpX67qd9z7jjmc4T/ke3zRUlnDydex9p8ytcwVpMIKcyvjYAQ==", - "dev": true, - "requires": { - "@polymer/iron-icon": "^3.0.0-pre.26", - "@polymer/iron-iconset-svg": "^3.0.0-pre.26", - "@polymer/polymer": "^3.0.0" - } - }, - "@polymer/iron-iconset-svg": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@polymer/iron-iconset-svg/-/iron-iconset-svg-3.0.1.tgz", - "integrity": "sha512-XNwURbNHRw6u2fJe05O5fMYye6GSgDlDqCO+q6K1zAnKIrpgZwf2vTkBd5uCcZwsN0FyCB3mvNZx4jkh85dRDw==", - "dev": true, - "requires": { - "@polymer/iron-meta": "^3.0.0-pre.26", - "@polymer/polymer": "^3.0.0" - } - }, - "@polymer/iron-location": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@polymer/iron-location/-/iron-location-3.0.2.tgz", - "integrity": "sha512-75XlPsrm6RQUPNzWWaA0TnTQaWZUYX8UB4Q6WCjikKWzmaSCCxlBrVVYf8WRqtCxw/PeCvLn5kGL6qhTlNTCEA==", - "dev": true, - "requires": { - "@polymer/polymer": "^3.0.0" - } - }, - "@polymer/iron-meta": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@polymer/iron-meta/-/iron-meta-3.0.1.tgz", - "integrity": "sha512-pWguPugiLYmWFV9UWxLWzZ6gm4wBwQdDy4VULKwdHCqR7OP7u98h+XDdGZsSlDPv6qoryV/e3tGHlTIT0mbzJA==", - "requires": { - "@polymer/polymer": "^3.0.0" - } - }, - "@polymer/iron-test-helpers": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@polymer/iron-test-helpers/-/iron-test-helpers-3.0.1.tgz", - "integrity": "sha512-2R7dnGcW2eg95i7LhYWWUO4AlAk6qXsPnKoyeN2R1t0km0ECMx0jjwqeLwCo8/7LwuVPZSiarI4DK7jyU7fJLQ==", - "dev": true, - "requires": { - "@polymer/polymer": "^3.0.0" - } - }, - "@polymer/iron-validatable-behavior": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@polymer/iron-validatable-behavior/-/iron-validatable-behavior-3.0.1.tgz", - "integrity": "sha512-wwpYh6wOa4fNI+jH5EYKC7TVPYQ2OfgQqocWat7GsNWcsblKYhLYbwsvEY5nO0n2xKqNfZzDLrUom5INJN7msQ==", - "requires": { - "@polymer/iron-meta": "^3.0.0-pre.26", - "@polymer/polymer": "^3.0.0" - } - }, - "@polymer/marked-element": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@polymer/marked-element/-/marked-element-3.0.1.tgz", - "integrity": "sha512-WJQzQetxdStVGQbyTBUBgd+hSI0Rl39uJg7b2zL3r6EfMnibzmA/YNT06M8jVZdxPF+B4SumrFWRtasVtGQRUQ==", - "dev": true, - "requires": { - "@polymer/polymer": "^3.0.0", - "marked": "~0.3.9" - } - }, - "@polymer/paper-behaviors": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@polymer/paper-behaviors/-/paper-behaviors-3.0.1.tgz", - "integrity": "sha512-6knhj69fPJejv8qR0kCSUY+Q0XjaUf0OSnkjRjmTJPAwSrRYtgqE+l6P1FfA+py1X/cUjgne9EF5rMZAKJIg1g==", - "requires": { - "@polymer/iron-behaviors": "^3.0.0-pre.26", - "@polymer/iron-checked-element-behavior": "^3.0.0-pre.26", - "@polymer/paper-ripple": "^3.0.0-pre.26", - "@polymer/polymer": "^3.0.0" - } - }, - "@polymer/paper-ripple": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@polymer/paper-ripple/-/paper-ripple-3.0.1.tgz", - "integrity": "sha512-dgOe12GyCF1VZBLUQqnzGWlf3xb255FajNCVB1VFj/AtskYtoamnafa7m3a+1vs+C8qbg4Benn5KwgxVDSW4cg==", - "requires": { - "@polymer/iron-a11y-keys-behavior": "^3.0.0-pre.26", - "@polymer/polymer": "^3.0.0" - } - }, - "@polymer/paper-styles": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@polymer/paper-styles/-/paper-styles-3.0.1.tgz", - "integrity": "sha512-y6hmObLqlCx602TQiSBKHqjwkE7xmDiFkoxdYGaNjtv4xcysOTdVJsDR/R9UHwIaxJ7gHlthMSykir1nv78++g==", - "requires": { - "@polymer/font-roboto": "^3.0.1", - "@polymer/iron-flex-layout": "^3.0.0-pre.26", - "@polymer/polymer": "^3.0.0" - } - }, - "@polymer/polymer": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@polymer/polymer/-/polymer-3.3.0.tgz", - "integrity": "sha512-rij7suomS7DxdBamnwr/Xa0V5hpypf7I9oYKseF2FWz5Xh2a3wJNpVjgJy1adXVCxqIyPhghsrthnfCt7EblsQ==", - "requires": { - "@webcomponents/shadycss": "^1.9.1" - } - }, - "@polymer/prism-element": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@polymer/prism-element/-/prism-element-3.0.1.tgz", - "integrity": "sha512-mam3oZZwVoxmC8i2srCxaTsvCqZF2HX4yxbm1JN9OGZS2JMwu7bnjjk7O8haoj9u6w+ocUi+vTLjYeIIoPx7vQ==", - "dev": true, - "requires": { - "@polymer/polymer": "^3.0.0", - "prismjs": "^1.11.0" - } - }, - "@polymer/sinonjs": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/@polymer/sinonjs/-/sinonjs-1.17.1.tgz", - "integrity": "sha512-/U8F/cOTrbF2iVVYgINYmvKbtbexs+89Q3v8AaHADRYabTg7aOZGOb0RyWpOI+sUJt04kj63U4FwMhzW5r4wZA==", - "dev": true - }, - "@polymer/test-fixture": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@polymer/test-fixture/-/test-fixture-4.0.2.tgz", - "integrity": "sha512-tLX8tFE4mkc4p84YG5239G0hbgTVv2irZYrSyO0OblUqIRbRoCPmbydm3HRFQkJeAB3rPCtyeZ2roJULsmTG3A==", - "dev": true - }, - "@types/babel-generator": { - "version": "6.25.3", - "resolved": "https://registry.npmjs.org/@types/babel-generator/-/babel-generator-6.25.3.tgz", - "integrity": "sha512-pGgnuxVddKcYIc+VJkRDop7gxLhqclNKBdlsm/5Vp8d+37pQkkDK7fef8d9YYImRzw9xcojEPc18pUYnbxmjqA==", - "dev": true, - "requires": { - "@types/babel-types": "*" - } - }, - "@types/babel-traverse": { - "version": "6.25.5", - "resolved": "https://registry.npmjs.org/@types/babel-traverse/-/babel-traverse-6.25.5.tgz", - "integrity": "sha512-WrMbwmu+MWf8FiUMbmVOGkc7bHPzndUafn1CivMaBHthBBoo0VNIcYk1KV71UovYguhsNOwf3UF5oRmkkGOU3w==", - "dev": true, - "requires": { - "@types/babel-types": "*" - } - }, - "@types/babel-types": { - "version": "6.25.2", - "resolved": "https://registry.npmjs.org/@types/babel-types/-/babel-types-6.25.2.tgz", - "integrity": "sha512-+3bMuktcY4a70a0KZc8aPJlEOArPuAKQYHU5ErjkOqGJdx8xuEEVK6nWogqigBOJ8nKPxRpyCUDTCPmZ3bUxGA==", - "dev": true - }, - "@types/babylon": { - "version": "6.16.5", - "resolved": "https://registry.npmjs.org/@types/babylon/-/babylon-6.16.5.tgz", - "integrity": "sha512-xH2e58elpj1X4ynnKp9qSnWlsRTIs6n3tgLGNfwAGHwePw0mulHQllV34n0T25uYSu1k0hRKkWXF890B1yS47w==", - "dev": true, - "requires": { - "@types/babel-types": "*" - } - }, - "@types/bluebird": { - "version": "3.5.27", - "resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.27.tgz", - "integrity": "sha512-6BmYWSBea18+tSjjSC3QIyV93ZKAeNWGM7R6aYt1ryTZXrlHF+QLV0G2yV0viEGVyRkyQsWfMoJ0k/YghBX5sQ==", - "dev": true - }, - "@types/body-parser": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.17.1.tgz", - "integrity": "sha512-RoX2EZjMiFMjZh9lmYrwgoP9RTpAjSHiJxdp4oidAQVO02T7HER3xj9UKue5534ULWeqVEkujhWcyvUce+d68w==", - "dev": true, - "requires": { - "@types/connect": "*", - "@types/node": "*" - } - }, - "@types/chai": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.0.tgz", - "integrity": "sha512-zw8UvoBEImn392tLjxoavuonblX/4Yb9ha4KBU10FirCfwgzhKO0dvyJSF9ByxV1xK1r2AgnAi/tvQaLgxQqxA==", - "dev": true - }, - "@types/chai-subset": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.3.tgz", - "integrity": "sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==", - "dev": true, - "requires": { - "@types/chai": "*" - } - }, - "@types/chalk": { - "version": "0.4.31", - "resolved": "https://registry.npmjs.org/@types/chalk/-/chalk-0.4.31.tgz", - "integrity": "sha1-ox10JBprHtu5c8822XooloNKUfk=", - "dev": true - }, - "@types/clean-css": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@types/clean-css/-/clean-css-4.2.1.tgz", - "integrity": "sha512-A1HQhQ0hkvqqByJMgg+Wiv9p9XdoYEzuwm11SVo1mX2/4PSdhjcrUlilJQoqLscIheC51t1D5g+EFWCXZ2VTQQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/clone": { - "version": "0.1.30", - "resolved": "https://registry.npmjs.org/@types/clone/-/clone-0.1.30.tgz", - "integrity": "sha1-5zZWSMG0ITalnH1QQGN7O1yDthQ=", - "dev": true - }, - "@types/compression": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/@types/compression/-/compression-0.0.33.tgz", - "integrity": "sha1-ldxzOiM5qoRjgdfxN3eS0lU9wn0=", - "dev": true, - "requires": { - "@types/express": "*" - } - }, - "@types/connect": { - "version": "3.4.32", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.32.tgz", - "integrity": "sha512-4r8qa0quOvh7lGD0pre62CAb1oni1OO6ecJLGCezTmhQ8Fz50Arx9RUszryR8KlgK6avuSXvviL6yWyViQABOg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/content-type": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@types/content-type/-/content-type-1.1.3.tgz", - "integrity": "sha512-pv8VcFrZ3fN93L4rTNIbbUzdkzjEyVMp5mPVjsFfOYTDOZMZiZ8P1dhu+kEv3faYyKzZgLlSvnyQNFg+p/v5ug==", - "dev": true - }, - "@types/cssbeautify": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@types/cssbeautify/-/cssbeautify-0.3.1.tgz", - "integrity": "sha1-jgvuj33suVIlDaDK6+BeMFkcF+8=", - "dev": true - }, - "@types/doctrine": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/@types/doctrine/-/doctrine-0.0.1.tgz", - "integrity": "sha1-uZny2fe0PKvgoaLzm8IDvH3K2p0=", - "dev": true - }, - "@types/escape-html": { - "version": "0.0.20", - "resolved": "https://registry.npmjs.org/@types/escape-html/-/escape-html-0.0.20.tgz", - "integrity": "sha512-6dhZJLbA7aOwkYB2GDGdIqJ20wmHnkDzaxV9PJXe7O02I2dSFTERzRB6JrX6cWKaS+VqhhY7cQUMCbO5kloFUw==", - "dev": true - }, - "@types/estree": { - "version": "0.0.39", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", - "dev": true - }, - "@types/events": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", - "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", - "dev": true - }, - "@types/express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.1.tgz", - "integrity": "sha512-VfH/XCP0QbQk5B5puLqTLEeFgR8lfCJHZJKkInZ9mkYd+u8byX0kztXEQxEk4wZXJs8HI+7km2ALXjn4YKcX9w==", - "dev": true, - "requires": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "*", - "@types/serve-static": "*" - } - }, - "@types/express-serve-static-core": { - "version": "4.16.9", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.16.9.tgz", - "integrity": "sha512-GqpaVWR0DM8FnRUJYKlWgyARoBUAVfRIeVDZQKOttLFp5SmhhF9YFIYeTPwMd/AXfxlP7xVO2dj1fGu0Q+krKQ==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/range-parser": "*" - } - }, - "@types/freeport": { - "version": "1.0.21", - "resolved": "https://registry.npmjs.org/@types/freeport/-/freeport-1.0.21.tgz", - "integrity": "sha1-c/ZUPtZ9PKP/+XuYVZFZi3CSBm8=", - "dev": true, - "optional": true - }, - "@types/glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", - "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", - "dev": true, - "requires": { - "@types/events": "*", - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "@types/glob-stream": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@types/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha512-RHv6ZQjcTncXo3thYZrsbAVwoy4vSKosSWhuhuQxLOTv74OJuFQxXkmUuZCr3q9uNBEVCvIzmZL/FeRNbHZGUg==", - "dev": true, - "requires": { - "@types/glob": "*", - "@types/node": "*" - } - }, - "@types/gulp-if": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/@types/gulp-if/-/gulp-if-0.0.33.tgz", - "integrity": "sha512-J5lzff21X7r1x/4hSzn02GgIUEyjCqYIXZ9GgGBLhbsD3RiBdqwnkFWgF16/0jO5rcVZ52Zp+6MQMQdvIsWuKg==", - "dev": true, - "requires": { - "@types/node": "*", - "@types/vinyl": "*" - } - }, - "@types/html-minifier": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/@types/html-minifier/-/html-minifier-3.5.3.tgz", - "integrity": "sha512-j1P/4PcWVVCPEy5lofcHnQ6BtXz9tHGiFPWzqm7TtGuWZEfCHEP446HlkSNc9fQgNJaJZ6ewPtp2aaFla/Uerg==", - "dev": true, - "requires": { - "@types/clean-css": "*", - "@types/relateurl": "*", - "@types/uglify-js": "*" - } - }, - "@types/is-windows": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@types/is-windows/-/is-windows-0.2.0.tgz", - "integrity": "sha1-byTuSHMdMRaOpRBhDW3RXl/Jxv8=", - "dev": true - }, - "@types/launchpad": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@types/launchpad/-/launchpad-0.6.0.tgz", - "integrity": "sha1-NylhCbfyd/bmxf1+DAcGvJGPu1E=", - "dev": true, - "optional": true - }, - "@types/mime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.1.tgz", - "integrity": "sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw==", - "dev": true - }, - "@types/minimatch": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", - "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", - "dev": true - }, - "@types/mz": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/mz/-/mz-0.0.29.tgz", - "integrity": "sha1-vCRyjGSZc/HHhR6QM/nOUlZowns=", - "dev": true, - "requires": { - "@types/bluebird": "*", - "@types/node": "*" - } - }, - "@types/node": { - "version": "10.12.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", - "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==", - "dev": true - }, - "@types/opn": { - "version": "3.0.28", - "resolved": "https://registry.npmjs.org/@types/opn/-/opn-3.0.28.tgz", - "integrity": "sha1-CX0NHJtXSVc6XZbfEyOHu20CEYo=", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/parse5": { - "version": "2.2.34", - "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-2.2.34.tgz", - "integrity": "sha1-44cKEOgnNacg9i1x3NGDunjvOp0=", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/path-is-inside": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/path-is-inside/-/path-is-inside-1.0.0.tgz", - "integrity": "sha512-hfnXRGugz+McgX2jxyy5qz9sB21LRzlGn24zlwN2KEgoPtEvjzNRrLtUkOOebPDPZl3Rq7ywKxYvylVcEZDnEw==", - "dev": true - }, - "@types/pem": { - "version": "1.9.5", - "resolved": "https://registry.npmjs.org/@types/pem/-/pem-1.9.5.tgz", - "integrity": "sha512-C0txxEw8B7DCoD85Ko7SEvzUogNd5VDJ5/YBG8XUcacsOGqxr5Oo4g3OUAfdEDUbhXanwUoVh/ZkMFw77FGPQQ==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/range-parser": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", - "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==", - "dev": true - }, - "@types/relateurl": { - "version": "0.2.28", - "resolved": "https://registry.npmjs.org/@types/relateurl/-/relateurl-0.2.28.tgz", - "integrity": "sha1-a9p9uGU/piZD9e5p6facEaOS46Y=", - "dev": true - }, - "@types/resolve": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.6.tgz", - "integrity": "sha512-g+Rg8uMWY76oYTyaL+m7ZcblqF/oj7pE6uEUyACluJx4zcop1Lk14qQiocdEkEVMDFm6DmKpxJhsER+ZuTwG3g==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/serve-static": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.3.tgz", - "integrity": "sha512-oprSwp094zOglVrXdlo/4bAHtKTAxX6VT8FOZlBKrmyLbNvE1zxZyJ6yikMVtHIvwP45+ZQGJn+FdXGKTozq0g==", - "dev": true, - "requires": { - "@types/express-serve-static-core": "*", - "@types/mime": "*" - } - }, - "@types/spdy": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/@types/spdy/-/spdy-3.4.4.tgz", - "integrity": "sha512-N9LBlbVRRYq6HgYpPkqQc3a9HJ/iEtVZToW6xlTtJiMhmRJ7jJdV7TaZQJw/Ve/1ePUsQiCTDc4JMuzzag94GA==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/ua-parser-js": { - "version": "0.7.33", - "resolved": "https://registry.npmjs.org/@types/ua-parser-js/-/ua-parser-js-0.7.33.tgz", - "integrity": "sha512-ngUKcHnytUodUCL7C6EZ+lVXUjTMQb+9p/e1JjV5tN9TVzS98lHozWEFRPY1QcCdwFeMsmVWfZ3DPPT/udCyIw==", - "dev": true - }, - "@types/uglify-js": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.0.4.tgz", - "integrity": "sha512-SudIN9TRJ+v8g5pTG8RRCqfqTMNqgWCKKd3vtynhGzkIIjxaicNAMuY5TRadJ6tzDu3Dotf3ngaMILtmOdmWEQ==", - "dev": true, - "requires": { - "source-map": "^0.6.1" - }, - "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 - } - } - }, - "@types/uuid": { - "version": "3.4.5", - "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-3.4.5.tgz", - "integrity": "sha512-MNL15wC3EKyw1VLF+RoVO4hJJdk9t/Hlv3rt1OL65Qvuadm4BYo6g9ZJQqoq7X8NBFSsQXgAujWciovh2lpVjA==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/vinyl": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.3.tgz", - "integrity": "sha512-hrT6xg16CWSmndZqOTJ6BGIn2abKyTw0B58bI+7ioUoj3Sma6u8ftZ1DTI2yCaJamOVGLOnQWiPH3a74+EaqTA==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/vinyl-fs": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/@types/vinyl-fs/-/vinyl-fs-2.4.11.tgz", - "integrity": "sha512-2OzQSfIr9CqqWMGqmcERE6Hnd2KY3eBVtFaulVo3sJghplUcaeMdL9ZjEiljcQQeHjheWY9RlNmumjIAvsBNaA==", - "dev": true, - "requires": { - "@types/glob-stream": "*", - "@types/node": "*", - "@types/vinyl": "*" - } - }, - "@types/whatwg-url": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-6.4.0.tgz", - "integrity": "sha512-tonhlcbQ2eho09am6RHnHOgvtDfDYINd5rgxD+2YSkKENooVCFsWizJz139MQW/PV8FfClyKrNe9ZbdHrSCxGg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@types/which/-/which-1.3.1.tgz", - "integrity": "sha512-ZrJDWpvg75LTGX4XwuneY9s6bF3OeZcGTpoGh3zDV9ytzcHMFsRrMIaLBRJZQMBoGyKs6unBQfVdrLZiYfb1zQ==", - "dev": true, - "optional": true - }, - "@webcomponents/shadycss": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@webcomponents/shadycss/-/shadycss-1.9.1.tgz", - "integrity": "sha512-IaZOnWOKXHghqk/WfPNDRIgDBi3RsVPY2IFAw6tYiL9UBGvQRy5R6uC+Fk7qTZsReTJ0xh5MTT8yAcb3MUR4mQ==" - }, - "@webcomponents/webcomponentsjs": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@webcomponents/webcomponentsjs/-/webcomponentsjs-2.3.0.tgz", - "integrity": "sha512-sR6FOrNnnncRuoJDqq9QxtRsJMbIvASw4vnJwIYKVlKO3AMc+NAr/bIQNnUiTTE9pBDTJkFpVaUdjJaRdsjmyA==", - "dev": true - }, - "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", - "dev": true, - "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" - } - }, - "accessibility-developer-tools": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/accessibility-developer-tools/-/accessibility-developer-tools-2.12.0.tgz", - "integrity": "sha1-PaDM6dbsY3OWS4TzXbfPw996tRQ=", - "dev": true - }, - "acorn": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", - "dev": true - }, - "acorn-jsx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", - "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", - "dev": true, - "requires": { - "acorn": "^3.0.4" - }, - "dependencies": { - "acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", - "dev": true - } - } - }, - "adm-zip": { - "version": "0.4.13", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.13.tgz", - "integrity": "sha512-fERNJX8sOXfel6qCBCMPvZLzENBEhZTzKqg6vrOW5pvoEaQuJhRU4ndTAh6lHOxn1I6jnz2NHra56ZODM751uw==", - "dev": true, - "optional": true - }, - "after": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", - "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=", - "dev": true - }, - "agent-base": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz", - "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", - "dev": true, - "optional": true, - "requires": { - "es6-promisify": "^5.0.0" - }, - "dependencies": { - "es6-promisify": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz", - "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", - "dev": true, - "optional": true, - "requires": { - "es6-promise": "^4.0.3" - } - } - } - }, - "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", - "dev": true, - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-align": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", - "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", - "dev": true, - "requires": { - "string-width": "^2.0.0" - } - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=", - "dev": true - }, - "append-field": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", - "integrity": "sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=", - "dev": true - }, - "archiver": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-3.1.1.tgz", - "integrity": "sha512-5Hxxcig7gw5Jod/8Gq0OneVgLYET+oNHcxgWItq4TbhOzRLKNAFUb9edAftiMKXvXfCB0vbGrJdZDNq0dWMsxg==", - "dev": true, - "requires": { - "archiver-utils": "^2.1.0", - "async": "^2.6.3", - "buffer-crc32": "^0.2.1", - "glob": "^7.1.4", - "readable-stream": "^3.4.0", - "tar-stream": "^2.1.0", - "zip-stream": "^2.1.2" - }, - "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" - } - }, - "bl": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-3.0.0.tgz", - "integrity": "sha512-EUAyP5UHU5hxF8BPT0LKW8gjYLhq1DQIcneOX/pL/m2Alo+OYDQAJlHq+yseMP50Os2nHXOSic6Ss3vSQeyf4A==", - "dev": true, - "requires": { - "readable-stream": "^3.0.1" - } - }, - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "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 - }, - "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" - } - }, - "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 - }, - "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" - } - }, - "tar-stream": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.0.tgz", - "integrity": "sha512-+DAn4Nb4+gz6WZigRzKEZl1QuJVOLtAwwF+WUxy1fJ6X63CaGaUAxJRD2KEn1OMfcbCjySTYpNC6WmfQoIEOdw==", - "dev": true, - "requires": { - "bl": "^3.0.0", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - } - } - } - }, - "archiver-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", - "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", - "dev": true, - "requires": { - "glob": "^7.1.4", - "graceful-fs": "^4.2.0", - "lazystream": "^1.0.0", - "lodash.defaults": "^4.2.0", - "lodash.difference": "^4.5.0", - "lodash.flatten": "^4.4.0", - "lodash.isplainobject": "^4.0.6", - "lodash.union": "^4.6.0", - "normalize-path": "^3.0.0", - "readable-stream": "^2.0.0" - }, - "dependencies": { - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "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" - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.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 - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-back": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", - "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", - "dev": true - }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "dev": true - }, - "array-flatten": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "arraybuffer.slice": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==", - "dev": true - }, - "asn1": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", - "dev": true, - "requires": { - "safer-buffer": "~2.1.0" - } - }, - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true - }, - "assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", - "dev": true - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, - "aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", - "dev": true - }, - "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==", - "dev": true - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - }, - "dependencies": { - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - } - } - }, - "babel-generator": { - "version": "6.26.1", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", - "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", - "dev": true, - "requires": { - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "detect-indent": "^4.0.0", - "jsesc": "^1.3.0", - "lodash": "^4.17.4", - "source-map": "^0.5.7", - "trim-right": "^1.0.1" - }, - "dependencies": { - "jsesc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", - "dev": true - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - } - } - }, - "babel-helper-evaluate-path": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/babel-helper-evaluate-path/-/babel-helper-evaluate-path-0.5.0.tgz", - "integrity": "sha512-mUh0UhS607bGh5wUMAQfOpt2JX2ThXMtppHRdRU1kL7ZLRWIXxoV2UIV1r2cAeeNeU1M5SB5/RSUgUxrK8yOkA==", - "dev": true - }, - "babel-helper-flip-expressions": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-helper-flip-expressions/-/babel-helper-flip-expressions-0.4.3.tgz", - "integrity": "sha1-NpZzahKKwYvCUlS19AoizrPB0/0=", - "dev": true - }, - "babel-helper-is-nodes-equiv": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/babel-helper-is-nodes-equiv/-/babel-helper-is-nodes-equiv-0.0.1.tgz", - "integrity": "sha1-NOmzALFHnd2Y7HfqC76TQt/jloQ=", - "dev": true - }, - "babel-helper-is-void-0": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-helper-is-void-0/-/babel-helper-is-void-0-0.4.3.tgz", - "integrity": "sha1-fZwBtFYee5Xb2g9u7kj1tg5nMT4=", - "dev": true - }, - "babel-helper-mark-eval-scopes": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.4.3.tgz", - "integrity": "sha1-0kSjvvmESHJgP/tG4izorN9VFWI=", - "dev": true - }, - "babel-helper-remove-or-void": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-helper-remove-or-void/-/babel-helper-remove-or-void-0.4.3.tgz", - "integrity": "sha1-pPA7QAd6D/6I5F0HAQ3uJB/1rmA=", - "dev": true - }, - "babel-helper-to-multiple-sequence-expressions": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/babel-helper-to-multiple-sequence-expressions/-/babel-helper-to-multiple-sequence-expressions-0.5.0.tgz", - "integrity": "sha512-m2CvfDW4+1qfDdsrtf4dwOslQC3yhbgyBFptncp4wvtdrDHqueW7slsYv4gArie056phvQFhT2nRcGS4bnm6mA==", - "dev": true - }, - "babel-messages": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-dynamic-import-node": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", - "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==", - "dev": true, - "requires": { - "object.assign": "^4.1.0" - } - }, - "babel-plugin-minify-builtins": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-builtins/-/babel-plugin-minify-builtins-0.5.0.tgz", - "integrity": "sha512-wpqbN7Ov5hsNwGdzuzvFcjgRlzbIeVv1gMIlICbPj0xkexnfoIDe7q+AZHMkQmAE/F9R5jkrB6TLfTegImlXag==", - "dev": true - }, - "babel-plugin-minify-constant-folding": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-constant-folding/-/babel-plugin-minify-constant-folding-0.5.0.tgz", - "integrity": "sha512-Vj97CTn/lE9hR1D+jKUeHfNy+m1baNiJ1wJvoGyOBUx7F7kJqDZxr9nCHjO/Ad+irbR3HzR6jABpSSA29QsrXQ==", - "dev": true, - "requires": { - "babel-helper-evaluate-path": "^0.5.0" - } - }, - "babel-plugin-minify-dead-code-elimination": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-dead-code-elimination/-/babel-plugin-minify-dead-code-elimination-0.5.1.tgz", - "integrity": "sha512-x8OJOZIrRmQBcSqxBcLbMIK8uPmTvNWPXH2bh5MDCW1latEqYiRMuUkPImKcfpo59pTUB2FT7HfcgtG8ZlR5Qg==", - "dev": true, - "requires": { - "babel-helper-evaluate-path": "^0.5.0", - "babel-helper-mark-eval-scopes": "^0.4.3", - "babel-helper-remove-or-void": "^0.4.3", - "lodash": "^4.17.11" - }, - "dependencies": { - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - } - } - }, - "babel-plugin-minify-flip-comparisons": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-flip-comparisons/-/babel-plugin-minify-flip-comparisons-0.4.3.tgz", - "integrity": "sha1-AMqHDLjxO0XAOLPB68DyJyk8llo=", - "dev": true, - "requires": { - "babel-helper-is-void-0": "^0.4.3" - } - }, - "babel-plugin-minify-guarded-expressions": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-guarded-expressions/-/babel-plugin-minify-guarded-expressions-0.4.4.tgz", - "integrity": "sha512-RMv0tM72YuPPfLT9QLr3ix9nwUIq+sHT6z8Iu3sLbqldzC1Dls8DPCywzUIzkTx9Zh1hWX4q/m9BPoPed9GOfA==", - "dev": true, - "requires": { - "babel-helper-evaluate-path": "^0.5.0", - "babel-helper-flip-expressions": "^0.4.3" - } - }, - "babel-plugin-minify-infinity": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-infinity/-/babel-plugin-minify-infinity-0.4.3.tgz", - "integrity": "sha1-37h2obCKBldjhO8/kuZTumB7Oco=", - "dev": true - }, - "babel-plugin-minify-mangle-names": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-mangle-names/-/babel-plugin-minify-mangle-names-0.5.0.tgz", - "integrity": "sha512-3jdNv6hCAw6fsX1p2wBGPfWuK69sfOjfd3zjUXkbq8McbohWy23tpXfy5RnToYWggvqzuMOwlId1PhyHOfgnGw==", - "dev": true, - "requires": { - "babel-helper-mark-eval-scopes": "^0.4.3" - } - }, - "babel-plugin-minify-numeric-literals": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-numeric-literals/-/babel-plugin-minify-numeric-literals-0.4.3.tgz", - "integrity": "sha1-jk/VYcefeAEob/YOjF/Z3u6TwLw=", - "dev": true - }, - "babel-plugin-minify-replace": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-replace/-/babel-plugin-minify-replace-0.5.0.tgz", - "integrity": "sha512-aXZiaqWDNUbyNNNpWs/8NyST+oU7QTpK7J9zFEFSA0eOmtUNMU3fczlTTTlnCxHmq/jYNFEmkkSG3DDBtW3Y4Q==", - "dev": true - }, - "babel-plugin-minify-simplify": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-simplify/-/babel-plugin-minify-simplify-0.5.1.tgz", - "integrity": "sha512-OSYDSnoCxP2cYDMk9gxNAed6uJDiDz65zgL6h8d3tm8qXIagWGMLWhqysT6DY3Vs7Fgq7YUDcjOomhVUb+xX6A==", - "dev": true, - "requires": { - "babel-helper-evaluate-path": "^0.5.0", - "babel-helper-flip-expressions": "^0.4.3", - "babel-helper-is-nodes-equiv": "^0.0.1", - "babel-helper-to-multiple-sequence-expressions": "^0.5.0" - } - }, - "babel-plugin-minify-type-constructors": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-plugin-minify-type-constructors/-/babel-plugin-minify-type-constructors-0.4.3.tgz", - "integrity": "sha1-G8bxW4f3qxCF1CszC3F2V6IVZQA=", - "dev": true, - "requires": { - "babel-helper-is-void-0": "^0.4.3" - } - }, - "babel-plugin-transform-inline-consecutive-adds": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-inline-consecutive-adds/-/babel-plugin-transform-inline-consecutive-adds-0.4.3.tgz", - "integrity": "sha1-Mj1Ho+pjqDp6w8gRro5pQfrysNE=", - "dev": true - }, - "babel-plugin-transform-member-expression-literals": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-member-expression-literals/-/babel-plugin-transform-member-expression-literals-6.9.4.tgz", - "integrity": "sha1-NwOcmgwzE6OUlfqsL/OmtbnQOL8=", - "dev": true - }, - "babel-plugin-transform-merge-sibling-variables": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-merge-sibling-variables/-/babel-plugin-transform-merge-sibling-variables-6.9.4.tgz", - "integrity": "sha1-hbQi/DN3tEnJ0c3kQIcgNTJAHa4=", - "dev": true - }, - "babel-plugin-transform-minify-booleans": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-minify-booleans/-/babel-plugin-transform-minify-booleans-6.9.4.tgz", - "integrity": "sha1-rLs+VqNVXdI5KOS1gtKFFi3SsZg=", - "dev": true - }, - "babel-plugin-transform-property-literals": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.9.4.tgz", - "integrity": "sha1-mMHSHiVXNlc/k+zlRFn2ziSYXTk=", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "babel-plugin-transform-regexp-constructors": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-regexp-constructors/-/babel-plugin-transform-regexp-constructors-0.4.3.tgz", - "integrity": "sha1-WLd3W2OvzzMyj66aX4j71PsLSWU=", - "dev": true - }, - "babel-plugin-transform-remove-console": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-console/-/babel-plugin-transform-remove-console-6.9.4.tgz", - "integrity": "sha1-uYA2DAZzhOJLNXpYjYB9PINSd4A=", - "dev": true - }, - "babel-plugin-transform-remove-debugger": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-debugger/-/babel-plugin-transform-remove-debugger-6.9.4.tgz", - "integrity": "sha1-QrcnYxyXl44estGZp67IShgznvI=", - "dev": true - }, - "babel-plugin-transform-remove-undefined": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-undefined/-/babel-plugin-transform-remove-undefined-0.5.0.tgz", - "integrity": "sha512-+M7fJYFaEE/M9CXa0/IRkDbiV3wRELzA1kKQFCJ4ifhrzLKn/9VCCgj9OFmYWwBd8IB48YdgPkHYtbYq+4vtHQ==", - "dev": true, - "requires": { - "babel-helper-evaluate-path": "^0.5.0" - } - }, - "babel-plugin-transform-simplify-comparison-operators": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-simplify-comparison-operators/-/babel-plugin-transform-simplify-comparison-operators-6.9.4.tgz", - "integrity": "sha1-9ir+CWyrDh9ootdT/fKDiIRxzrk=", - "dev": true - }, - "babel-plugin-transform-undefined-to-void": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-undefined-to-void/-/babel-plugin-transform-undefined-to-void-6.9.4.tgz", - "integrity": "sha1-viQcqBQEAwZ4t0hxcyK4nQyP4oA=", - "dev": true - }, - "babel-preset-minify": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/babel-preset-minify/-/babel-preset-minify-0.5.1.tgz", - "integrity": "sha512-1IajDumYOAPYImkHbrKeiN5AKKP9iOmRoO2IPbIuVp0j2iuCcj0n7P260z38siKMZZ+85d3mJZdtW8IgOv+Tzg==", - "dev": true, - "requires": { - "babel-plugin-minify-builtins": "^0.5.0", - "babel-plugin-minify-constant-folding": "^0.5.0", - "babel-plugin-minify-dead-code-elimination": "^0.5.1", - "babel-plugin-minify-flip-comparisons": "^0.4.3", - "babel-plugin-minify-guarded-expressions": "^0.4.4", - "babel-plugin-minify-infinity": "^0.4.3", - "babel-plugin-minify-mangle-names": "^0.5.0", - "babel-plugin-minify-numeric-literals": "^0.4.3", - "babel-plugin-minify-replace": "^0.5.0", - "babel-plugin-minify-simplify": "^0.5.1", - "babel-plugin-minify-type-constructors": "^0.4.3", - "babel-plugin-transform-inline-consecutive-adds": "^0.4.3", - "babel-plugin-transform-member-expression-literals": "^6.9.4", - "babel-plugin-transform-merge-sibling-variables": "^6.9.4", - "babel-plugin-transform-minify-booleans": "^6.9.4", - "babel-plugin-transform-property-literals": "^6.9.4", - "babel-plugin-transform-regexp-constructors": "^0.4.3", - "babel-plugin-transform-remove-console": "^6.9.4", - "babel-plugin-transform-remove-debugger": "^6.9.4", - "babel-plugin-transform-remove-undefined": "^0.5.0", - "babel-plugin-transform-simplify-comparison-operators": "^6.9.4", - "babel-plugin-transform-undefined-to-void": "^6.9.4", - "lodash": "^4.17.11" - }, - "dependencies": { - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - } - } - }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "dev": true, - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } - }, - "babel-traverse": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", - "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "debug": "^2.6.8", - "globals": "^9.18.0", - "invariant": "^2.2.2", - "lodash": "^4.17.4" - }, - "dependencies": { - "babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", - "dev": true - }, - "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - } - } - }, - "babel-types": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" - }, - "dependencies": { - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true - } - } - }, - "babylon": { - "version": "7.0.0-beta.47", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.47.tgz", - "integrity": "sha512-+rq2cr4GDhtToEzKFD6KZZMDBXhjFAr9JjPw9pAppZACeEWqNM294j+NdBzkSHYXwzzBmVjZ3nEVJlOhbR2gOQ==", - "dev": true - }, - "backo2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", - "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=", - "dev": true - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "base64-arraybuffer": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz", - "integrity": "sha1-c5JncZI7Whl0etZmqlzUv5xunOg=", - "dev": true - }, - "base64-js": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.0.tgz", - "integrity": "sha1-o5mS1yNYSBGYK+XikLtqU9hnAPE=", - "dev": true - }, - "base64id": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", - "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=", - "dev": true - }, - "bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", - "dev": true, - "requires": { - "tweetnacl": "^0.14.3" - } - }, - "better-assert": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz", - "integrity": "sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI=", - "dev": true, - "requires": { - "callsite": "1.0.0" - } - }, - "bl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.0.tgz", - "integrity": "sha512-wbgvOpqopSr7uq6fJrLH8EsvYMJf9gzfo2jCsL2eTy75qXPukA4pCgHamOQkZtY5vmfVtjB+P3LNlMHW5CEZXA==", - "dev": true, - "optional": true, - "requires": { - "readable-stream": "^2.3.5", - "safe-buffer": "^5.1.1" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "blob": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", - "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==", - "dev": true - }, - "body-parser": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", - "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", - "dev": true, - "requires": { - "bytes": "3.1.0", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "~1.1.2", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "on-finished": "~2.3.0", - "qs": "6.7.0", - "raw-body": "2.4.0", - "type-is": "~1.6.17" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "bower-config": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/bower-config/-/bower-config-1.4.1.tgz", - "integrity": "sha1-hf2d82fCuNu9DKpMXyutQM2Ewsw=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.3", - "mout": "^1.0.0", - "optimist": "^0.6.1", - "osenv": "^0.1.3", - "untildify": "^2.1.0" - } - }, - "boxen": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", - "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", - "dev": true, - "requires": { - "ansi-align": "^2.0.0", - "camelcase": "^4.0.0", - "chalk": "^2.0.1", - "cli-boxes": "^1.0.0", - "string-width": "^2.0.0", - "term-size": "^1.2.0", - "widest-line": "^2.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "browser-capabilities": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/browser-capabilities/-/browser-capabilities-1.1.4.tgz", - "integrity": "sha512-BezMQhbQklxjRQpZZQ8tnbzEo6AldUwMh8/PeWt5/CTBSwByQRXZEAK2fbnEahQ4poeeaI0suAYRq25A1YGOmw==", - "dev": true, - "requires": { - "@types/ua-parser-js": "^0.7.31", - "ua-parser-js": "^0.7.15" - } - }, - "browser-stdout": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", - "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", - "dev": true - }, - "browserstack": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/browserstack/-/browserstack-1.5.3.tgz", - "integrity": "sha512-AO+mECXsW4QcqC9bxwM29O7qWa7bJT94uBFzeb5brylIQwawuEziwq20dPYbins95GlWzOawgyDNdjYAo32EKg==", - "dev": true, - "optional": true, - "requires": { - "https-proxy-agent": "^2.2.1" - } - }, - "buffer": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.4.2.tgz", - "integrity": "sha512-iy9koArjAFCzGnx3ZvNA6Z0clIbbFgbdWQ0mKD3hO0krOrZh8UgA6qMKcZvwLJxS+D6iVR76+5/pV56yMNYTag==", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4" - } - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "busboy": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", - "integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=", - "dev": true, - "requires": { - "dicer": "0.2.5", - "readable-stream": "1.1.x" - } - }, - "bytes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", - "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", - "dev": true - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, - "call-me-maybe": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", - "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", - "dev": true - }, - "callsite": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", - "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=", - "dev": true - }, - "camel-case": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", - "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", - "dev": true, - "requires": { - "no-case": "^2.2.0", - "upper-case": "^1.1.1" - } - }, - "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", - "dev": true - }, - "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", - "dev": true, - "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" - } - }, - "cancel-token": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/cancel-token/-/cancel-token-0.1.1.tgz", - "integrity": "sha1-wYGXZ0uxyEwdaTPr8V2NWlznm08=", - "dev": true, - "requires": { - "@types/node": "^4.0.30" - }, - "dependencies": { - "@types/node": { - "version": "4.9.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-4.9.3.tgz", - "integrity": "sha512-Q9eESThBvAbfEzznF1qTAKUoPbJEbK3lTSO0S3mICvmG/vUSZ+HnCtidpuB58Po7CJt5A2goKsDiYScN8d1V4A==", - "dev": true - } - } - }, - "capture-stack-trace": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz", - "integrity": "sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw==", - "dev": true - }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true - }, - "chai": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-3.5.0.tgz", - "integrity": "sha1-TQJjewZ/6Vi9v906QOxW/vc3Mkc=", - "dev": true, - "requires": { - "assertion-error": "^1.0.1", - "deep-eql": "^0.1.3", - "type-detect": "^1.0.0" - } - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "charenc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", - "dev": true - }, - "ci-info": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", - "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", - "dev": true - }, - "clang-format": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/clang-format/-/clang-format-1.2.4.tgz", - "integrity": "sha512-sw+nrGUp3hvmANd1qF8vZPuezSYQAiXgGBiEtkXTtJnnu6b00fCqkkDIsnRKrNgg4nv6NYZE92ejvOMIXZoejw==", - "dev": true, - "requires": { - "async": "^1.5.2", - "glob": "^7.0.0", - "resolve": "^1.1.6" - } - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "clean-css": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", - "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==", - "dev": true, - "requires": { - "source-map": "~0.6.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 - } - } - }, - "cleankill": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/cleankill/-/cleankill-2.0.0.tgz", - "integrity": "sha1-WYMN/ItBHVPccq0J1Fp46jMWGpE=", - "dev": true - }, - "cli-boxes": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", - "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", - "dev": true - }, - "clipboard": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.4.tgz", - "integrity": "sha512-Vw26VSLRpJfBofiVaFb/I8PVfdI1OxKcYShe6fm0sP/DtmiWQNCjhM/okTvdCo0G+lMMm1rMYbk4IK4x1X+kgQ==", - "dev": true, - "optional": true, - "requires": { - "good-listener": "^1.2.2", - "select": "^1.1.2", - "tiny-emitter": "^2.0.0" - } - }, - "clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true - }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, - "color": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", - "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", - "dev": true, - "requires": { - "color-convert": "^1.9.1", - "color-string": "^1.5.2" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "color-string": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", - "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", - "dev": true, - "requires": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "colornames": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/colornames/-/colornames-1.1.1.tgz", - "integrity": "sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y=", - "dev": true - }, - "colors": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.3.tgz", - "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==", - "dev": true - }, - "colorspace": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.2.tgz", - "integrity": "sha512-vt+OoIP2d76xLhjwbBaucYlNSpPsrJWPlBTtwCpQKIu6/CSMutyzX93O/Do0qzpH3YoHEes8YEFXyZ797rEhzQ==", - "dev": true, - "requires": { - "color": "3.0.x", - "text-hex": "1.0.x" - } - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "command-line-args": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.1.1.tgz", - "integrity": "sha512-hL/eG8lrll1Qy1ezvkant+trihbGnaKaeEjj6Scyr3DN+RC7iQ5Rz84IeLERfAWDGo0HBSNAakczwgCilDXnWg==", - "dev": true, - "requires": { - "array-back": "^3.0.1", - "find-replace": "^3.0.0", - "lodash.camelcase": "^4.3.0", - "typical": "^4.0.0" - } - }, - "command-line-usage": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-5.0.5.tgz", - "integrity": "sha512-d8NrGylA5oCXSbGoKz05FkehDAzSmIm4K03S5VDh4d5lZAtTWfc3D1RuETtuQCn8129nYfJfDdF7P/lwcz1BlA==", - "dev": true, - "requires": { - "array-back": "^2.0.0", - "chalk": "^2.4.1", - "table-layout": "^0.4.3", - "typical": "^2.6.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "array-back": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", - "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", - "dev": true, - "requires": { - "typical": "^2.6.1" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "typical": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", - "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=", - "dev": true - } - } - }, - "commander": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", - "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", - "dev": true, - "requires": { - "graceful-readlink": ">= 1.0.0" - } - }, - "component-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", - "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=", - "dev": true - }, - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", - "dev": true - }, - "component-inherit": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", - "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=", - "dev": true - }, - "compress-commons": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-2.1.1.tgz", - "integrity": "sha512-eVw6n7CnEMFzc3duyFVrQEuY1BlHR3rYsSztyG32ibGMW722i3C6IizEGMFmfMU+A+fALvBIwxN3czffTcdA+Q==", - "dev": true, - "requires": { - "buffer-crc32": "^0.2.13", - "crc32-stream": "^3.0.1", - "normalize-path": "^3.0.0", - "readable-stream": "^2.3.6" - }, - "dependencies": { - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "compressible": { - "version": "2.0.17", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.17.tgz", - "integrity": "sha512-BGHeLCK1GV7j1bSmQQAi26X+GgWcTjLr/0tzSvMCl3LH1w1IJ4PFSPoV5316b30cneTziC+B1a+3OjoSUcQYmw==", - "dev": true, - "requires": { - "mime-db": ">= 1.40.0 < 2" - } - }, - "compression": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", - "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", - "dev": true, - "requires": { - "accepts": "~1.3.5", - "bytes": "3.0.0", - "compressible": "~2.0.16", - "debug": "2.6.9", - "on-headers": "~1.0.2", - "safe-buffer": "5.1.2", - "vary": "~1.1.2" - }, - "dependencies": { - "bytes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", - "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "configstore": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-3.1.2.tgz", - "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==", - "dev": true, - "requires": { - "dot-prop": "^4.1.0", - "graceful-fs": "^4.1.2", - "make-dir": "^1.0.0", - "unique-string": "^1.0.0", - "write-file-atomic": "^2.0.0", - "xdg-basedir": "^3.0.0" - } - }, - "content-disposition": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", - "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", - "dev": true, - "requires": { - "safe-buffer": "5.1.2" - } - }, - "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", - "dev": true - }, - "convert-source-map": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", - "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "cookie": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", - "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", - "dev": true - }, - "cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", - "dev": true - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, - "core-js": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz", - "integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "dev": true, - "requires": { - "object-assign": "^4", - "vary": "^1" - } - }, - "crc": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", - "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", - "dev": true, - "requires": { - "buffer": "^5.1.0" - } - }, - "crc32-stream": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-3.0.1.tgz", - "integrity": "sha512-mctvpXlbzsvK+6z8kJwSJ5crm7yBwrQMTybJzMw1O4lLGJqjlDCXY2Zw7KheiA6XBEcBmfLx1D88mjRGVJtY9w==", - "dev": true, - "requires": { - "crc": "^3.4.4", - "readable-stream": "^3.4.0" - }, - "dependencies": { - "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" - } - }, - "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 - }, - "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" - } - } - } - }, - "create-error-class": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", - "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", - "dev": true, - "requires": { - "capture-stack-trace": "^1.0.0" - } - }, - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", - "dev": true - }, - "crypto-random-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", - "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", - "dev": true - }, - "css-slam": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/css-slam/-/css-slam-2.1.2.tgz", - "integrity": "sha512-cObrY+mhFEmepWpua6EpMrgRNTQ0eeym+kvR0lukI6hDEzK7F8himEDS4cJ9+fPHCoArTzVrrR0d+oAUbTR1NA==", - "dev": true, - "requires": { - "command-line-args": "^5.0.2", - "command-line-usage": "^5.0.5", - "dom5": "^3.0.0", - "parse5": "^4.0.0", - "shady-css-parser": "^0.1.0" - } - }, - "cssbeautify": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cssbeautify/-/cssbeautify-0.3.1.tgz", - "integrity": "sha1-Et0fc0A1wub6ymfcvc73TkKBE5c=", - "dev": true - }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", - "dev": true, - "requires": { - "array-find-index": "^1.0.1" - } - }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true - }, - "deep-eql": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", - "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", - "dev": true, - "requires": { - "type-detect": "0.1.1" - }, - "dependencies": { - "type-detect": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", - "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", - "dev": true - } - } - }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true - }, - "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" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, - "delegate": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", - "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==", - "dev": true, - "optional": true - }, - "depd": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", - "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", - "dev": true - }, - "destroy": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", - "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", - "dev": true - }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true - }, - "detect-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", - "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "dev": true, - "requires": { - "repeating": "^2.0.0" - } - }, - "detect-node": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", - "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", - "dev": true - }, - "diagnostics": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.1.tgz", - "integrity": "sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==", - "dev": true, - "requires": { - "colorspace": "1.1.x", - "enabled": "1.0.x", - "kuler": "1.0.x" - } - }, - "dicer": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", - "integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=", - "dev": true, - "requires": { - "readable-stream": "1.1.x", - "streamsearch": "0.1.2" - } - }, - "diff": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", - "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", - "dev": true - }, - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dom-urls": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/dom-urls/-/dom-urls-1.1.0.tgz", - "integrity": "sha1-AB3fgWKM0ecGElxxdvU8zsVdkY4=", - "dev": true, - "requires": { - "urijs": "^1.16.1" - } - }, - "dom5": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dom5/-/dom5-3.0.1.tgz", - "integrity": "sha512-JPFiouQIr16VQ4dX6i0+Hpbg3H2bMKPmZ+WZgBOSSvOPx9QHwwY8sPzeM2baUtViESYto6wC2nuZOMC/6gulcA==", - "dev": true, - "requires": { - "@types/parse5": "^2.2.34", - "clone": "^2.1.0", - "parse5": "^4.0.0" - } - }, - "dot-prop": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", - "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", - "dev": true, - "requires": { - "is-obj": "^1.0.0" - } - }, - "duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", - "dev": true, - "requires": { - "readable-stream": "^2.0.2" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", - "dev": true - }, - "duplexify": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", - "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", - "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", - "dev": true, - "requires": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "ee-first": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", - "dev": true - }, - "emitter-component": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/emitter-component/-/emitter-component-1.1.1.tgz", - "integrity": "sha1-Bl4tvtaVm/RwZ57avq95gdEAOrY=", - "dev": true - }, - "enabled": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz", - "integrity": "sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=", - "dev": true, - "requires": { - "env-variable": "0.0.x" - } - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true - }, - "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "engine.io": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.3.2.tgz", - "integrity": "sha512-AsaA9KG7cWPXWHp5FvHdDWY3AMWeZ8x+2pUVLcn71qE5AtAzgGbxuclOytygskw8XGmiQafTmnI9Bix3uihu2w==", - "dev": true, - "requires": { - "accepts": "~1.3.4", - "base64id": "1.0.0", - "cookie": "0.3.1", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.0", - "ws": "~6.1.0" - }, - "dependencies": { - "cookie": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", - "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=", - "dev": true - }, - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "engine.io-client": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.3.2.tgz", - "integrity": "sha512-y0CPINnhMvPuwtqXfsGuWE8BB66+B6wTtCofQDRecMQPYX3MYUZXFNKDhdrSe3EVjgOu4V3rxdeqN/Tr91IgbQ==", - "dev": true, - "requires": { - "component-emitter": "1.2.1", - "component-inherit": "0.0.3", - "debug": "~3.1.0", - "engine.io-parser": "~2.1.1", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "ws": "~6.1.0", - "xmlhttprequest-ssl": "~1.5.4", - "yeast": "0.1.2" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "engine.io-parser": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.1.3.tgz", - "integrity": "sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA==", - "dev": true, - "requires": { - "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.5", - "blob": "0.0.5", - "has-binary2": "~1.0.2" - } - }, - "env-variable": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.5.tgz", - "integrity": "sha512-zoB603vQReOFvTg5xMl9I1P2PnHsHQQKTEowsKKD7nseUfJq6UWzK+4YtlWUO1nhiQUxe6XMkk+JleSZD1NZFA==", - "dev": true - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - }, - "dependencies": { - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - } - } - }, - "es6-promise": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", - "dev": true - }, - "es6-promisify": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-6.0.2.tgz", - "integrity": "sha512-eO6vFm0JvqGzjWIQA6QVKjxpmELfhWbDUWHm1rPfIbn55mhKPiAa5xpLmQWJrNa629ZIeQ8ZvMAi13kvrjK6Mg==", - "dev": true - }, - "escape-html": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "espree": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", - "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", - "dev": true, - "requires": { - "acorn": "^5.5.0", - "acorn-jsx": "^3.0.0" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", - "dev": true - }, - "eventemitter3": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", - "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", - "dev": true - }, - "execa": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", - "dev": true, - "requires": { - "cross-spawn": "^5.0.1", - "get-stream": "^3.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "expand-range": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", - "dev": true, - "requires": { - "fill-range": "^2.1.0" - }, - "dependencies": { - "fill-range": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", - "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", - "dev": true, - "requires": { - "is-number": "^2.1.0", - "isobject": "^2.0.0", - "randomatic": "^3.0.0", - "repeat-element": "^1.1.2", - "repeat-string": "^1.5.2" - } - }, - "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.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": { - "is-buffer": "^1.1.5" - } - } - } - }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "express": { - "version": "4.17.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", - "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", - "dev": true, - "requires": { - "accepts": "~1.3.7", - "array-flatten": "1.1.1", - "body-parser": "1.19.0", - "content-disposition": "0.5.3", - "content-type": "~1.0.4", - "cookie": "0.4.0", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "~1.1.2", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "~1.1.2", - "fresh": "0.5.2", - "merge-descriptors": "1.0.1", - "methods": "~1.1.2", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", - "proxy-addr": "~2.0.5", - "qs": "6.7.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.1.2", - "send": "0.17.1", - "serve-static": "1.14.1", - "setprototypeof": "1.1.1", - "statuses": "~1.5.0", - "type-is": "~1.6.18", - "utils-merge": "1.0.1", - "vary": "~1.1.2" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "dev": true, - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - }, - "dependencies": { - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } - } - } - } - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", - "dev": true - }, - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", - "dev": true - }, - "fast-glob": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.6.tgz", - "integrity": "sha512-0BvMaZc1k9F+MeWWMe8pL6YltFzZYcJsYU7D4JyDA6PAczaXvxqQQ/z+mDF7/4Mw01DeUc+i3CTKajnkANkV4w==", - "dev": true, - "requires": { - "@mrmlnc/readdir-enhanced": "^2.2.1", - "@nodelib/fs.stat": "^1.1.2", - "glob-parent": "^3.1.0", - "is-glob": "^4.0.0", - "merge2": "^1.2.3", - "micromatch": "^3.1.10" - }, - "dependencies": { - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - } - } - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true - }, - "fast-safe-stringify": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.6.tgz", - "integrity": "sha512-q8BZ89jjc+mz08rSxROs8VsrBBcn1SIw1kq9NjolL509tkABRk9io01RAjSaEv1Xb2uFLt8VtRiZbGp5H8iDtg==", - "dev": true - }, - "fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "dev": true, - "optional": true, - "requires": { - "pend": "~1.2.0" - } - }, - "fecha": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz", - "integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg==", - "dev": true - }, - "filename-regex": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", - "dev": true - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "finalhandler": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", - "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", - "dev": true, - "requires": { - "debug": "2.6.9", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.3", - "statuses": "~1.5.0", - "unpipe": "~1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "find-port": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/find-port/-/find-port-1.0.1.tgz", - "integrity": "sha1-2whKbL+ZVk2Zhprnn73s9m6KGFw=", - "dev": true, - "requires": { - "async": "~0.2.9" - }, - "dependencies": { - "async": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", - "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", - "dev": true - } - } - }, - "find-replace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", - "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", - "dev": true, - "requires": { - "array-back": "^3.0.1" - } - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "first-chunk-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", - "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", - "dev": true - }, - "follow-redirects": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.8.1.tgz", - "integrity": "sha512-micCIbldHioIegeKs41DoH0KS3AXfFzgS30qVkM6z/XOE/GJgvmsoc839NUqa1B9udYe9dQxgv7KFwng6+p/dw==", - "dev": true, - "requires": { - "debug": "^3.0.0" - }, - "dependencies": { - "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" - } - }, - "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 - } - } - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true - }, - "fork-stream": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/fork-stream/-/fork-stream-0.0.4.tgz", - "integrity": "sha1-24Sfznf2cIpfjzhq5TOgkHtUrnA=", - "dev": true - }, - "form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - } - }, - "formatio": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.1.1.tgz", - "integrity": "sha1-XtPM1jZVEJc4NGXZlhmRAOhhYek=", - "dev": true, - "requires": { - "samsam": "~1.1" - } - }, - "forwarded": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", - "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", - "dev": true - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, - "freeport": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/freeport/-/freeport-1.0.5.tgz", - "integrity": "sha1-JV6KuEFwwzuoXZkOghrl9KGpvF0=", - "dev": true, - "optional": true - }, - "fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", - "dev": true - }, - "fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true - }, - "get-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", - "dev": true - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0" - } - }, - "glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", - "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.2", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-base": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "dev": true, - "requires": { - "glob-parent": "^2.0.0", - "is-glob": "^2.0.0" - }, - "dependencies": { - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - } - } - }, - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, - "requires": { - "is-glob": "^2.0.0" - }, - "dependencies": { - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - } - } - }, - "glob-stream": { - "version": "5.3.5", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", - "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", - "dev": true, - "requires": { - "extend": "^3.0.0", - "glob": "^5.0.3", - "glob-parent": "^3.0.0", - "micromatch": "^2.3.7", - "ordered-read-streams": "^0.3.0", - "through2": "^0.6.0", - "to-absolute-glob": "^0.1.1", - "unique-stream": "^2.0.2" - }, - "dependencies": { - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1" - } - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, - "requires": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" - } - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true, - "requires": { - "is-posix-bracket": "^0.1.0" - } - }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - }, - "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" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - } - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "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": { - "is-buffer": "^1.1.5" - } - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, - "requires": { - "arr-diff": "^2.0.0", - "array-unique": "^0.2.1", - "braces": "^1.8.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" - }, - "dependencies": { - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - } - } - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } - } - } - }, - "glob-to-regexp": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", - "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", - "dev": true - }, - "global-dirs": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", - "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", - "dev": true, - "requires": { - "ini": "^1.3.4" - } - }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "good-listener": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", - "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=", - "dev": true, - "optional": true, - "requires": { - "delegate": "^3.1.2" - } - }, - "got": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/got/-/got-6.7.1.tgz", - "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", - "dev": true, - "requires": { - "create-error-class": "^3.0.0", - "duplexer3": "^0.1.4", - "get-stream": "^3.0.0", - "is-redirect": "^1.0.0", - "is-retry-allowed": "^1.0.0", - "is-stream": "^1.0.0", - "lowercase-keys": "^1.0.0", - "safe-buffer": "^5.0.1", - "timed-out": "^4.0.0", - "unzip-response": "^2.0.1", - "url-parse-lax": "^1.0.0" - } - }, - "graceful-fs": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", - "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==", - "dev": true - }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", - "dev": true - }, - "growl": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", - "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", - "dev": true - }, - "gulp-if": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/gulp-if/-/gulp-if-2.0.2.tgz", - "integrity": "sha1-pJe351cwBQQcqivIt92jyARE1ik=", - "dev": true, - "requires": { - "gulp-match": "^1.0.3", - "ternary-stream": "^2.0.1", - "through2": "^2.0.1" - } - }, - "gulp-match": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.1.0.tgz", - "integrity": "sha512-DlyVxa1Gj24DitY2OjEsS+X6tDpretuxD6wTfhXE/Rw2hweqc1f6D/XtsJmoiCwLWfXgR87W9ozEityPCVzGtQ==", - "dev": true, - "requires": { - "minimatch": "^3.0.3" - } - }, - "gulp-sourcemaps": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz", - "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=", - "dev": true, - "requires": { - "convert-source-map": "^1.1.1", - "graceful-fs": "^4.1.2", - "strip-bom": "^2.0.0", - "through2": "^2.0.0", - "vinyl": "^1.0.0" - } - }, - "handle-thing": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-1.2.5.tgz", - "integrity": "sha1-/Xqtcmvxpf0W38KbL3pmAdJxOcQ=", - "dev": true - }, - "har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", - "dev": true - }, - "har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", - "dev": true, - "requires": { - "ajv": "^6.5.5", - "har-schema": "^2.0.0" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "has-binary2": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", - "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", - "dev": true, - "requires": { - "isarray": "2.0.1" - }, - "dependencies": { - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", - "dev": true - } - } - }, - "has-color": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz", - "integrity": "sha1-ZxRKUmDDT8PMpnfQQdr1L+e3iy8=", - "dev": true - }, - "has-cors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", - "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=", - "dev": true - }, - "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 - }, - "has-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", - "dev": true - }, - "homedir-polyfill": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", - "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", - "dev": true, - "requires": { - "parse-passwd": "^1.0.0" - } - }, - "hosted-git-info": { - "version": "2.8.4", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.4.tgz", - "integrity": "sha512-pzXIvANXEFrc5oFFXRMkbLPQ2rXRoDERwDLyrcUxGhaZhgP54BBSl9Oheh7Vv0T090cszWBxPjkQQ5Sq1PbBRQ==", - "dev": true - }, - "hpack.js": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", - "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "obuf": "^1.0.0", - "readable-stream": "^2.0.1", - "wbuf": "^1.1.0" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "html-minifier": { - "version": "3.5.21", - "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz", - "integrity": "sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==", - "dev": true, - "requires": { - "camel-case": "3.0.x", - "clean-css": "4.2.x", - "commander": "2.17.x", - "he": "1.2.x", - "param-case": "2.1.x", - "relateurl": "0.2.x", - "uglify-js": "3.4.x" - }, - "dependencies": { - "commander": { - "version": "2.17.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", - "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", - "dev": true - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - } - } - }, - "http-deceiver": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", - "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", - "dev": true - }, - "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", - "statuses": ">= 1.5.0 < 2", - "toidentifier": "1.0.0" - } - }, - "http-proxy": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz", - "integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==", - "dev": true, - "requires": { - "eventemitter3": "^3.0.0", - "follow-redirects": "^1.0.0", - "requires-port": "^1.0.0" - } - }, - "http-proxy-middleware": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.17.4.tgz", - "integrity": "sha1-ZC6ISIUdZvCdTxJJEoRtuutBuDM=", - "dev": true, - "requires": { - "http-proxy": "^1.16.2", - "is-glob": "^3.1.0", - "lodash": "^4.17.2", - "micromatch": "^2.3.11" - }, - "dependencies": { - "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1" - } - }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, - "requires": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" - } - }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", - "dev": true, - "requires": { - "is-posix-bracket": "^0.1.0" - } - }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - }, - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "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": { - "is-buffer": "^1.1.5" - } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, - "requires": { - "arr-diff": "^2.0.0", - "array-unique": "^0.2.1", - "braces": "^1.8.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" - }, - "dependencies": { - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - } - } - } - } - }, - "http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - } - }, - "https-proxy-agent": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", - "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", - "dev": true, - "optional": true, - "requires": { - "agent-base": "^4.3.0", - "debug": "^3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "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, - "optional": true - } - } - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ieee754": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", - "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==", - "dev": true - }, - "import-lazy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", - "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", - "dev": true - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "indent": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/indent/-/indent-0.0.2.tgz", - "integrity": "sha1-jHnwgBkFWbaHA0uEx676l9WpEdk=", - "dev": true - }, - "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true, - "requires": { - "repeating": "^2.0.0" - } - }, - "indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "dev": true - }, - "invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, - "requires": { - "loose-envify": "^1.0.0" - } - }, - "ipaddr.js": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", - "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==", - "dev": true - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "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": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", - "dev": true - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-ci": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", - "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", - "dev": true, - "requires": { - "ci-info": "^1.5.0" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "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": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "is-dotfile": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true - }, - "is-equal-shallow": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", - "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", - "dev": true, - "requires": { - "is-primitive": "^2.0.0" - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-finite": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - }, - "is-installed-globally": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", - "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", - "dev": true, - "requires": { - "global-dirs": "^0.1.0", - "is-path-inside": "^1.0.0" - } - }, - "is-npm": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", - "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=", - "dev": true - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "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": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", - "dev": true - }, - "is-path-inside": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", - "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", - "dev": true, - "requires": { - "path-is-inside": "^1.0.1" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "is-posix-bracket": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", - "dev": true - }, - "is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "dev": true - }, - "is-redirect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", - "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", - "dev": true - }, - "is-retry-allowed": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", - "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", - "dev": true - }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", - "dev": true - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "is-valid-glob": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz", - "integrity": "sha1-1LVcafUYhvm2XHDWwmItN+KfSP4=", - "dev": true - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true - }, - "json3": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", - "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", - "dev": true - }, - "json5": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", - "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "jsonschema": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.2.4.tgz", - "integrity": "sha512-lz1nOH69GbsVHeVgEdvyavc/33oymY1AZwtePMiMj4HZPMbP5OIKK3zT9INMWjwua/V4Z4yq7wSlBbSG+g4AEw==", - "dev": true - }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", - "dev": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" - } - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, - "kuler": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz", - "integrity": "sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ==", - "dev": true, - "requires": { - "colornames": "^1.1.1" - } - }, - "latest-version": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-3.1.0.tgz", - "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", - "dev": true, - "requires": { - "package-json": "^4.0.0" - } - }, - "launchpad": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/launchpad/-/launchpad-0.7.2.tgz", - "integrity": "sha512-nmfx8QWqCvAmukHPticyO3+frnUKp0tDKXz3Au570XHBE0G1lNyN+KSODHgTqIIEuCIAlAgpbWjI36Vjk1mDKA==", - "dev": true, - "optional": true, - "requires": { - "async": "^2.0.1", - "browserstack": "^1.2.0", - "debug": "^2.2.0", - "plist": "^2.0.1", - "q": "^1.4.1", - "underscore": "^1.8.3" - }, - "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, - "optional": true, - "requires": { - "lodash": "^4.17.14" - } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true, - "optional": true - }, - "underscore": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", - "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", - "dev": true, - "optional": true - } - } - }, - "lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true, - "requires": { - "readable-stream": "^2.0.5" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", - "dev": true - }, - "lodash._baseassign": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", - "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", - "dev": true, - "requires": { - "lodash._basecopy": "^3.0.0", - "lodash.keys": "^3.0.0" - } - }, - "lodash._basecopy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", - "dev": true - }, - "lodash._basecreate": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", - "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", - "dev": true - }, - "lodash._getnative": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", - "dev": true - }, - "lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", - "dev": true - }, - "lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", - "dev": true - }, - "lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", - "dev": true - }, - "lodash.create": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", - "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", - "dev": true, - "requires": { - "lodash._baseassign": "^3.0.0", - "lodash._basecreate": "^3.0.0", - "lodash._isiterateecall": "^3.0.0" - } - }, - "lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", - "dev": true - }, - "lodash.difference": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", - "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=", - "dev": true - }, - "lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", - "dev": true - }, - "lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", - "dev": true - }, - "lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", - "dev": true - }, - "lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", - "dev": true - }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", - "dev": true - }, - "lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true, - "requires": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" - } - }, - "lodash.padend": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", - "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=", - "dev": true - }, - "lodash.sortby": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", - "dev": true - }, - "lodash.template": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", - "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", - "dev": true, - "requires": { - "lodash._reinterpolate": "^3.0.0", - "lodash.templatesettings": "^4.0.0" - } - }, - "lodash.templatesettings": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", - "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", - "dev": true, - "requires": { - "lodash._reinterpolate": "^3.0.0" - } - }, - "lodash.union": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", - "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=", - "dev": true - }, - "logform": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/logform/-/logform-1.10.0.tgz", - "integrity": "sha512-em5ojIhU18fIMOw/333mD+ZLE2fis0EzXl1ZwHx4iQzmpQi6odNiY/t+ITNr33JZhT9/KEaH+UPIipr6a9EjWg==", - "dev": true, - "requires": { - "colors": "^1.2.1", - "fast-safe-stringify": "^2.0.4", - "fecha": "^2.3.3", - "ms": "^2.1.1", - "triple-beam": "^1.2.0" - }, - "dependencies": { - "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 - } - } - }, - "lolex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.3.2.tgz", - "integrity": "sha1-fD2mL/yzDw9agKJWbKJORdigHzE=", - "dev": true - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dev": true, - "requires": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" - } - }, - "lower-case": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", - "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", - "dev": true - }, - "lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "dev": true - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "magic-string": { - "version": "0.22.5", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.5.tgz", - "integrity": "sha512-oreip9rJZkzvA8Qzk9HFs8fZGF/u7H/gtrE8EN6RjKJ9kh2HlC+yQ2QezifqTZfGyiuAV0dRv5a+y/8gBb1m9w==", - "dev": true, - "requires": { - "vlq": "^0.2.2" - } - }, - "make-dir": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", - "dev": true, - "requires": { - "pify": "^3.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, - "marked": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.19.tgz", - "integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==", - "dev": true - }, - "matcher": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/matcher/-/matcher-1.1.1.tgz", - "integrity": "sha512-+BmqxWIubKTRKNWx/ahnCkk3mG8m7OturVlqq6HiojGJTd5hVYbgZm6WzcYPCoB+KBT4Vd6R7WSRG2OADNaCjg==", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.4" - } - }, - "math-random": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz", - "integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A==", - "dev": true - }, - "md5": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz", - "integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=", - "dev": true, - "requires": { - "charenc": "~0.0.1", - "crypt": "~0.0.1", - "is-buffer": "~1.1.1" - } - }, - "media-typer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", - "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", - "dev": true - }, - "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", - "dev": true, - "requires": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", - "dev": true - }, - "merge-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", - "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", - "dev": true, - "requires": { - "readable-stream": "^2.0.1" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "merge2": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.2.3.tgz", - "integrity": "sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA==", - "dev": true - }, - "methods": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - }, - "mime-db": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", - "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", - "dev": true - }, - "mime-types": { - "version": "2.1.24", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", - "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", - "dev": true, - "requires": { - "mime-db": "1.40.0" - } - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimatch-all": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/minimatch-all/-/minimatch-all-1.1.0.tgz", - "integrity": "sha1-QMSWonouEo0Zv3WOdrsBoMcUV4c=", - "dev": true, - "requires": { - "minimatch": "^3.0.2" - } - }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "mocha": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz", - "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==", - "dev": true, - "requires": { - "browser-stdout": "1.3.0", - "commander": "2.9.0", - "debug": "2.6.8", - "diff": "3.2.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.1", - "growl": "1.9.2", - "he": "1.1.1", - "json3": "3.3.2", - "lodash.create": "3.1.1", - "mkdirp": "0.5.1", - "supports-color": "3.1.2" - }, - "dependencies": { - "debug": { - "version": "2.6.8", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "mout": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mout/-/mout-1.1.0.tgz", - "integrity": "sha512-XsP0vf4As6BfqglxZqbqQ8SR6KQot2AgxvR0gG+WtUkf90vUXchMOZQtPf/Hml1rEffJupqL/tIrU6EYhsUQjw==", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "multer": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.2.tgz", - "integrity": "sha512-xY8pX7V+ybyUpbYMxtjM9KAiD9ixtg5/JkeKUTD6xilfDv0vzzOFcCp4Ljb1UU3tSOM3VTZtKo63OmzOrGi3Cg==", - "dev": true, - "requires": { - "append-field": "^1.0.0", - "busboy": "^0.2.11", - "concat-stream": "^1.5.2", - "mkdirp": "^0.5.1", - "object-assign": "^4.1.1", - "on-finished": "^2.3.0", - "type-is": "^1.6.4", - "xtend": "^4.0.0" - } - }, - "multipipe": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-1.0.2.tgz", - "integrity": "sha1-zBPv2DPJzamfIk+GhGG44aP9k50=", - "dev": true, - "requires": { - "duplexer2": "^0.1.2", - "object-assign": "^4.1.0" - } - }, - "mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, - "requires": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - } - }, - "native-promise-only": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz", - "integrity": "sha1-IKMYwwy0X3H+et+/eyHJnBRy7xE=", - "dev": true - }, - "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", - "dev": true - }, - "nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true, - "optional": true - }, - "no-case": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", - "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", - "dev": true, - "requires": { - "lower-case": "^1.1.1" - } - }, - "nomnom": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.8.1.tgz", - "integrity": "sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=", - "dev": true, - "requires": { - "chalk": "~0.4.0", - "underscore": "~1.6.0" - }, - "dependencies": { - "ansi-styles": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.0.0.tgz", - "integrity": "sha1-yxAt8cVvUSPquLZ817mAJ6AnkXg=", - "dev": true - }, - "chalk": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.4.0.tgz", - "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", - "dev": true, - "requires": { - "ansi-styles": "~1.0.0", - "has-color": "~0.1.0", - "strip-ansi": "~0.1.0" - } - }, - "strip-ansi": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.1.1.tgz", - "integrity": "sha1-OeipjQRNFQZgq+SmgIrPcLt7yZE=", - "dev": true - } - } - }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "resolve": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", - "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - } - } - }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - }, - "npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", - "dev": true, - "requires": { - "path-key": "^2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object-component": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", - "integrity": "sha1-8MaapQ78lbhmwYb0AKM3acsvEpE=", - "dev": true - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.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": { - "is-buffer": "^1.1.5" - } - } - } - }, - "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-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - } - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "object.omit": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", - "dev": true, - "requires": { - "for-own": "^0.1.4", - "is-extendable": "^0.1.1" - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "obuf": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", - "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", - "dev": true - }, - "on-finished": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", - "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", - "dev": true, - "requires": { - "ee-first": "1.1.1" - } - }, - "on-headers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", - "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "one-time": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz", - "integrity": "sha1-+M33eISCb+Tf+T46nMN7HkSAdC4=", - "dev": true - }, - "opn": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/opn/-/opn-3.0.3.tgz", - "integrity": "sha1-ttmec5n3jWXDuq/+8fsojpuFJDo=", - "dev": true, - "requires": { - "object-assign": "^4.0.1" - } - }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, - "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" - } - }, - "ordered-read-streams": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", - "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", - "dev": true, - "requires": { - "is-stream": "^1.0.1", - "readable-stream": "^2.0.1" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "osenv": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", - "dev": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", - "dev": true - }, - "package-json": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-4.0.1.tgz", - "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", - "dev": true, - "requires": { - "got": "^6.7.1", - "registry-auth-token": "^3.0.1", - "registry-url": "^3.0.3", - "semver": "^5.1.0" - } - }, - "param-case": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", - "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", - "dev": true, - "requires": { - "no-case": "^2.2.0" - } - }, - "parse-glob": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", - "dev": true, - "requires": { - "glob-base": "^0.3.0", - "is-dotfile": "^1.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.0" - }, - "dependencies": { - "is-extglob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "^1.0.0" - } - } - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, - "parse5": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-4.0.0.tgz", - "integrity": "sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA==", - "dev": true - }, - "parseqs": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.5.tgz", - "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", - "dev": true, - "requires": { - "better-assert": "~1.0.0" - } - }, - "parseuri": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.5.tgz", - "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", - "dev": true, - "requires": { - "better-assert": "~1.0.0" - } - }, - "parseurl": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", - "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", - "dev": true - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", - "dev": true - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", - "dev": true - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "pem": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/pem/-/pem-1.14.2.tgz", - "integrity": "sha512-TOnPtq3ZFnCniOZ+rka4pk8UIze9xG1qI+wNE7EmkiR/cg+53uVvk5QbkWZ7M6RsuOxzz62FW1hlAobJr/lTOA==", - "dev": true, - "requires": { - "es6-promisify": "^6.0.0", - "md5": "^2.2.1", - "os-tmpdir": "^1.0.1", - "which": "^1.3.1" - } - }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true, - "optional": true - }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, - "plist": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/plist/-/plist-2.1.0.tgz", - "integrity": "sha1-V8zbeggh3yGDEhejytVOPhRqECU=", - "dev": true, - "optional": true, - "requires": { - "base64-js": "1.2.0", - "xmlbuilder": "8.2.2", - "xmldom": "0.1.x" - } - }, - "plylog": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/plylog/-/plylog-1.1.0.tgz", - "integrity": "sha512-/QnY5aSVaP54va6hruzNtAj02HpsLlAt7V5EndMrtq6ZUTZJKUja43rgiUtGXqm95yrSJjbZoPW0yQQQwLpoJA==", - "dev": true, - "requires": { - "logform": "^1.9.1", - "winston": "^3.0.0", - "winston-transport": "^4.2.0" - } - }, - "polymer-analyzer": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/polymer-analyzer/-/polymer-analyzer-3.2.4.tgz", - "integrity": "sha512-JmxUhMajTuC18tLXbTtu2+aN2x9bTX+4MvCD4IZKJ0rtAL8jWi1iRLfogpHJB4Ig9Dc8EEEuEYipLuzPFl3vqA==", - "dev": true, - "requires": { - "@babel/generator": "^7.0.0-beta.42", - "@babel/traverse": "^7.0.0-beta.42", - "@babel/types": "^7.0.0-beta.42", - "@types/babel-generator": "^6.25.1", - "@types/babel-traverse": "^6.25.2", - "@types/babel-types": "^6.25.1", - "@types/babylon": "^6.16.2", - "@types/chai-subset": "^1.3.0", - "@types/chalk": "^0.4.30", - "@types/clone": "^0.1.30", - "@types/cssbeautify": "^0.3.1", - "@types/doctrine": "^0.0.1", - "@types/is-windows": "^0.2.0", - "@types/minimatch": "^3.0.1", - "@types/parse5": "^2.2.34", - "@types/path-is-inside": "^1.0.0", - "@types/resolve": "0.0.6", - "@types/whatwg-url": "^6.4.0", - "babylon": "^7.0.0-beta.42", - "cancel-token": "^0.1.1", - "chalk": "^1.1.3", - "clone": "^2.0.0", - "cssbeautify": "^0.3.1", - "doctrine": "^2.0.2", - "dom5": "^3.0.0", - "indent": "0.0.2", - "is-windows": "^1.0.2", - "jsonschema": "^1.1.0", - "minimatch": "^3.0.4", - "parse5": "^4.0.0", - "path-is-inside": "^1.0.2", - "resolve": "^1.5.0", - "shady-css-parser": "^0.1.0", - "stable": "^0.1.6", - "strip-indent": "^2.0.0", - "vscode-uri": "=1.0.6", - "whatwg-url": "^6.4.0" - } - }, - "polymer-build": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/polymer-build/-/polymer-build-3.1.4.tgz", - "integrity": "sha512-OhTOPG5Y/tK2HqGZ5XA/CVDh+TuOaDv7wTZWXDCg6hxeMgNKuljDMn2coyGU5NLM0pLbS+gwFAc2ZJ5cWHCHNg==", - "dev": true, - "requires": { - "@babel/core": "^7.0.0", - "@babel/plugin-external-helpers": "^7.0.0", - "@babel/plugin-proposal-async-generator-functions": "^7.0.0", - "@babel/plugin-proposal-object-rest-spread": "^7.0.0", - "@babel/plugin-syntax-async-generators": "^7.0.0", - "@babel/plugin-syntax-dynamic-import": "^7.0.0", - "@babel/plugin-syntax-import-meta": "^7.0.0", - "@babel/plugin-syntax-object-rest-spread": "^7.0.0", - "@babel/plugin-transform-arrow-functions": "^7.0.0", - "@babel/plugin-transform-async-to-generator": "^7.0.0", - "@babel/plugin-transform-block-scoped-functions": "^7.0.0", - "@babel/plugin-transform-block-scoping": "^7.0.0", - "@babel/plugin-transform-classes": "^7.0.0", - "@babel/plugin-transform-computed-properties": "^7.0.0", - "@babel/plugin-transform-destructuring": "^7.0.0", - "@babel/plugin-transform-duplicate-keys": "^7.0.0", - "@babel/plugin-transform-exponentiation-operator": "^7.0.0", - "@babel/plugin-transform-for-of": "^7.0.0", - "@babel/plugin-transform-function-name": "^7.0.0", - "@babel/plugin-transform-instanceof": "^7.0.0", - "@babel/plugin-transform-literals": "^7.0.0", - "@babel/plugin-transform-modules-amd": "^7.0.0", - "@babel/plugin-transform-object-super": "^7.0.0", - "@babel/plugin-transform-parameters": "^7.0.0", - "@babel/plugin-transform-regenerator": "^7.0.0", - "@babel/plugin-transform-shorthand-properties": "^7.0.0", - "@babel/plugin-transform-spread": "^7.0.0", - "@babel/plugin-transform-sticky-regex": "^7.0.0", - "@babel/plugin-transform-template-literals": "^7.0.0", - "@babel/plugin-transform-typeof-symbol": "^7.0.0", - "@babel/plugin-transform-unicode-regex": "^7.0.0", - "@babel/traverse": "^7.0.0", - "@polymer/esm-amd-loader": "^1.0.0", - "@types/babel-types": "^6.25.1", - "@types/babylon": "^6.16.2", - "@types/gulp-if": "0.0.33", - "@types/html-minifier": "^3.5.1", - "@types/is-windows": "^0.2.0", - "@types/mz": "0.0.31", - "@types/parse5": "^2.2.34", - "@types/resolve": "0.0.7", - "@types/uuid": "^3.4.3", - "@types/vinyl": "^2.0.0", - "@types/vinyl-fs": "^2.4.8", - "babel-plugin-minify-guarded-expressions": "^0.4.3", - "babel-preset-minify": "^0.5.0", - "babylon": "^7.0.0-beta.42", - "css-slam": "^2.1.2", - "dom5": "^3.0.0", - "gulp-if": "^2.0.2", - "html-minifier": "^3.5.10", - "matcher": "^1.1.0", - "multipipe": "^1.0.2", - "mz": "^2.6.0", - "parse5": "^4.0.0", - "plylog": "^1.0.0", - "polymer-analyzer": "^3.1.3", - "polymer-bundler": "^4.0.9", - "polymer-project-config": "^4.0.3", - "regenerator-runtime": "^0.11.1", - "stream": "0.0.2", - "sw-precache": "^5.1.1", - "uuid": "^3.2.1", - "vinyl": "^1.2.0", - "vinyl-fs": "^2.4.4" - }, - "dependencies": { - "@types/mz": { - "version": "0.0.31", - "resolved": "https://registry.npmjs.org/@types/mz/-/mz-0.0.31.tgz", - "integrity": "sha1-pNgMCC/v5x5Ap8DwfR5lVbu8e1I=", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/resolve": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.7.tgz", - "integrity": "sha512-GPewdjkb0Q76o459qgp6pBLzJj/bD3oveS2kfLhIkZ9U3t3AFKtl5DlFB6lGTw0iZmcmxoGC8lpLW3NNJKrN9A==", - "dev": true, - "requires": { - "@types/node": "*" - } - } - } - }, - "polymer-bundler": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/polymer-bundler/-/polymer-bundler-4.0.10.tgz", - "integrity": "sha512-nwlN3LQlQDqbZ2sUH3394C/dHZUDHq8tpdS5HARvPDb0Q9IXWD+znOR1cr7wSjF0EZN4LiUH5hWyUoV4QSjhpQ==", - "dev": true, - "requires": { - "@types/babel-generator": "^6.25.1", - "@types/babel-traverse": "^6.25.3", - "babel-generator": "^6.26.1", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "clone": "^2.1.0", - "command-line-args": "^5.0.2", - "command-line-usage": "^5.0.5", - "dom5": "^3.0.0", - "espree": "^3.5.2", - "magic-string": "^0.22.4", - "mkdirp": "^0.5.1", - "parse5": "^4.0.0", - "polymer-analyzer": "^3.2.2", - "rollup": "^1.3.0", - "source-map": "^0.5.6", - "vscode-uri": "=1.0.6" - } - }, - "polymer-project-config": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/polymer-project-config/-/polymer-project-config-4.0.3.tgz", - "integrity": "sha512-Drr+Imq+znhBC8XSt9pMlmPixoGnIOmleV5SD6mto1zOGC5oCDbSNsQL2v89DWOk+9aSUO79vnWwOmEPDSvYfw==", - "dev": true, - "requires": { - "@types/parse5": "^2.2.34", - "browser-capabilities": "^1.0.0", - "jsonschema": "^1.1.1", - "minimatch-all": "^1.1.0", - "plylog": "^1.0.0", - "winston": "^3.0.0" - } - }, - "polyserve": { - "version": "0.27.15", - "resolved": "https://registry.npmjs.org/polyserve/-/polyserve-0.27.15.tgz", - "integrity": "sha512-AaFgANt+tUUVgHLw+BnaVYcn649JiwL1ru0TOZUKj1gGGn/Bq2S16gxql+1muGpRaAsgFu13Zu7k5XkwatwwSg==", - "dev": true, - "requires": { - "@types/compression": "^0.0.33", - "@types/content-type": "^1.1.0", - "@types/escape-html": "0.0.20", - "@types/express": "^4.0.36", - "@types/mime": "^2.0.0", - "@types/mz": "0.0.29", - "@types/opn": "^3.0.28", - "@types/parse5": "^2.2.34", - "@types/pem": "^1.8.1", - "@types/resolve": "0.0.6", - "@types/serve-static": "^1.7.31", - "@types/spdy": "^3.4.1", - "bower-config": "^1.4.1", - "browser-capabilities": "^1.0.0", - "command-line-args": "^5.0.2", - "command-line-usage": "^5.0.5", - "compression": "^1.6.2", - "content-type": "^1.0.2", - "cors": "^2.8.4", - "escape-html": "^1.0.3", - "express": "^4.8.5", - "find-port": "^1.0.1", - "http-proxy-middleware": "^0.17.2", - "lru-cache": "^4.0.2", - "mime": "^2.3.1", - "mz": "^2.4.0", - "opn": "^3.0.2", - "pem": "^1.8.3", - "polymer-build": "^3.1.0", - "polymer-project-config": "^4.0.0", - "requirejs": "^2.3.4", - "resolve": "^1.5.0", - "send": "^0.16.2", - "spdy": "^3.3.3" - }, - "dependencies": { - "mime": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", - "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", - "dev": true - } - } - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "prepend-http": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz", - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", - "dev": true - }, - "preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", - "dev": true - }, - "pretty-bytes": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-4.0.2.tgz", - "integrity": "sha1-sr+C5zUNZcbDOqlaqlpPYyf2HNk=", - "dev": true - }, - "prismjs": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.17.1.tgz", - "integrity": "sha512-PrEDJAFdUGbOP6xK/UsfkC5ghJsPJviKgnQOoxaDbBjwc8op68Quupwt1DeAFoG8GImPhiKXAvvsH7wDSLsu1Q==", - "dev": true, - "requires": { - "clipboard": "^2.0.0" - } - }, - "private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, - "optional": true - }, - "proxy-addr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", - "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", - "dev": true, - "requires": { - "forwarded": "~0.1.2", - "ipaddr.js": "1.9.0" - } - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "psl": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.3.0.tgz", - "integrity": "sha512-avHdspHO+9rQTLbv1RO+MPYeP/SzsCoxofjVnHanETfQhTJrmB0HlDoW+EiN/R+C0BZ+gERab9NY0lPN2TxNag==", - "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 - }, - "q": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", - "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", - "dev": true - }, - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", - "dev": true - }, - "randomatic": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz", - "integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==", - "dev": true, - "requires": { - "is-number": "^4.0.0", - "kind-of": "^6.0.0", - "math-random": "^1.0.1" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, - "range-parser": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", - "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", - "dev": true - }, - "raw-body": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", - "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", - "dev": true, - "requires": { - "bytes": "3.1.0", - "http-errors": "1.7.2", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - } - } - }, - "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", - "dev": true, - "requires": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" - }, - "dependencies": { - "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true, - "requires": { - "get-stdin": "^4.0.1" - } - } - } - }, - "reduce-flatten": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-1.0.1.tgz", - "integrity": "sha1-JYx479FT3fk8tWEjf2EYTzaW4yc=", - "dev": true - }, - "regenerate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", - "dev": true - }, - "regenerate-unicode-properties": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz", - "integrity": "sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==", - "dev": true, - "requires": { - "regenerate": "^1.4.0" - } - }, - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true - }, - "regenerator-transform": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.1.tgz", - "integrity": "sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ==", - "dev": true, - "requires": { - "private": "^0.1.6" - } - }, - "regex-cache": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", - "dev": true, - "requires": { - "is-equal-shallow": "^0.1.3" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, - "regexpu-core": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.5.tgz", - "integrity": "sha512-FpI67+ky9J+cDizQUJlIlNZFKual/lUkFr1AG6zOCpwZ9cLrg8UUVakyUQJD7fCDIe9Z2nwTQJNPyonatNmDFQ==", - "dev": true, - "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.1.0", - "regjsgen": "^0.5.0", - "regjsparser": "^0.6.0", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.1.0" - } - }, - "registry-auth-token": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.4.0.tgz", - "integrity": "sha512-4LM6Fw8eBQdwMYcES4yTnn2TqIasbXuwDx3um+QRs7S55aMKCBKBxvPXl2RiUjHwuJLTyYfxSpmfSAjQpcuP+A==", - "dev": true, - "requires": { - "rc": "^1.1.6", - "safe-buffer": "^5.0.1" - } - }, - "registry-url": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", - "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", - "dev": true, - "requires": { - "rc": "^1.0.1" - } - }, - "regjsgen": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", - "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==", - "dev": true - }, - "regjsparser": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", - "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - } - } - }, - "relateurl": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", - "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", - "dev": true - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, - "requires": { - "is-finite": "^1.0.0" - } - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "dev": true, - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "dependencies": { - "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", - "dev": true - } - } - }, - "requirejs": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz", - "integrity": "sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==", - "dev": true - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true - }, - "resolve": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz", - "integrity": "sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - } - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - }, - "dependencies": { - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true, - "optional": 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" - } - } - } - }, - "rollup": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.20.3.tgz", - "integrity": "sha512-/OMCkY0c6E8tleeVm4vQVDz24CkVgvueK3r8zTYu2AQNpjrcaPwO9hE+pWj5LTFrvvkaxt4MYIp2zha4y0lRvg==", - "dev": true, - "requires": { - "@types/estree": "0.0.39", - "@types/node": "^12.7.2", - "acorn": "^7.0.0" - }, - "dependencies": { - "@types/node": { - "version": "12.7.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.3.tgz", - "integrity": "sha512-3SiLAIBkDWDg6vFo0+5YJyHPWU9uwu40Qe+v+0MH8wRKYBimHvvAOyk3EzMrD/TrIlLYfXrqDqrg913PynrMJQ==", - "dev": true - }, - "acorn": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.0.0.tgz", - "integrity": "sha512-PaF/MduxijYYt7unVGRuds1vBC9bFxbNf+VWqhOClfdgy7RlVkQqt610ig1/yxTgsDIfW1cWDel5EBbOy3jdtQ==", - "dev": true - } - } - }, - "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 - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "samsam": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz", - "integrity": "sha1-vsEf3IOp/aBjQBIQ5AF2wwJNFWc=", - "dev": true - }, - "sauce-connect-launcher": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/sauce-connect-launcher/-/sauce-connect-launcher-1.2.7.tgz", - "integrity": "sha512-v07+QhFrxgz3seMFuRSonu3gW1s6DbcLQlFhjsRrmKUauzPbbudHdnn91WYgEwhoZVdPNzeZpAEJwcQyd9xnTA==", - "dev": true, - "optional": true, - "requires": { - "adm-zip": "~0.4.3", - "async": "^2.1.2", - "https-proxy-agent": "^2.2.1", - "lodash": "^4.16.6", - "rimraf": "^2.5.4" - }, - "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, - "optional": true, - "requires": { - "lodash": "^4.17.14" - } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true, - "optional": true - } - } - }, - "select": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", - "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=", - "dev": true, - "optional": true - }, - "select-hose": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", - "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", - "dev": true - }, - "selenium-standalone": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/selenium-standalone/-/selenium-standalone-6.16.0.tgz", - "integrity": "sha512-tl7HFH2FOxJD1is7Pzzsl0pY4vuePSdSWiJdPn+6ETBkpeJDiuzou8hBjvWYWpD+eIVcOrmy3L0R3GzkdHLzDw==", - "dev": true, - "optional": true, - "requires": { - "async": "^2.6.2", - "commander": "^2.19.0", - "cross-spawn": "^6.0.5", - "debug": "^4.1.1", - "lodash": "^4.17.11", - "minimist": "^1.2.0", - "mkdirp": "^0.5.1", - "progress": "2.0.3", - "request": "2.88.0", - "tar-stream": "2.0.0", - "urijs": "^1.19.1", - "which": "^1.3.1", - "yauzl": "^2.10.0" - }, - "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, - "optional": true, - "requires": { - "lodash": "^4.17.14" - } - }, - "commander": { - "version": "2.20.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", - "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", - "dev": true, - "optional": true - }, - "cross-spawn": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", - "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", - "dev": true, - "optional": true, - "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true, - "optional": true - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true, - "optional": true - }, - "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, - "optional": true - } - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "semver-diff": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", - "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", - "dev": true, - "requires": { - "semver": "^5.0.3" - } - }, - "send": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", - "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", - "dev": true, - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.6.2", - "mime": "1.4.1", - "ms": "2.0.0", - "on-finished": "~2.3.0", - "range-parser": "~1.2.0", - "statuses": "~1.4.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "http-errors": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", - "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", - "dev": true, - "requires": { - "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.0", - "statuses": ">= 1.4.0 < 2" - } - }, - "mime": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", - "dev": true - }, - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", - "dev": true - }, - "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==", - "dev": true - } - } - }, - "serve-static": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", - "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", - "dev": true, - "requires": { - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "parseurl": "~1.3.3", - "send": "0.17.1" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - }, - "dependencies": { - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", - "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", - "dev": true, - "requires": { - "debug": "2.6.9", - "depd": "~1.1.2", - "destroy": "~1.0.4", - "encodeurl": "~1.0.2", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "fresh": "0.5.2", - "http-errors": "~1.7.2", - "mime": "1.6.0", - "ms": "2.1.1", - "on-finished": "~2.3.0", - "range-parser": "~1.2.1", - "statuses": "~1.5.0" - } - } - } - }, - "server-destroy": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz", - "integrity": "sha1-8Tv5KOQrnD55OD5hzDmYtdFObN0=", - "dev": true - }, - "serviceworker-cache-polyfill": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/serviceworker-cache-polyfill/-/serviceworker-cache-polyfill-4.0.0.tgz", - "integrity": "sha1-3hnuc77yGrPAdAo3sz22JGS6ves=", - "dev": true - }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "setprototypeof": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", - "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", - "dev": true - }, - "shady-css-parser": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/shady-css-parser/-/shady-css-parser-0.1.0.tgz", - "integrity": "sha512-irfJUUkEuDlNHKZNAp2r7zOyMlmbfVJ+kWSfjlCYYUx/7dJnANLCyTzQZsuxy5NJkvtNwSxY5Gj8MOlqXUQPyA==", - "dev": true - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true - }, - "simple-swizzle": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", - "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", - "dev": true, - "requires": { - "is-arrayish": "^0.3.1" - } - }, - "sinon": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-1.17.7.tgz", - "integrity": "sha1-RUKk9JugxFwF6y6d2dID4rjv4L8=", - "dev": true, - "requires": { - "formatio": "1.1.1", - "lolex": "1.3.2", - "samsam": "1.1.2", - "util": ">=0.10.3 <1" - } - }, - "sinon-chai": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-2.14.0.tgz", - "integrity": "sha512-9stIF1utB0ywNHNT7RgiXbdmen8QDCRsrTjw+G9TgKt1Yexjiv8TOWZ6WHsTPz57Yky3DIswZvEqX8fpuHNDtQ==", - "dev": true - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - }, - "dependencies": { - "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": { - "is-buffer": "^1.1.5" - } - } - } - }, - "socket.io": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.2.0.tgz", - "integrity": "sha512-wxXrIuZ8AILcn+f1B4ez4hJTPG24iNgxBBDaJfT6MsyOhVYiTXWexGoPkd87ktJG8kQEcL/NBvRi64+9k4Kc0w==", - "dev": true, - "requires": { - "debug": "~4.1.0", - "engine.io": "~3.3.1", - "has-binary2": "~1.0.2", - "socket.io-adapter": "~1.1.0", - "socket.io-client": "2.2.0", - "socket.io-parser": "~3.3.0" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "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 - } - } - }, - "socket.io-adapter": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", - "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=", - "dev": true - }, - "socket.io-client": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.2.0.tgz", - "integrity": "sha512-56ZrkTDbdTLmBIyfFYesgOxsjcLnwAKoN4CiPyTVkMQj3zTUh0QAx3GbvIvLpFEOvQWu92yyWICxB0u7wkVbYA==", - "dev": true, - "requires": { - "backo2": "1.0.2", - "base64-arraybuffer": "0.1.5", - "component-bind": "1.0.0", - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "engine.io-client": "~3.3.1", - "has-binary2": "~1.0.2", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "object-component": "0.0.3", - "parseqs": "0.0.5", - "parseuri": "0.0.5", - "socket.io-parser": "~3.3.0", - "to-array": "0.1.4" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - } - } - }, - "socket.io-parser": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.0.tgz", - "integrity": "sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng==", - "dev": true, - "requires": { - "component-emitter": "1.2.1", - "debug": "~3.1.0", - "isarray": "2.0.1" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=", - "dev": true - } - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-resolve": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", - "dev": true, - "requires": { - "atob": "^2.1.1", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", - "dev": true - }, - "spdy": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-3.4.7.tgz", - "integrity": "sha1-Qv9B7OXMD5mjpsKKq7c/XDsDrLw=", - "dev": true, - "requires": { - "debug": "^2.6.8", - "handle-thing": "^1.2.5", - "http-deceiver": "^1.2.7", - "safe-buffer": "^5.0.1", - "select-hose": "^2.0.0", - "spdy-transport": "^2.0.18" - } - }, - "spdy-transport": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-2.1.1.tgz", - "integrity": "sha512-q7D8c148escoB3Z7ySCASadkegMmUZW8Wb/Q1u0/XBgDKMO880rLQDj8Twiew/tYi7ghemKUi/whSYOwE17f5Q==", - "dev": true, - "requires": { - "debug": "^2.6.8", - "detect-node": "^2.0.3", - "hpack.js": "^2.1.6", - "obuf": "^1.1.1", - "readable-stream": "^2.2.9", - "safe-buffer": "^5.0.1", - "wbuf": "^1.7.2" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - } - }, - "sshpk": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", - "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", - "dev": true, - "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - } - }, - "stable": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", - "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", - "dev": true - }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", - "dev": true - }, - "stacky": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/stacky/-/stacky-1.3.1.tgz", - "integrity": "sha1-PxF+UYe5pz0j+HbWnwXIWxGAShI=", - "dev": true, - "requires": { - "chalk": "^1.1.1", - "lodash": "^3.0.0" - } - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "statuses": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", - "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", - "dev": true - }, - "stream": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stream/-/stream-0.0.2.tgz", - "integrity": "sha1-f1Nj8Ff2WSxVlfALyAon9c7B8O8=", - "dev": true, - "requires": { - "emitter-component": "^1.1.1" - } - }, - "stream-shift": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", - "dev": true - }, - "streamsearch": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", - "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - }, - "strip-bom-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz", - "integrity": "sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=", - "dev": true, - "requires": { - "first-chunk-stream": "^1.0.0", - "strip-bom": "^2.0.0" - } - }, - "strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", - "dev": true - }, - "strip-indent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", - "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", - "dev": true - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - }, - "supports-color": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", - "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - }, - "sw-precache": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/sw-precache/-/sw-precache-5.2.1.tgz", - "integrity": "sha512-8FAy+BP/FXE+ILfiVTt+GQJ6UEf4CVHD9OfhzH0JX+3zoy2uFk7Vn9EfXASOtVmmIVbL3jE/W8Z66VgPSZcMhw==", - "dev": true, - "requires": { - "dom-urls": "^1.1.0", - "es6-promise": "^4.0.5", - "glob": "^7.1.1", - "lodash.defaults": "^4.2.0", - "lodash.template": "^4.4.0", - "meow": "^3.7.0", - "mkdirp": "^0.5.1", - "pretty-bytes": "^4.0.2", - "sw-toolbox": "^3.4.0", - "update-notifier": "^2.3.0" - } - }, - "sw-toolbox": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/sw-toolbox/-/sw-toolbox-3.6.0.tgz", - "integrity": "sha1-Jt8dHHA0hljk3qKIQxkUm3sxg7U=", - "dev": true, - "requires": { - "path-to-regexp": "^1.0.1", - "serviceworker-cache-polyfill": "^4.0.0" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "path-to-regexp": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", - "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", - "dev": true, - "requires": { - "isarray": "0.0.1" - } - } - } - }, - "table-layout": { - "version": "0.4.5", - "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-0.4.5.tgz", - "integrity": "sha512-zTvf0mcggrGeTe/2jJ6ECkJHAQPIYEwDoqsiqBjI24mvRmQbInK5jq33fyypaCBxX08hMkfmdOqj6haT33EqWw==", - "dev": true, - "requires": { - "array-back": "^2.0.0", - "deep-extend": "~0.6.0", - "lodash.padend": "^4.6.1", - "typical": "^2.6.1", - "wordwrapjs": "^3.0.0" - }, - "dependencies": { - "array-back": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", - "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", - "dev": true, - "requires": { - "typical": "^2.6.1" - } - }, - "typical": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", - "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=", - "dev": true - } - } - }, - "tar-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.0.0.tgz", - "integrity": "sha512-n2vtsWshZOVr/SY4KtslPoUlyNh06I2SGgAOCZmquCEjlbV/LjY2CY80rDtdQRHFOYXNlgBDo6Fr3ww2CWPOtA==", - "dev": true, - "optional": true, - "requires": { - "bl": "^2.2.0", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "dependencies": { - "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, - "optional": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "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, - "optional": true - }, - "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, - "optional": true, - "requires": { - "safe-buffer": "~5.2.0" - } - } - } - }, - "temp": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.3.tgz", - "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=", - "dev": true, - "optional": true, - "requires": { - "os-tmpdir": "^1.0.0", - "rimraf": "~2.2.6" - }, - "dependencies": { - "rimraf": { - "version": "2.2.8", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.2.8.tgz", - "integrity": "sha1-5Dm+Kq7jJzIZUnMPmaiSnk/FBYI=", - "dev": true, - "optional": true - } - } - }, - "term-size": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", - "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", - "dev": true, - "requires": { - "execa": "^0.7.0" - } - }, - "ternary-stream": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.1.1.tgz", - "integrity": "sha512-j6ei9hxSoyGlqTmoMjOm+QNvUKDOIY6bNl4Uh1lhBvl6yjPW2iLqxDUYyfDPZknQ4KdRziFl+ec99iT4l7g0cw==", - "dev": true, - "requires": { - "duplexify": "^3.5.0", - "fork-stream": "^0.0.4", - "merge-stream": "^1.0.0", - "through2": "^2.0.1" - } - }, - "text-encoding": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.6.4.tgz", - "integrity": "sha1-45mpgiV6J22uQou5KEXLcb3CbRk=", - "dev": true - }, - "text-hex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", - "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", - "dev": true - }, - "thenify": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz", - "integrity": "sha1-5p44obq+lpsBCCB5eLn2K4hgSDk=", - "dev": true, - "requires": { - "any-promise": "^1.0.0" - } - }, - "thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", - "dev": true, - "requires": { - "thenify": ">= 3.1.0 < 4" - } - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "through2-filter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", - "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", - "dev": true, - "requires": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - }, - "timed-out": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", - "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=", - "dev": true - }, - "tiny-emitter": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", - "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==", - "dev": true, - "optional": true - }, - "to-absolute-glob": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz", - "integrity": "sha1-HN+kcqnvUMI57maZm2YsoOs5k38=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "to-array": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", - "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", - "dev": true - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "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": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, - "toidentifier": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", - "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", - "dev": true - }, - "tough-cookie": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", - "dev": true, - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true - } - } - }, - "tr46": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", - "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", - "dev": true - }, - "trim-right": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", - "dev": true - }, - "triple-beam": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", - "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==", - "dev": true - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", - "dev": true, - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", - "dev": true - }, - "type-detect": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-1.0.0.tgz", - "integrity": "sha1-diIXzAbbJY7EiQihKY6LlRIejqI=", - "dev": true - }, - "type-is": { - "version": "1.6.18", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", - "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", - "dev": true, - "requires": { - "media-typer": "0.3.0", - "mime-types": "~2.1.24" - } - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "typical": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", - "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", - "dev": true - }, - "ua-parser-js": { - "version": "0.7.20", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.20.tgz", - "integrity": "sha512-8OaIKfzL5cpx8eCMAhhvTlft8GYF8b2eQr6JkCyVdrgjcytyOmPCXrqXFcUnhonRpLlh5yxEZVohm6mzaowUOw==", - "dev": true - }, - "uglify-js": { - "version": "3.4.10", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz", - "integrity": "sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==", - "dev": true, - "requires": { - "commander": "~2.19.0", - "source-map": "~0.6.1" - }, - "dependencies": { - "commander": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", - "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", - "dev": true - }, - "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 - } - } - }, - "underscore": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", - "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=", - "dev": true - }, - "unicode-canonical-property-names-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", - "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", - "dev": true - }, - "unicode-match-property-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", - "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", - "dev": true, - "requires": { - "unicode-canonical-property-names-ecmascript": "^1.0.4", - "unicode-property-aliases-ecmascript": "^1.0.4" - } - }, - "unicode-match-property-value-ecmascript": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz", - "integrity": "sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g==", - "dev": true - }, - "unicode-property-aliases-ecmascript": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz", - "integrity": "sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw==", - "dev": true - }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, - "unique-stream": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz", - "integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==", - "dev": true, - "requires": { - "json-stable-stringify-without-jsonify": "^1.0.1", - "through2-filter": "^3.0.0" - }, - "dependencies": { - "through2-filter": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz", - "integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==", - "dev": true, - "requires": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - } - } - }, - "unique-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", - "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", - "dev": true, - "requires": { - "crypto-random-string": "^1.0.0" - } - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", - "dev": true - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - } - } - }, - "untildify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-2.1.0.tgz", - "integrity": "sha1-F+soB5h/dpUunASF/DEdBqgmouA=", - "dev": true, - "requires": { - "os-homedir": "^1.0.0" - } - }, - "unzip-response": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-2.0.1.tgz", - "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=", - "dev": true - }, - "update-notifier": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-2.5.0.tgz", - "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==", - "dev": true, - "requires": { - "boxen": "^1.2.1", - "chalk": "^2.0.1", - "configstore": "^3.0.0", - "import-lazy": "^2.1.0", - "is-ci": "^1.0.10", - "is-installed-globally": "^0.1.0", - "is-npm": "^1.0.0", - "latest-version": "^3.0.0", - "semver-diff": "^2.0.0", - "xdg-basedir": "^3.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "upper-case": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", - "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", - "dev": true - }, - "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "urijs": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.1.tgz", - "integrity": "sha512-xVrGVi94ueCJNrBSTjWqjvtgvl3cyOTThp2zaMaFNGp3F542TR6sM3f2o8RqZl+AwteClSVmoCyt0ka4RjQOQg==", - "dev": true - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "url-parse-lax": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", - "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", - "dev": true, - "requires": { - "prepend-http": "^1.0.1" - } - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, - "util": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", - "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", - "dev": true, - "requires": { - "inherits": "2.0.3" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "utils-merge": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", - "dev": true - }, - "uuid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", - "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==", - "dev": true - }, - "vali-date": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", - "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=", - "dev": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "vargs": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/vargs/-/vargs-0.1.0.tgz", - "integrity": "sha1-a2GE2mUgzDIEzhtAfKwm2SYJ6/8=", - "dev": true - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "dev": true - }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "requires": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" - }, - "dependencies": { - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - } - } - }, - "vinyl-fs": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", - "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", - "dev": true, - "requires": { - "duplexify": "^3.2.0", - "glob-stream": "^5.3.2", - "graceful-fs": "^4.0.0", - "gulp-sourcemaps": "1.6.0", - "is-valid-glob": "^0.3.0", - "lazystream": "^1.0.0", - "lodash.isequal": "^4.0.0", - "merge-stream": "^1.0.0", - "mkdirp": "^0.5.0", - "object-assign": "^4.0.0", - "readable-stream": "^2.0.4", - "strip-bom": "^2.0.0", - "strip-bom-stream": "^1.0.0", - "through2": "^2.0.0", - "through2-filter": "^2.0.0", - "vali-date": "^1.0.0", - "vinyl": "^1.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "vlq": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz", - "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow==", - "dev": true - }, - "vscode-uri": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.6.tgz", - "integrity": "sha512-sLI2L0uGov3wKVb9EB+vIQBl9tVP90nqRvxSoJ35vI3NjxE8jfsE5DSOhWgSunHSZmKS4OCi2jrtfxK7uyp2ww==", - "dev": true - }, - "wbuf": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", - "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", - "dev": true, - "requires": { - "minimalistic-assert": "^1.0.0" - } - }, - "wct-browser-legacy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wct-browser-legacy/-/wct-browser-legacy-1.0.2.tgz", - "integrity": "sha512-23rbZwBh/DxWU36htJN9lsyBq3NxgVbuyMUq7fgFP6ZVTel+uFWO6LPXPoZQ6VyvXvlUYLE5PxY+ZdJ88a4COw==", - "dev": true, - "requires": { - "@polymer/polymer": "^3.0.0", - "@polymer/sinonjs": "^1.14.1", - "@polymer/test-fixture": "^3.0.0-pre.1", - "@webcomponents/webcomponentsjs": "^2.0.0", - "accessibility-developer-tools": "^2.12.0", - "async": "^1.5.2", - "chai": "^3.5.0", - "lodash": "^3.10.1", - "mocha": "^3.4.2", - "sinon": "^1.17.1", - "sinon-chai": "^2.10.0", - "stacky": "^1.3.1" - }, - "dependencies": { - "@polymer/test-fixture": { - "version": "3.0.0-pre.21", - "resolved": "https://registry.npmjs.org/@polymer/test-fixture/-/test-fixture-3.0.0-pre.21.tgz", - "integrity": "sha512-IxzUe6YzaORzUksafHAXHprV29YncOJgr0+1zNAifl0/f+cb5iAd4IWUrnsnVFHG5UGTLjvis5RgV6vvIZPDrA==", - "dev": true - } - } - }, - "wct-local": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/wct-local/-/wct-local-2.1.5.tgz", - "integrity": "sha512-eqoZhjGy4Xq2tY0uB46Grkw/ztq+/rC0ImbYKl62unFHXtOgal+kkvnxR3SLRFNM8ty9+ItgycPeH0IpTqVL+w==", - "dev": true, - "optional": true, - "requires": { - "@types/express": "^4.0.30", - "@types/freeport": "^1.0.19", - "@types/launchpad": "^0.6.0", - "@types/which": "^1.3.1", - "chalk": "^2.3.0", - "cleankill": "^2.0.0", - "freeport": "^1.0.4", - "launchpad": "^0.7.0", - "selenium-standalone": "^6.7.0", - "which": "^1.0.8" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "optional": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "optional": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "optional": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "optional": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "wct-sauce": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wct-sauce/-/wct-sauce-2.1.0.tgz", - "integrity": "sha512-c3R4PJcbpS7Gxv2vZ4HDAqpXV6cT9peslAWMU7hHH9PMhKDPbn8RNa6E4DVL0tOmZznB+3cRmtZ6+vJ/aDwu1A==", - "dev": true, - "optional": true, - "requires": { - "chalk": "^2.4.1", - "cleankill": "^2.0.0", - "lodash": "^4.17.10", - "request": "^2.85.0", - "sauce-connect-launcher": "^1.0.0", - "temp": "^0.8.1", - "uuid": "^3.2.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "optional": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "optional": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "optional": true - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true, - "optional": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "optional": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "wd": { - "version": "1.11.4", - "resolved": "https://registry.npmjs.org/wd/-/wd-1.11.4.tgz", - "integrity": "sha512-FHL+ofdCoU2FGvDFser8rXI4GFwwcyAaUuvddtdctig2X0zVVT6p7FAXf7nS0z7wTwXtEuZXX7MrnVTvFPqJTQ==", - "dev": true, - "requires": { - "archiver": "^3.0.0", - "async": "^2.0.0", - "lodash": "^4.0.0", - "mkdirp": "^0.5.1", - "q": "^1.5.1", - "request": "2.88.0", - "vargs": "^0.1.0" - }, - "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" - } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - } - } - }, - "web-component-tester": { - "version": "6.9.2", - "resolved": "https://registry.npmjs.org/web-component-tester/-/web-component-tester-6.9.2.tgz", - "integrity": "sha512-s2kB/+IE8XWcnxY1fqSpqTiiHEGHWgUWariAbiRlxmAvWSuvaCVNALHYebsZrLCNCLHKcJR8/sGv/bw0MWMvjw==", - "dev": true, - "requires": { - "@polymer/sinonjs": "^1.14.1", - "@polymer/test-fixture": "^0.0.3", - "@webcomponents/webcomponentsjs": "^1.0.7", - "accessibility-developer-tools": "^2.12.0", - "async": "^2.4.1", - "body-parser": "^1.17.2", - "bower-config": "^1.4.0", - "chalk": "^1.1.3", - "cleankill": "^2.0.0", - "express": "^4.15.3", - "findup-sync": "^2.0.0", - "glob": "^7.1.2", - "lodash": "^3.10.1", - "multer": "^1.3.0", - "nomnom": "^1.8.1", - "polyserve": "^0.27.13", - "resolve": "^1.5.0", - "semver": "^5.3.0", - "send": "^0.16.1", - "server-destroy": "^1.0.1", - "sinon": "^2.3.5", - "sinon-chai": "^2.10.0", - "socket.io": "^2.0.3", - "stacky": "^1.3.1", - "update-notifier": "^2.2.0", - "wct-local": "^2.1.1", - "wct-sauce": "^2.0.2", - "wd": "^1.2.0" - }, - "dependencies": { - "@polymer/test-fixture": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/@polymer/test-fixture/-/test-fixture-0.0.3.tgz", - "integrity": "sha1-REN1JpfU2Sk7vEEuoLXk00HxSdk=", - "dev": true - }, - "@webcomponents/webcomponentsjs": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/@webcomponents/webcomponentsjs/-/webcomponentsjs-1.3.3.tgz", - "integrity": "sha512-eLH04VBMpuZGzBIhOnUjECcQPEPcmfhWEijW9u1B5I+2PPYdWf3vWUExdDxu4Y3GljRSTCOlWnGtS9tpzmXMyQ==", - "dev": true - }, - "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" - }, - "dependencies": { - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - } - } - }, - "formatio": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/formatio/-/formatio-1.2.0.tgz", - "integrity": "sha1-87IWfZBoxGmKjVH092CjmlTYGOs=", - "dev": true, - "requires": { - "samsam": "1.x" - } - }, - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "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" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "lolex": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-1.6.0.tgz", - "integrity": "sha1-OpoCg0UqR9dDnnJzG54H1zhuSfY=", - "dev": true - }, - "path-to-regexp": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.7.0.tgz", - "integrity": "sha1-Wf3g9DW62suhA6hOnTvGTpa5k30=", - "dev": true, - "requires": { - "isarray": "0.0.1" - } - }, - "samsam": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", - "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", - "dev": true - }, - "sinon": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-2.4.1.tgz", - "integrity": "sha512-vFTrO9Wt0ECffDYIPSP/E5bBugt0UjcBQOfQUMh66xzkyPEnhl/vM2LRZi2ajuTdkH07sA6DzrM6KvdvGIH8xw==", - "dev": true, - "requires": { - "diff": "^3.1.0", - "formatio": "1.2.0", - "lolex": "^1.6.0", - "native-promise-only": "^0.8.1", - "path-to-regexp": "^1.7.0", - "samsam": "^1.1.3", - "text-encoding": "0.6.4", - "type-detect": "^4.0.0" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - } - } - }, - "webidl-conversions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", - "dev": true - }, - "webmat": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/webmat/-/webmat-0.2.2.tgz", - "integrity": "sha512-qi4Ol9a+0jArgbO8HdnIplE7f4p+9vXtRie8q321dmkqXAlWtVuSz7fL9g+S6yVynWBWq2MqVM/dq25W6tUWUw==", - "dev": true, - "requires": { - "clang-format": "^1.2.2", - "dom5": "^3.0.0", - "esprima": "^4.0.0", - "fast-glob": "^2.2.0", - "parse5": "^4.0.0" - } - }, - "whatwg-url": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-6.5.0.tgz", - "integrity": "sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==", - "dev": true, - "requires": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" - } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "widest-line": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", - "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", - "dev": true, - "requires": { - "string-width": "^2.1.1" - } - }, - "winston": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.2.1.tgz", - "integrity": "sha512-zU6vgnS9dAWCEKg/QYigd6cgMVVNwyTzKs81XZtTFuRwJOcDdBg7AU0mXVyNbs7O5RH2zdv+BdNZUlx7mXPuOw==", - "dev": true, - "requires": { - "async": "^2.6.1", - "diagnostics": "^1.1.1", - "is-stream": "^1.1.0", - "logform": "^2.1.1", - "one-time": "0.0.4", - "readable-stream": "^3.1.1", - "stack-trace": "0.0.x", - "triple-beam": "^1.3.0", - "winston-transport": "^4.3.0" - }, - "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" - } - }, - "lodash": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", - "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", - "dev": true - }, - "logform": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/logform/-/logform-2.1.2.tgz", - "integrity": "sha512-+lZh4OpERDBLqjiwDLpAWNQu6KMjnlXH2ByZwCuSqVPJletw0kTWJf5CgSNAUKn1KUkv3m2cUz/LK8zyEy7wzQ==", - "dev": true, - "requires": { - "colors": "^1.2.1", - "fast-safe-stringify": "^2.0.4", - "fecha": "^2.3.3", - "ms": "^2.1.1", - "triple-beam": "^1.3.0" - } - }, - "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 - }, - "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" - } - }, - "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 - }, - "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" - } - } - } - }, - "winston-transport": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.3.0.tgz", - "integrity": "sha512-B2wPuwUi3vhzn/51Uukcao4dIduEiPOcOt9HJ3QeaXgkJ5Z7UwpBzxS4ZGNHtrxrUvTwemsQiSys0ihOf8Mp1A==", - "dev": true, - "requires": { - "readable-stream": "^2.3.6", - "triple-beam": "^1.2.0" - }, - "dependencies": { - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true - }, - "wordwrapjs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-3.0.0.tgz", - "integrity": "sha512-mO8XtqyPvykVCsrwj5MlOVWvSnCdT+C+QVbm6blradR7JExAhbkZ7hZ9A+9NUtwzSqrlUo9a67ws0EiILrvRpw==", - "dev": true, - "requires": { - "reduce-flatten": "^1.0.1", - "typical": "^2.6.1" - }, - "dependencies": { - "typical": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", - "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=", - "dev": true - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, - "ws": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/ws/-/ws-6.1.4.tgz", - "integrity": "sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA==", - "dev": true, - "requires": { - "async-limiter": "~1.0.0" - } - }, - "xdg-basedir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", - "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", - "dev": true - }, - "xmlbuilder": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-8.2.2.tgz", - "integrity": "sha1-aSSGc0ELS6QuGmE2VR0pIjNap3M=", - "dev": true, - "optional": true - }, - "xmldom": { - "version": "0.1.27", - "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", - "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=", - "dev": true, - "optional": true - }, - "xmlhttprequest-ssl": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", - "integrity": "sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4=", - "dev": true - }, - "xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, - "yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "dev": true, - "optional": true, - "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "yeast": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", - "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=", - "dev": true - }, - "zip-stream": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-2.1.2.tgz", - "integrity": "sha512-ykebHGa2+uzth/R4HZLkZh3XFJzivhVsjJt8bN3GvBzLaqqrUdRacu+c4QtnUgjkkQfsOuNE1JgLKMCPNmkKgg==", - "dev": true, - "requires": { - "archiver-utils": "^2.1.0", - "compress-commons": "^2.1.1", - "readable-stream": "^3.4.0" - }, - "dependencies": { - "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" - } - }, - "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 - }, - "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" - } - } - } - } - } -} diff --git a/e2e/test/polymer-project/package.json b/e2e/test/polymer-project/package.json deleted file mode 100644 index 55f66f3810..0000000000 --- a/e2e/test/polymer-project/package.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "description": "Material design button", - "keywords": [ - "web-components", - "web-component", - "polymer", - "paper", - "button" - ], - "repository": { - "type": "git", - "url": "git://github.com/PolymerElements/paper-button.git" - }, - "homepage": "https://github.com/PolymerElements/paper-button", - "name": "polymer-project", - "license": "BSD-3-Clause", - "devDependencies": { - "@polymer/iron-demo-helpers": "~3.1.0", - "@polymer/iron-icon": "~3.0.1", - "@polymer/iron-icons": "~3.0.1", - "@polymer/iron-test-helpers": "~3.0.1", - "@polymer/test-fixture": "~4.0.2", - "@webcomponents/webcomponentsjs": "~2.3.0", - "wct-browser-legacy": "~1.0.2", - "web-component-tester": "~6.9.2", - "webmat": "~0.2.2" - }, - "localDependencies": { - "@stryker-mutator/api": "../../../packages/api", - "@stryker-mutator/core": "../../../packages/core", - "@stryker-mutator/wct-runner": "../../../packages/wct-runner", - "@stryker-mutator/javascript-mutator": "../../../packages/javascript-mutator", - "@stryker-mutator/util": "../../../packages/util" - }, - "scripts": { - "pretest": "rimraf \"reports\" \"stryker.log\"", - "test": "cross-env LAUNCHPAD_BROWSERS=chrome stryker run", - "posttest": "mocha --require ../../tasks/ts-node-register.js verify/*.ts" - }, - "engines": { - "node": ">=10" - }, - "version": "3.0.1", - "main": "paper-button.js", - "author": "The Polymer Authors", - "dependencies": { - "@polymer/polymer": "~3.3.0", - "@polymer/iron-flex-layout": "~3.0.1", - "@polymer/paper-behaviors": "~3.0.1", - "@polymer/paper-styles": "~3.0.1" - } -} diff --git a/e2e/test/polymer-project/paper-button.js b/e2e/test/polymer-project/paper-button.js deleted file mode 100644 index ea8edc3975..0000000000 --- a/e2e/test/polymer-project/paper-button.js +++ /dev/null @@ -1,211 +0,0 @@ -/** -@license -Copyright (c) 2015 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at -http://polymer.github.io/LICENSE.txt The complete set of authors may be found at -http://polymer.github.io/AUTHORS.txt The complete set of contributors may be -found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as -part of the polymer project is also subject to an additional IP rights grant -found at http://polymer.github.io/PATENTS.txt -*/ -import '@polymer/iron-flex-layout/iron-flex-layout.js'; -import '@polymer/paper-styles/element-styles/paper-material-styles.js'; - -import {PaperButtonBehavior, PaperButtonBehaviorImpl} from '@polymer/paper-behaviors/paper-button-behavior.js'; -import {Polymer} from '@polymer/polymer/lib/legacy/polymer-fn.js'; -import {html} from '@polymer/polymer/polymer-legacy.js'; - -const template = html` - - - `; - -template.setAttribute('strip-whitespace', ''); - -/** -Material design: -[Buttons](https://www.google.com/design/spec/components/buttons.html) - -`paper-button` is a button. When the user touches the button, a ripple effect -emanates from the point of contact. It may be flat or raised. A raised button is -styled with a shadow. - -Example: - - Flat button - Raised button - No ripple effect - Toggle-able button - -A button that has `toggles` true will remain `active` after being clicked (and -will have an `active` attribute set). For more information, see the -`IronButtonState` behavior. - -You may use custom DOM in the button body to create a variety of buttons. For -example, to create a button with an icon and some text: - - - - custom button content - - -To use `paper-button` as a link, wrap it in an anchor tag. Since `paper-button` -will already receive focus, you may want to prevent the anchor tag from -receiving focus as well by setting its tabindex to -1. - - - Polymer Project - - -### Styling - -Style the button with CSS as you would a normal DOM element. - - paper-button.fancy { - background: green; - color: yellow; - } - - paper-button.fancy:hover { - background: lime; - } - - paper-button[disabled], - paper-button[toggles][active] { - background: red; - } - -By default, the ripple is the same color as the foreground at 25% opacity. You -may customize the color using the `--paper-button-ink-color` custom property. - -The following custom properties and mixins are also available for styling: - -Custom property | Description | Default -----------------|-------------|---------- -`--paper-button-ink-color` | Background color of the ripple | `Based on the button's color` -`--paper-button` | Mixin applied to the button | `{}` -`--paper-button-disabled` | Mixin applied to the disabled button. Note that you can also use the `paper-button[disabled]` selector | `{}` -`--paper-button-flat-keyboard-focus` | Mixin applied to a flat button after it's been focused using the keyboard | `{}` -`--paper-button-raised-keyboard-focus` | Mixin applied to a raised button after it's been focused using the keyboard | `{}` - -@demo demo/index.html -*/ -Polymer({ - _template: template, - - is: 'paper-button', - - behaviors: [PaperButtonBehavior], - - properties: { - /** - * If true, the button should be styled with a shadow. - */ - raised: { - type: Boolean, - reflectToAttribute: true, - value: false, - observer: '_calculateElevation', - } - }, - - _calculateElevation: function() { - if (!this.raised) { - this._setElevation(0); - } else { - PaperButtonBehaviorImpl._calculateElevation.apply(this); - } - } - - /** - Fired when the animation finishes. - This is useful if you want to wait until - the ripple animation finishes to perform some action. - - @event transitionend - Event param: {{node: Object}} detail Contains the animated node. - */ -}); diff --git a/e2e/test/polymer-project/stryker.conf.js b/e2e/test/polymer-project/stryker.conf.js deleted file mode 100644 index 5e91c7f243..0000000000 --- a/e2e/test/polymer-project/stryker.conf.js +++ /dev/null @@ -1,16 +0,0 @@ -module.exports = function(config) { - config.set({ - mutator: "javascript", - packageManager: "npm", - reporters: ["event-recorder", "clear-text", "progress"], - testRunner: "wct", - transpilers: [], - coverageAnalysis: "off", - mutate: ["paper-button.js"], - wct: { - npm: true - }, - maxConcurrentTestRunners: 2, - timeoutMS: 30000 - }); -}; diff --git a/e2e/test/polymer-project/test/index.html b/e2e/test/polymer-project/test/index.html deleted file mode 100644 index 7984f07ef9..0000000000 --- a/e2e/test/polymer-project/test/index.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - paper-button tests - - - - - - - diff --git a/e2e/test/polymer-project/test/paper-button.html b/e2e/test/polymer-project/test/paper-button.html deleted file mode 100644 index 667ab35c94..0000000000 --- a/e2e/test/polymer-project/test/paper-button.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - paper-button basic tests - - - - - - - - - - - - - - diff --git a/e2e/test/polymer-project/verify/verify.ts b/e2e/test/polymer-project/verify/verify.ts deleted file mode 100644 index 52e6120b6e..0000000000 --- a/e2e/test/polymer-project/verify/verify.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { expectMetricsResult, produceMetrics } from '../../../helpers'; - -describe('After running stryker on polymer-project', () => { - it('should report expected values', async () => { - await expectMetricsResult({ - metrics: produceMetrics({ - killed: 14, - mutationScore: 88.24, - mutationScoreBasedOnCoveredCode: 88.24, - survived: 2, - timeout: 1, - totalCovered: 17, - totalDetected: 15, - totalMutants: 17, - totalUndetected: 2, - totalValid : 17 - }) - }); - /* - File | % score | # killed | # timeout | # survived | # no cov | # error | - -----------------|---------|----------|-----------|------------|----------|---------| - All files | 88.24 | 14 | 1 | 2 | 0 | 0 | - paper-button.js | 88.24 | 14 | 1 | 2 | 0 | 0 | - */ - }); -}); diff --git a/e2e/test/polymer-project/wct.conf.json b/e2e/test/polymer-project/wct.conf.json deleted file mode 100644 index bb2d5a8f1e..0000000000 --- a/e2e/test/polymer-project/wct.conf.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "plugins": { - "local": { - "browserOptions": { - "chrome": [ - "no-sandbox", - "headless", - "disable-gpu" - ], - "firefox": [ - "-headless" - ] - } - } - } -} \ No newline at end of file diff --git a/e2e/test/reporters-e2e/.mocharc.jsonc b/e2e/test/reporters-e2e/.mocharc.jsonc new file mode 100644 index 0000000000..3c2e5a6a9d --- /dev/null +++ b/e2e/test/reporters-e2e/.mocharc.jsonc @@ -0,0 +1,4 @@ +{ + "require": "./test/helpers/testSetup.js", + "spec": ["test/unit/*.js"] +} \ No newline at end of file diff --git a/e2e/test/reporters-e2e/package-lock.json b/e2e/test/reporters-e2e/package-lock.json new file mode 100644 index 0000000000..3900182e5c --- /dev/null +++ b/e2e/test/reporters-e2e/package-lock.json @@ -0,0 +1,5 @@ +{ + "name": "mocha-mocha", + "version": "0.0.0", + "lockfileVersion": 1 +} diff --git a/e2e/test/reporters-e2e/package.json b/e2e/test/reporters-e2e/package.json new file mode 100644 index 0000000000..a1576477fc --- /dev/null +++ b/e2e/test/reporters-e2e/package.json @@ -0,0 +1,15 @@ +{ + "name": "reporters-e2e", + "version": "0.0.0", + "private": true, + "description": "A module to perform an integration test", + "main": "index.js", + "scripts": { + "pretest": "rimraf \"reports\"", + "test": "mkdir -p reports && stryker run > reports/stdout.txt", + "test:unit": "mocha", + "posttest": "mocha --no-config --require ../../tasks/ts-node-register.js verify/*.ts" + }, + "author": "", + "license": "ISC" +} diff --git a/e2e/test/reporters-e2e/src/Add.js b/e2e/test/reporters-e2e/src/Add.js new file mode 100644 index 0000000000..0d6e64385c --- /dev/null +++ b/e2e/test/reporters-e2e/src/Add.js @@ -0,0 +1,26 @@ +module.exports.add = function(num1, num2) { + return num1 + num2; +}; + +module.exports.addOne = function(number) { + number++; + return number; +}; + +module.exports.negate = function(number) { + return -number; +}; + +module.exports.notCovered = function(number) { + return number > 10; +}; + +module.exports.isNegativeNumber = function(number) { + var isNegative = false; + if(number < 0){ + isNegative = true; + } + return isNegative; +}; + + diff --git a/e2e/test/reporters-e2e/src/Circle.js b/e2e/test/reporters-e2e/src/Circle.js new file mode 100644 index 0000000000..c1660c2d3f --- /dev/null +++ b/e2e/test/reporters-e2e/src/Circle.js @@ -0,0 +1,8 @@ +module.exports.getCircumference = function(radius) { + //Function to test multiple math mutations in a single function. + return 2 * Math.PI * radius; +}; + +module.exports.untestedFunction = function() { + var i = 5 / 2 * 3; +}; diff --git a/e2e/test/reporters-e2e/stryker.conf.json b/e2e/test/reporters-e2e/stryker.conf.json new file mode 100644 index 0000000000..fbb9dff9c5 --- /dev/null +++ b/e2e/test/reporters-e2e/stryker.conf.json @@ -0,0 +1,11 @@ +{ + "$schema": "../../node_modules/@stryker-mutator/core/schema/stryker-schema.json", + "testRunner": "mocha", + "concurrency": 2, + "coverageAnalysis": "perTest", + "reporters": ["clear-text", "html", "event-recorder"], + "plugins": [ + "@stryker-mutator/mocha-runner" + ], + "allowConsoleColors": false +} diff --git a/e2e/test/reporters-e2e/test/helpers/testSetup.js b/e2e/test/reporters-e2e/test/helpers/testSetup.js new file mode 100644 index 0000000000..993b68e6fc --- /dev/null +++ b/e2e/test/reporters-e2e/test/helpers/testSetup.js @@ -0,0 +1,5 @@ +exports.mochaHooks = { + beforeAll() { + global.expect = require('chai').expect; + } +} diff --git a/e2e/test/reporters-e2e/test/unit/AddSpec.js b/e2e/test/reporters-e2e/test/unit/AddSpec.js new file mode 100644 index 0000000000..d37ba16e88 --- /dev/null +++ b/e2e/test/reporters-e2e/test/unit/AddSpec.js @@ -0,0 +1,52 @@ +var addModule = require('../../src/Add'); +var add = addModule.add; +var addOne = addModule.addOne; +var isNegativeNumber = addModule.isNegativeNumber; +var negate = addModule.negate; +var notCovered = addModule.notCovered; + +describe('Add', function() { + it('should be able to add two numbers', function() { + var num1 = 2; + var num2 = 5; + var expected = num1 + num2; + + var actual = add(num1, num2); + + expect(actual).to.be.equal(expected); + }); + + it('should be able 1 to a number', function() { + var number = 2; + var expected = 3; + + var actual = addOne(number); + + expect(actual).to.be.equal(expected); + }); + + it('should be able negate a number', function() { + var number = 2; + var expected = -2; + + var actual = negate(number); + + expect(actual).to.be.equal(expected); + }); + + it('should be able to recognize a negative number', function() { + var number = -2; + + var isNegative = isNegativeNumber(number); + + expect(isNegative).to.be.true; + }); + + it('should be able to recognize that 0 is not a negative number', function() { + var number = 0; + + var isNegative = isNegativeNumber(number); + + expect(isNegative).to.be.false; + }); +}); diff --git a/e2e/test/mocha-mocha/test/unit/CircleSpec.js b/e2e/test/reporters-e2e/test/unit/CircleSpec.js similarity index 100% rename from e2e/test/mocha-mocha/test/unit/CircleSpec.js rename to e2e/test/reporters-e2e/test/unit/CircleSpec.js diff --git a/e2e/test/reporters-e2e/verify/verify.ts b/e2e/test/reporters-e2e/verify/verify.ts new file mode 100644 index 0000000000..8ec82f3cfb --- /dev/null +++ b/e2e/test/reporters-e2e/verify/verify.ts @@ -0,0 +1,61 @@ +import { expect } from 'chai'; +import fs from 'fs'; +import { describe } from 'mocha'; + +describe('Verify stryker has ran correctly', () => { + + function expectExists(fileName: string) { + expect(fs.existsSync(fileName), `Missing ${fileName}!`).true; + } + + it('should report html files', () => { + expectExists('reports/mutation/html/index.html'); + expectExists('reports/mutation/html/mutation-test-elements.js'); + expectExists('reports/mutation/html/stryker-80x80.png'); + expectExists('reports/mutation/html/bind-mutation-test-report.js'); + }); + + it('should have a clear text report', () => { + expectExists('reports/stdout.txt'); + }); + + describe('clearText report', () => { + + let stdout: string; + beforeEach(async () => { + stdout = await fs.promises.readFile('reports/stdout.txt', 'utf8'); + }) + + it('should report NoCoverage mutants', () => { + expect(stdout).matches(createNoCoverageMutantRegex()); + }); + + it('should report Survived mutants', () => { + expect(stdout).matches(createSurvivedMutantRegex()); + }); + + it('should report average tests per mutant', () => { + expect(stdout).contains('Ran 0.80 tests per mutant on average.'); + }); + + it('should report the clearText table', () => { + const clearTextTableRegex = createClearTextTableSummaryRowRegex(); + expect(stdout).matches(clearTextTableRegex); + }); + + it('should finish up with the clear text report', () => { + const clearTextTableRegex = createClearTextTableSummaryRowRegex(); + const survivedMutantRegex = createSurvivedMutantRegex(); + const indexOfSurvivedMutant = survivedMutantRegex.exec(stdout).index; + const indexOfClearTextTable = clearTextTableRegex.exec(stdout).index; + expect(indexOfSurvivedMutant).lessThan(indexOfClearTextTable); + }); + }) + +}); + +const createNoCoverageMutantRegex = () => /#6\.\s*\[NoCoverage\]/; + +const createSurvivedMutantRegex = () => /#20\.\s*\[Survived\]/; + +const createClearTextTableSummaryRowRegex = () => /All files\s*\|\s*64\.00\s*\|\s*16\s*\|\s*0\s*\|\s*1\s*\|\s*8\s*\|\s*0\s*\|/; diff --git a/e2e/test/typescript-transpiling/package.json b/e2e/test/typescript-transpiling/package.json index 6f2befab11..37d97e363d 100644 --- a/e2e/test/typescript-transpiling/package.json +++ b/e2e/test/typescript-transpiling/package.json @@ -5,9 +5,19 @@ "description": "A module to perform an integration test", "main": "index.js", "scripts": { - "pretest": "rimraf \"reports\"", - "test": "stryker run stryker.conf.js", - "posttest": "mocha --require ../../tasks/ts-node-register.js verify/*.ts" + "clean": "rimraf dist", + "prebuild": "npm run clean", + "build": "tsc", + "pretest:unit": "npm run build", + "test:unit": "mocha", + "pretest": "rimraf \"reports\" \"dist\"", + "test": "stryker run", + "posttest": "mocha --require ../../tasks/ts-node-register.js --no-package verify/*.ts" + }, + "mocha": { + "spec": [ + "dist/test/**/*.js" + ] }, "author": "", "license": "ISC" diff --git a/e2e/test/typescript-transpiling/src/Errors.ts b/e2e/test/typescript-transpiling/src/Errors.ts new file mode 100644 index 0000000000..aea538f178 --- /dev/null +++ b/e2e/test/typescript-transpiling/src/Errors.ts @@ -0,0 +1,37 @@ +export abstract class TypedInjectError extends Error {} +export type InjectionTarget = Function | symbol | number | string | undefined; + +function describeInjectAction(target: InjectionTarget) { + if (typeof target === 'function') { + return 'inject'; + } else { + return 'resolve'; + } +} + +function name(target: InjectionTarget) { + if (typeof target === 'function') { + if (target.toString().startsWith('class')) { + return `[class ${target.name || ''}]`; + } else { + return `[function ${target.name || ''}]`; + } + } else { + return `[token "${String(target)}"]`; + } +} + + +export class InjectionError extends TypedInjectError { + constructor(public readonly path: InjectionTarget[], public readonly cause: Error) { + super(`Could not ${describeInjectAction(path[0])} ${path.map(name).join(' -> ')}. Cause: ${cause.message}`); + } + + static create(target: InjectionTarget, error: Error) { + if (error instanceof InjectionError) { + return new InjectionError([target, ...error.path], error.cause); + } else { + return new InjectionError([target], error); + } + } +} diff --git a/e2e/test/typescript-transpiling/stryker.conf.js b/e2e/test/typescript-transpiling/stryker.conf.js deleted file mode 100644 index b2c87b48c5..0000000000 --- a/e2e/test/typescript-transpiling/stryker.conf.js +++ /dev/null @@ -1,21 +0,0 @@ -module.exports = function (config) { - config.set({ - tsconfigFile: 'tsconfig.json', - mutate: ['src/*.ts'], - testFramework: 'mocha', - testRunner: 'mocha', - coverageAnalysis: 'off', - reporters: ['clear-text', 'html', 'event-recorder'], - maxConcurrentTestRunners: 2, - mutator: 'typescript', - logLevel: 'info', - transpilers: [ - 'typescript' - ], - mochaOptions: { - files: [ - 'test/**/*.js' - ] - } - }); -}; diff --git a/e2e/test/typescript-transpiling/stryker.conf.json b/e2e/test/typescript-transpiling/stryker.conf.json new file mode 100644 index 0000000000..4a462fb560 --- /dev/null +++ b/e2e/test/typescript-transpiling/stryker.conf.json @@ -0,0 +1,15 @@ +{ + "$schema": "../../node_modules/@stryker-mutator/core/schema/stryker-schema.json", + "packageManager": "npm", + "testRunner": "mocha", + "concurrency": 1, + "coverageAnalysis": "perTest", + "reporters": ["event-recorder", "html", "progress", "clear-text"], + "checkers": ["typescript"], + "tsconfigFile": "tsconfig.json", + "buildCommand": "npm run build", + "plugins": [ + "@stryker-mutator/mocha-runner", + "@stryker-mutator/typescript-checker" + ] +} diff --git a/e2e/test/typescript-transpiling/test/Errors.spec.ts b/e2e/test/typescript-transpiling/test/Errors.spec.ts new file mode 100644 index 0000000000..89fe82d550 --- /dev/null +++ b/e2e/test/typescript-transpiling/test/Errors.spec.ts @@ -0,0 +1,31 @@ +import { InjectionError } from '../src/Errors'; +import { expect } from 'chai'; + +describe(InjectionError.name, () => { + it('should format a correct message', () => { + const cause = new Error('expected cause'); + function bar() { + // idle + } + expect(new InjectionError([class Foo {}, bar, 'baz'], cause).message).eq( + 'Could not inject [class Foo] -> [function bar] -> [token "baz"]. Cause: expected cause' + ); + }); + + describe(InjectionError.create.name, () => { + it('should create a new injection error for a given cause', () => { + const cause = new Error('Expected cause'); + const actual = InjectionError.create('foo', cause); + expect(actual.cause).eq(cause); + expect(actual.path).deep.eq(['foo']); + }); + it('should prepend to the path for given InjectionError', () => { + const cause = new Error('Expected cause'); + class Foo {} + const err = new InjectionError(['foo', Foo], cause); + const actual = InjectionError.create('bar', err); + expect(actual.cause).eq(cause); + expect(actual.path).deep.eq(['bar', 'foo', Foo]); + }); + }); +}); diff --git a/e2e/test/typescript-transpiling/tsconfig.json b/e2e/test/typescript-transpiling/tsconfig.json index 0fa6f31637..5929222955 100644 --- a/e2e/test/typescript-transpiling/tsconfig.json +++ b/e2e/test/typescript-transpiling/tsconfig.json @@ -1,15 +1,14 @@ { "compilerOptions": { - "lib": [ - "es5", - "es2015.promise", - "es2015.core" + "target": "es2017", + "module": "commonjs", + "outDir": "dist", + "types": [ + "mocha" ] }, - "files": [ - "src/Add.ts", - "src/Circle.ts", - "test/AddSpec.ts", - "test/CircleSpec.ts" + "include": [ + "src", + "test", ] -} \ No newline at end of file +} diff --git a/e2e/test/typescript-transpiling/verify/verify.ts b/e2e/test/typescript-transpiling/verify/verify.ts index be8899f2a6..206f339c01 100644 --- a/e2e/test/typescript-transpiling/verify/verify.ts +++ b/e2e/test/typescript-transpiling/verify/verify.ts @@ -5,15 +5,18 @@ describe('Verify stryker has ran correctly', () => { it('should report correct score', async () => { await expectMetricsResult({ metrics: produceMetrics({ - killed: 16, - mutationScore: 64, - mutationScoreBasedOnCoveredCode: 64, - survived: 9, - totalCovered: 25, - totalDetected: 16, - totalMutants: 25, - totalUndetected: 9, - totalValid: 25 + compileErrors: 10, + killed: 42, + mutationScore: 75, + mutationScoreBasedOnCoveredCode: 91.3, + survived: 4, + noCoverage: 10, + totalCovered: 46, + totalDetected: 42, + totalMutants: 66, + totalUndetected: 14, + totalInvalid: 10, + totalValid: 56 }) }); }); diff --git a/e2e/test/vue-cli-javascript-jest/package-lock.json b/e2e/test/vue-cli-javascript-jest/package-lock.json index c3e523dc8a..a20f2807d6 100644 --- a/e2e/test/vue-cli-javascript-jest/package-lock.json +++ b/e2e/test/vue-cli-javascript-jest/package-lock.json @@ -2052,9 +2052,9 @@ "dev": true }, "@vue/test-utils": { - "version": "1.0.0-beta.31", - "resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-1.0.0-beta.31.tgz", - "integrity": "sha512-IlhSx5hyEVnbvDZ3P98R1jNmy88QAd/y66Upn4EcvxSD5D4hwOutl3dIdfmSTSXs4b9DIMDnEVjX7t00cvOnvg==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-1.0.5.tgz", + "integrity": "sha512-P2x8kXwqfTXesAdfJQN146V1S3QD3Xv9wYZ1B09Oecmg7I3Fpqqo1CwfIn5ivwuXyBPQWFDH4vyBHynnYjIkRg==", "dev": true, "requires": { "dom-event-types": "^1.0.0", diff --git a/e2e/test/vue-cli-javascript-jest/package.json b/e2e/test/vue-cli-javascript-jest/package.json index 362db3a8c9..e8e9b3f098 100644 --- a/e2e/test/vue-cli-javascript-jest/package.json +++ b/e2e/test/vue-cli-javascript-jest/package.json @@ -11,23 +11,22 @@ "posttest": "mocha --require ../../tasks/ts-node-register.js --no-package verify/verify.ts" }, "dependencies": { - "core-js": "^3.6.4", - "vue": "^2.6.11" + "core-js": "~3.6.4", + "vue": "~2.6.11" }, "devDependencies": { "@vue/cli-plugin-babel": "~4.3.0", "@vue/cli-plugin-unit-jest": "~4.3.0", "@vue/cli-service": "~4.3.0", - "@vue/test-utils": "1.0.0-beta.31", - "jest-fetch-mock": "^3.0.3", - "vue-template-compiler": "^2.6.11" + "@vue/test-utils": "~1.0.5", + "jest-fetch-mock": "~3.0.3", + "vue-template-compiler": "~2.6.11" }, "localDependencies": { "@stryker-mutator/api": "../../../packages/api", "@stryker-mutator/core": "../../../packages/core", + "@stryker-mutator/instrumenter": "../../../packages/instrumenter", "@stryker-mutator/jest-runner": "../../../packages/jest-runner", - "@stryker-mutator/vue-mutator": "../../../packages/vue-mutator", - "@stryker-mutator/javascript-mutator": "../../../packages/javascript-mutator", "@stryker-mutator/util": "../../../packages/util" }, "browserslist": [ diff --git a/e2e/test/vue-cli-javascript-jest/stryker.conf.json b/e2e/test/vue-cli-javascript-jest/stryker.conf.json index ee06b92e6c..b01864568c 100644 --- a/e2e/test/vue-cli-javascript-jest/stryker.conf.json +++ b/e2e/test/vue-cli-javascript-jest/stryker.conf.json @@ -1,14 +1,12 @@ { - "$schema": "https://raw.githubusercontent.com/stryker-mutator/stryker/master/packages/api/schema/stryker-core.json", - "mutator": "vue", - "mutate": [ - "{src,lib}/**/*.+(js|vue)", - "!{src,lib}/**/*.spec.js" - ], + "$schema": "../../node_modules/@stryker-mutator/core/schema/stryker-schema.json", + "mutator": { + "plugins": [] + }, "tempDirName": "stryker-tmp", "packageManager": "npm", "testRunner": "jest", - "maxConcurrentTestRunners": 2, + "concurrency": 2, "coverageAnalysis": "off", "reporters": [ "event-recorder", diff --git a/e2e/test/vue-cli-typescript-mocha/package-lock.json b/e2e/test/vue-cli-typescript-mocha/package-lock.json index 057f6d4f7c..dcfb2398ed 100644 --- a/e2e/test/vue-cli-typescript-mocha/package-lock.json +++ b/e2e/test/vue-cli-typescript-mocha/package-lock.json @@ -11947,9 +11947,9 @@ } }, "whatwg-fetch": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz", - "integrity": "sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.4.0.tgz", + "integrity": "sha512-rsum2ulz2iuZH08mJkT0Yi6JnKhwdw4oeyMjokgxd+mmqYSd9cPpOQf01TIWgjxG/U4+QR+AwKq6lSbXVxkyoQ==", "dev": true }, "whatwg-mimetype": { diff --git a/e2e/test/vue-cli-typescript-mocha/package.json b/e2e/test/vue-cli-typescript-mocha/package.json index 2db90c217f..b0e6e5465f 100644 --- a/e2e/test/vue-cli-typescript-mocha/package.json +++ b/e2e/test/vue-cli-typescript-mocha/package.json @@ -10,23 +10,23 @@ "posttest": "mocha --require ../../tasks/ts-node-register.js --no-package verify/verify.ts" }, "dependencies": { - "core-js": "^3.6.4", - "vue": "^2.6.11" + "core-js": "~3.6.4", + "vue": "~2.6.11" }, "devDependencies": { - "@types/chai": "^4.2.11", - "@types/mocha": "^5.2.4", - "@types/sinon": "^9.0.0", + "@types/chai": "~4.2.11", + "@types/mocha": "~5.2.4", + "@types/sinon": "~9.0.0", "@vue/cli-plugin-babel": "~4.3.0", "@vue/cli-plugin-typescript": "~4.3.0", "@vue/cli-plugin-unit-mocha": "~4.3.0", "@vue/cli-service": "~4.3.0", - "@vue/test-utils": "1.0.0", - "chai": "^4.1.2", - "sinon": "^9.0.2", + "@vue/test-utils": "~1.0.0", + "chai": "~4.2.0", + "sinon": "~9.0.2", "typescript": "~3.8.3", - "vue-template-compiler": "^2.6.11", - "whatwg-fetch": "^3.0.0" + "vue-template-compiler": "~2.6.11", + "whatwg-fetch": "~3.4.0" }, "mocha": { "spec": "src/**/*.ts" @@ -39,10 +39,10 @@ "localDependencies": { "@stryker-mutator/api": "../../../packages/api", "@stryker-mutator/core": "../../../packages/core", + "@stryker-mutator/instrumenter": "../../../packages/instrumenter", "@stryker-mutator/mocha-runner": "../../../packages/mocha-runner", - "@stryker-mutator/webpack-transpiler": "../../../packages/webpack-transpiler", "@stryker-mutator/vue-mutator": "../../../packages/vue-mutator", - "@stryker-mutator/typescript": "../../../packages/typescript", + "@stryker-mutator/typescript-checker": "../../../packages/typescript-checker", "@stryker-mutator/util": "../../../packages/util" } } diff --git a/e2e/test/vue-cli-typescript-mocha/stryker.conf.json b/e2e/test/vue-cli-typescript-mocha/stryker.conf.json index 8f4d9855df..6e2c1d4c9e 100644 --- a/e2e/test/vue-cli-typescript-mocha/stryker.conf.json +++ b/e2e/test/vue-cli-typescript-mocha/stryker.conf.json @@ -1,19 +1,12 @@ { - "$schema": "https://raw.githubusercontent.com/stryker-mutator/stryker/master/packages/api/schema/stryker-core.json", - "mutator": "vue", - "mutate": [ - "{src,lib}/**/*.+(ts|vue)", - "!{src,lib}/**/*.spec.ts" - ], + "$schema": "../../node_modules/@stryker-mutator/core/schema/stryker-schema.json", "packageManager": "npm", "testRunner": "mocha", - "maxConcurrentTestRunners": 2, - "coverageAnalysis": "off", - "reporters": ["event-recorder"], - "transpilers": ["webpack"], - "webpack": { - "configFile": "webpack.test.config.js" - }, + "concurrency": 2, + "coverageAnalysis": "perTest", + "symlinkNodeModules": false, + "reporters": ["progress", "clear-text", "event-recorder"], + "buildCommand": "webpack --config webpack.test.config.js", "mochaOptions": { "package": "package.json", "require": [ @@ -21,5 +14,12 @@ ], "spec": ["dist/js/chunk-vendors.js", "dist/js/tests.js"] }, - "tsconfigFile": "tsconfig.json" + "tsconfigFile": "tsconfig.json", + "plugins": [ + "@stryker-mutator/mocha-runner", + "@stryker-mutator/typescript-checker" + ], + "checkers": [ + "typescript" + ] } diff --git a/e2e/test/vue-cli-typescript-mocha/verify/verify.ts b/e2e/test/vue-cli-typescript-mocha/verify/verify.ts index ab07862b82..f4f52baddd 100644 --- a/e2e/test/vue-cli-typescript-mocha/verify/verify.ts +++ b/e2e/test/vue-cli-typescript-mocha/verify/verify.ts @@ -4,11 +4,13 @@ describe('Verify stryker has ran correctly', () => { it('should report correct score', async () => { await expectMetrics({ - killed: 4, - survived: 13, - compileErrors: 0, + killed: 2, + survived: 1, + noCoverage: 10, + compileErrors: 3, runtimeErrors: 0, - timeout: 0 + timeout: 0, + mutationScore: 15.38 }); }); }); diff --git a/e2e/test/vue-javascript/package-lock.json b/e2e/test/vue-javascript/package-lock.json index 88f98395eb..4cd095a9ae 100644 --- a/e2e/test/vue-javascript/package-lock.json +++ b/e2e/test/vue-javascript/package-lock.json @@ -6199,9 +6199,9 @@ } }, "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==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.6.0.tgz", + "integrity": "sha512-8uQYa7zJN8hq9z+g8z1bqCfdC8eoDAeVnM5sfqs7KHv9/ifoJ500m018fpFc7RDaO6SWCLCXwo/wPSNcdYTgcw==", "dev": true }, "js-levenshtein": { diff --git a/e2e/test/vue-javascript/package.json b/e2e/test/vue-javascript/package.json index 26aa4ef4ee..0af8b9c936 100644 --- a/e2e/test/vue-javascript/package.json +++ b/e2e/test/vue-javascript/package.json @@ -10,7 +10,7 @@ "build": "cross-env NODE_ENV=production webpack", "unit": "cross-env BABEL_ENV=test karma start test/karma.conf.js --single-run", "pretest": "rimraf \"reports\"", - "test": "stryker run stryker.conf.js --fileLogLevel trace --logLevel debug", + "test": "stryker run --fileLogLevel trace", "posttest": "mocha --require ../../tasks/ts-node-register.js verify/*.ts" }, "dependencies": { @@ -45,7 +45,7 @@ "eslint-plugin-vue": "~6.0.0", "friendly-errors-webpack-plugin": "~1.7.0", "html-webpack-plugin": "~3.2.0", - "jasmine-core": "^3.5.0", + "jasmine-core": "~3.6.0", "karma": "~4.4.1", "karma-chai": "~0.1.0", "karma-chrome-launcher": "~3.1.0", @@ -70,9 +70,8 @@ "localDependencies": { "@stryker-mutator/api": "../../../packages/api", "@stryker-mutator/core": "../../../packages/core", - "@stryker-mutator/javascript-mutator": "../../../packages/javascript-mutator", + "@stryker-mutator/instrumenter": "../../../packages/instrumenter", "@stryker-mutator/karma-runner": "../../../packages/karma-runner", - "@stryker-mutator/vue-mutator": "../../../packages/vue-mutator", "@stryker-mutator/util": "../../../packages/util" }, "engines": { diff --git a/e2e/test/vue-javascript/stryker.conf.js b/e2e/test/vue-javascript/stryker.conf.js deleted file mode 100644 index 68c3a693a1..0000000000 --- a/e2e/test/vue-javascript/stryker.conf.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = function (config) { - config.set({ - mutate: ['src/**/*.js', 'src/**/*.vue'], - mutator: 'vue', - testFramework: 'jasmine', - testRunner: 'karma', - reporters: ['clear-text', 'html', 'event-recorder'], - maxConcurrentTestRunners: 2, - karma: { - configFile: 'test/karma.conf.js' - }, - coverageAnalysis: 'off' - }); -}; diff --git a/e2e/test/vue-javascript/stryker.conf.json b/e2e/test/vue-javascript/stryker.conf.json new file mode 100644 index 0000000000..2128168691 --- /dev/null +++ b/e2e/test/vue-javascript/stryker.conf.json @@ -0,0 +1,18 @@ +{ + "$schema": "../../node_modules/@stryker-mutator/core/schema/stryker-schema.json", + "testRunner": "karma", + "reporters": [ + "clear-text", + "html", + "event-recorder", + "progress" + ], + "concurrency": 2, + "karma": { + "configFile": "test/karma.conf.js" + }, + "coverageAnalysis": "perTest", + "plugins": [ + "@stryker-mutator/karma-runner" + ] +} diff --git a/e2e/test/vue-javascript/verify/verify.ts b/e2e/test/vue-javascript/verify/verify.ts index 18dbb04454..bd22a03ea2 100644 --- a/e2e/test/vue-javascript/verify/verify.ts +++ b/e2e/test/vue-javascript/verify/verify.ts @@ -1,22 +1,21 @@ -import { expectMetricsResult, produceMetrics } from '../../../helpers'; +import { expectMetrics } from '../../../helpers'; describe('After running stryker on VueJS project', () => { - it('should report 25% mutation score', async () => { - await expectMetricsResult({ - metrics: produceMetrics({ - killed: 4, - mutationScore: 29.41, - mutationScoreBasedOnCoveredCode: 29.41, - runtimeErrors: 0, - survived: 12, - timeout: 1, - totalCovered: 17, - totalDetected: 5, - totalInvalid: 0, - totalMutants: 17, - totalUndetected: 12, - totalValid: 17 - }) + it('should report ~29% mutation score', async () => { + await expectMetrics({ + killed: 4, + mutationScore: 29.41, + mutationScoreBasedOnCoveredCode: 41.67, + runtimeErrors: 0, + noCoverage: 5, + survived: 7, + timeout: 1, + totalCovered: 12, + totalDetected: 5, + totalInvalid: 0, + totalMutants: 17, + totalUndetected: 12, + totalValid: 17 }); }); }); diff --git a/e2e/test/webpack-zero-conf-karma/karma.conf.js b/e2e/test/webpack-zero-conf-karma/karma.conf.js new file mode 100644 index 0000000000..9394010c40 --- /dev/null +++ b/e2e/test/webpack-zero-conf-karma/karma.conf.js @@ -0,0 +1,13 @@ +module.exports = function(config) { + config.set({ + files: ['dist/main.js', 'test/*.js'], + frameworks: [ + 'jasmine' + ], + browsers: [ + 'ChromeHeadless' + ] + }); +} + + diff --git a/e2e/test/webpack-zero-conf-karma/package.json b/e2e/test/webpack-zero-conf-karma/package.json index edb7915792..a07d3eab76 100644 --- a/e2e/test/webpack-zero-conf-karma/package.json +++ b/e2e/test/webpack-zero-conf-karma/package.json @@ -6,7 +6,8 @@ "main": "index.js", "scripts": { "pretest": "rimraf \"reports\"", - "test": "stryker run stryker.conf.js", + "test": "stryker run", + "test:unit": "karma start", "posttest": "mocha --require ../../tasks/ts-node-register.js verify/*.ts" }, "author": "", diff --git a/e2e/test/webpack-zero-conf-karma/stryker.conf.js b/e2e/test/webpack-zero-conf-karma/stryker.conf.js deleted file mode 100644 index 0bf29f349f..0000000000 --- a/e2e/test/webpack-zero-conf-karma/stryker.conf.js +++ /dev/null @@ -1,19 +0,0 @@ -module.exports = function (config) { - config.set({ - mutate: ['src/**/*.js'], - transpilers: [ - 'webpack' - ], - testFramework: 'jasmine', - testRunner: 'karma', - reporters: ['clear-text', 'html', 'event-recorder'], - maxConcurrentTestRunners: 2, - karma: { - config: { - files: ['dist/main.js', 'test/*.js'] - } - }, - coverageAnalysis: 'off', - mutator: 'javascript' - }); -}; diff --git a/e2e/test/webpack-zero-conf-karma/stryker.conf.json b/e2e/test/webpack-zero-conf-karma/stryker.conf.json new file mode 100644 index 0000000000..d72345d165 --- /dev/null +++ b/e2e/test/webpack-zero-conf-karma/stryker.conf.json @@ -0,0 +1,19 @@ +{ + "$schema": "../../node_modules/@stryker-mutator/core/schema/stryker-schema.json", + "testRunner": "karma", + "reporters": [ + "clear-text", + "progress", + "html", + "event-recorder" + ], + "buildCommand": "webpack", + "concurrency": 2, + "karma": { + "configFile": "karma.conf.js" + }, + "coverageAnalysis": "perTest", + "plugins": [ + "@stryker-mutator/karma-runner" + ] +} diff --git a/e2e/test/webpack-zero-conf-karma/verify/verify.ts b/e2e/test/webpack-zero-conf-karma/verify/verify.ts index 655c9624f2..174e517825 100644 --- a/e2e/test/webpack-zero-conf-karma/verify/verify.ts +++ b/e2e/test/webpack-zero-conf-karma/verify/verify.ts @@ -1,22 +1,16 @@ -import { expectMetricsResult, produceMetrics } from '../../../helpers'; +import { expectMetrics } from '../../../helpers'; describe('Verify stryker has ran correctly', () => { it('should report correct score', async () => { - await expectMetricsResult({ - metrics: produceMetrics({ - compileErrors: 3, - killed: 2, - mutationScore: 33.33, - mutationScoreBasedOnCoveredCode: 33.33, - survived: 4, - totalCovered: 6, - totalDetected: 2, - totalInvalid: 3, - totalMutants: 9, - totalUndetected: 4, - totalValid: 6 - }) + await expectMetrics({ + compileErrors: 0, + killed: 2, + mutationScore: 33.33, + mutationScoreBasedOnCoveredCode: 100, + survived: 0, + noCoverage: 4, + timeout: 0 }); }); }); diff --git a/lerna.json b/lerna.json index f371199678..c76fd0a455 100644 --- a/lerna.json +++ b/lerna.json @@ -3,7 +3,7 @@ "packages": [ "packages/*" ], - "version": "3.3.1", + "version": "4.0.0-beta.10", "command": { "version": { "allowBranch": [ diff --git a/package.json b/package.json index 80e2ee795d..623ec4d0ea 100644 --- a/package.json +++ b/package.json @@ -2,55 +2,54 @@ "name": "stryker-parent", "private": true, "devDependencies": { - "@types/chai": "4.2.11", - "@types/chai-as-promised": "7.1.2", - "@types/glob": "^7.1.0", - "@types/istanbul": "^0.4.29", - "@types/karma": "^5.0.0", - "@types/lodash": "^4.14.110", - "@types/minimatch": "^3.0.3", - "@types/mkdirp": "1.0.0", - "@types/mocha": "^7.0.2", + "@types/chai": "~4.2.12", + "@types/chai-as-promised": "~7.1.3", + "@types/glob": "~7.1.0", + "@types/istanbul": "~0.4.29", + "@types/karma": "~5.0.0", + "@types/lodash": "~4.14.110", + "@types/mkdirp": "~1.0.1", + "@types/mocha": "~8.0.0", + "@types/minimatch": "~3.0.3", "@types/node": "^14.0.1", - "@types/rimraf": "3.0.0", + "@types/rimraf": "~3.0.0", "@types/sinon": "5.0.5", - "@types/sinon-chai": "3.2.4", - "@typescript-eslint/eslint-plugin": "2.33.0", - "@typescript-eslint/parser": "2.33.0", - "acorn": "^7.0.0", - "chai": "^4.1.1", - "chai-as-promised": "^7.1.1", - "concurrently": "^5.0.0", - "cross-env": "^7.0.0", - "eslint": "6.8.0", - "eslint-config-prettier": "6.11.0", - "eslint-plugin-import": "2.20.2", - "eslint-plugin-prettier": "3.1.3", - "execa": "^3.2.0", - "glob": "^7.1.1", + "@types/sinon-chai": "~3.2.4", + "@typescript-eslint/eslint-plugin": "4.0.0", + "@typescript-eslint/parser": "3.10.1", + "chai": "~4.2.0", + "chai-as-promised": "~7.1.1", + "concurrently": "~5.3.0", + "cross-env": "~7.0.0", + "eslint": "7.10.0", + "eslint-config-prettier": "6.12.0", + "eslint-plugin-import": "2.22.1", + "eslint-plugin-prettier": "3.1.4", + "execa": "~3.4.0", + "glob": "~7.1.1", "install-local": "~2.0.0", - "jasmine": "^3.1.0", - "jasmine-core": "^3.1.0", + "jasmine": "~3.6.1", + "jasmine-core": "~3.6.0", "json-schema-to-typescript": "~9.1.0", - "lerna": "^3.10.7", + "lerna": "~3.22.1", "link-parent-bin": "~1.0.0", - "minimatch": "^3.0.4", - "mocha": "^8.0.1", - "nyc": "^15.0.0", - "prettier": "2.0.5", - "rimraf": "^3.0.0", - "sinon": "^9.0.0", - "sinon-chai": "3.5.0", - "source-map-support": "^0.5.6", - "typescript": "~3.9.2" + "minimatch": "~3.0.4", + "mocha": "~8.1.3", + "nyc": "~15.1.0", + "prettier": "2.1.2", + "rimraf": "~3.0.0", + "sinon": "~9.1.0", + "sinon-chai": "~3.5.0", + "source-map-support": "~0.5.6", + "typescript": "~4.0.2" }, "scripts": { "all": "npm run clean && npm run build && npm run lint && npm run test", "postinstall": "lerna bootstrap --no-ci && link-parent-bin", - "lint": "eslint . --ext .ts,.tsx", - "lint:log": "eslint . --ext .ts,.tsx -f compact -o lint.log", - "lint:fix": "eslint . --ext .ts,.tsx --fix", - "clean": "rimraf \"packages/api/!(stryker.conf)+(.d.ts|.js|.map)\" \"packages/*/+(test|src)/**/*+(.d.ts|.js|.map)\" \"packages/*/{.nyc_output,reports,coverage,src-generated,*.tsbuildinfo,.stryker-tmp}\"", + "lint": "eslint . --resolve-plugins-relative-to . --ext .ts,.tsx", + "lint:log": "eslint . --resolve-plugins-relative-to . --ext .ts,.tsx -f compact -o lint.log", + "lint:fix": "eslint . --resolve-plugins-relative-to . --ext .ts,.tsx --fix", + "clean": "rimraf \"packages/api/!(stryker.conf)+(.d.ts|.js|.map)\" \"packages/*/+(test|src)/**/*+(.d.ts|.js|.map)\" \"packages/*/{.nyc_output,reports,coverage,src-generated,*.tsbuildinfo,.stryker-tmp,dist}\"", "generate": "node tasks/generate-json-schema-to-ts.js && node tasks/generate-mono-schema.js", "prebuild": "npm run generate", "build": "tsc -b && lerna run build", diff --git a/packages/api/.mocharc.jsonc b/packages/api/.mocharc.jsonc new file mode 100644 index 0000000000..7aa86ca6b3 --- /dev/null +++ b/packages/api/.mocharc.jsonc @@ -0,0 +1,3 @@ +{ + "require": ["test/setup.js"] +} diff --git a/packages/api/.nycrc b/packages/api/.nycrc deleted file mode 100644 index 9a746ff000..0000000000 --- a/packages/api/.nycrc +++ /dev/null @@ -1,11 +0,0 @@ -{ - "nyc":{ - "lines": 100, - "statements": 100, - "functions": 100, - "branches": 100, - "exclude": [ - "testResources/**/*.js" - ] - } -} \ No newline at end of file diff --git a/packages/api/.nycrc.json b/packages/api/.nycrc.json new file mode 100644 index 0000000000..9bbb5bec30 --- /dev/null +++ b/packages/api/.nycrc.json @@ -0,0 +1,13 @@ +{ + "lines": 90, + "statements": 90, + "functions": 90, + "branches": 90, + "excludeAfterRemap": false, + "checkCoverage": true, + "reporter": "html", + "reportDir": "reports/coverage", + "exclude": [ + "testResources/**/*.js" + ] +} diff --git a/packages/api/.vscode/launch.json b/packages/api/.vscode/launch.json index 090eaac215..c7285fbf35 100644 --- a/packages/api/.vscode/launch.json +++ b/packages/api/.vscode/launch.json @@ -1,24 +1,6 @@ { "version": "0.2.0", "configurations": [ - { - "type": "node", - "request": "launch", - "name": "Integration tests", - "program": "${workspaceFolder}/../../node_modules/mocha/bin/_mocha", - "args": [ - "--timeout", - "999999", - "--colors", - "${workspaceFolder}/test/helpers/**/*.js", - "${workspaceFolder}/test/integration/**/*.js" - ], - "internalConsoleOptions": "openOnSessionStart", - "outFiles": [ - "${workspaceRoot}/test/**/*.js", - "${workspaceRoot}/src/**/*.js" - ] - }, { "type": "node", "request": "launch", @@ -35,7 +17,10 @@ "outFiles": [ "${workspaceRoot}/test/**/*.js", "${workspaceRoot}/src/**/*.js" + ], + "skipFiles": [ + "/**" ] } ] -} \ No newline at end of file +} diff --git a/packages/api/CHANGELOG.md b/packages/api/CHANGELOG.md index fc64640501..8fdc15a346 100644 --- a/packages/api/CHANGELOG.md +++ b/packages/api/CHANGELOG.md @@ -3,6 +3,151 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [4.0.0-beta.10](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.9...v4.0.0-beta.10) (2020-10-05) + + +### Features + +* **instrumenter:** add excludedMutations support ([#2513](https://github.com/stryker-mutator/stryker/issues/2513)) ([bfd714f](https://github.com/stryker-mutator/stryker/commit/bfd714fe1b4f9c3b2468164a95d0c5bd0cbc8fcf)) + + + + + +# [4.0.0-beta.9](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.8...v4.0.0-beta.9) (2020-09-30) + + +### Features + +* **core:** add `appendPlugins` command-line option ([#2385](https://github.com/stryker-mutator/stryker/issues/2385)) ([0dec9b8](https://github.com/stryker-mutator/stryker/commit/0dec9b84b07391752af5514f90a2120c4f01d260)) +* **test-runner:** Add `--maxTestRunnerReuse` support ([5919484](https://github.com/stryker-mutator/stryker/commit/59194841505e520ddc382ea4affc78ef16978e1b)) + + + + + +# [4.0.0-beta.8](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.7...v4.0.0-beta.8) (2020-09-22) + + +### Features + +* **core:** add `--cleanTempDir` cli option ([6ef792c](https://github.com/stryker-mutator/stryker/commit/6ef792c839c0464c7acbeb72560574dc94480eea)) + + + + + +# [4.0.0-beta.7](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.6...v4.0.0-beta.7) (2020-09-17) + +**Note:** Version bump only for package @stryker-mutator/api + + + + + +# [4.0.0-beta.6](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.5...v4.0.0-beta.6) (2020-09-10) + +**Note:** Version bump only for package @stryker-mutator/api + + + + + +# [4.0.0-beta.5](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.4...v4.0.0-beta.5) (2020-09-09) + + +### Features + +* **mutate:** a new default for `mutate` ([#2452](https://github.com/stryker-mutator/stryker/issues/2452)) ([673516d](https://github.com/stryker-mutator/stryker/commit/673516d3fb92534fc3aad62d17243b558fae3ba4)), closes [#2384](https://github.com/stryker-mutator/stryker/issues/2384) +* **typescript:** Disable type checking ([#2446](https://github.com/stryker-mutator/stryker/issues/2446)) ([3ff996b](https://github.com/stryker-mutator/stryker/commit/3ff996b7516b7782434d86aa9aecbee334978a7f)), closes [#2438](https://github.com/stryker-mutator/stryker/issues/2438) + + + + + +# [4.0.0-beta.4](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.3...v4.0.0-beta.4) (2020-08-29) + + +### Features + +* **api:** rename test_runner2 -> test_runner ([#2442](https://github.com/stryker-mutator/stryker/issues/2442)) ([4d3ae97](https://github.com/stryker-mutator/stryker/commit/4d3ae9764dbd689c895b76e44f2eea76c82fabc8)) +* **options:** deprecate old stryker options ([#2395](https://github.com/stryker-mutator/stryker/issues/2395)) ([7c637c8](https://github.com/stryker-mutator/stryker/commit/7c637c8714169a03facd42a7521f7670b7606a32)) +* **reporter-api:** support mutation switching ([67f1ed5](https://github.com/stryker-mutator/stryker/commit/67f1ed52f4d17df4306362064180d267ed5445c7)) + + +### BREAKING CHANGES + +* **api:** Plugin creators should now use `'test_runner'` instead of `'test_runner2'`. +* **reporter-api:** The `onMutantTested` and `onAllMutantsTested` methods on the `Reporter` api have changed + + + + + +# [4.0.0-beta.3](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.2...v4.0.0-beta.3) (2020-08-19) + + +### Bug Fixes + +* **core:** exit process on error ([#2378](https://github.com/stryker-mutator/stryker/issues/2378)) ([af18a59](https://github.com/stryker-mutator/stryker/commit/af18a590fc916d75d54bcfaf2dda1d6a90bd4df8)), closes [#2315](https://github.com/stryker-mutator/stryker/issues/2315) + + +### Features + +* **core:** add ability to override file headers ([#2363](https://github.com/stryker-mutator/stryker/issues/2363)) ([430d6d3](https://github.com/stryker-mutator/stryker/commit/430d6d3d17fe2ad8e2cef3b858afa7efb86c2342)) +* **core:** strip comments in sandbox ([#2365](https://github.com/stryker-mutator/stryker/issues/2365)) ([55f27f2](https://github.com/stryker-mutator/stryker/commit/55f27f29b6994096c9aad038958ee93e9fa0f035)), closes [#2364](https://github.com/stryker-mutator/stryker/issues/2364) +* **test runner api:** remove `sandboxFileNames` injectable values ([#2369](https://github.com/stryker-mutator/stryker/issues/2369)) ([92f3bf5](https://github.com/stryker-mutator/stryker/commit/92f3bf528d0b01be1f6c219b37a5f90da0431686)), closes [#2351](https://github.com/stryker-mutator/stryker/issues/2351) + + + + + +# [4.0.0-beta.2](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.1...v4.0.0-beta.2) (2020-08-07) + + +### Features + +* **command:** Support command test runner with mutation switching ([#2345](https://github.com/stryker-mutator/stryker/issues/2345)) ([59b1cfc](https://github.com/stryker-mutator/stryker/commit/59b1cfc06c4f8f5ec1e55dce4823e0f9c384b16c)) +* **jest-runner:** support mutation switching ([#2350](https://github.com/stryker-mutator/stryker/issues/2350)) ([9e6e6e0](https://github.com/stryker-mutator/stryker/commit/9e6e6e077731344ed0588d64b5c8ba2f19c8492e)) + + + + + +# [4.0.0-beta.1](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.0...v4.0.0-beta.1) (2020-07-17) + +**Note:** Version bump only for package @stryker-mutator/api + + + + + +# [4.0.0-beta.0](https://github.com/stryker-mutator/stryker/compare/v3.3.1...v4.0.0-beta.0) (2020-07-10) + + +### Features + +* **api:** add id to Mutant interface ([#2255](https://github.com/stryker-mutator/stryker/issues/2255)) ([cfc9053](https://github.com/stryker-mutator/stryker/commit/cfc90537d0b9815cba2b44b9681d171ca602766e)) +* **api:** add new test runner api ([#2249](https://github.com/stryker-mutator/stryker/issues/2249)) ([bbbc308](https://github.com/stryker-mutator/stryker/commit/bbbc308806f46260ed0777ea2a33342ec12d105e)) +* **api:** remove support for options editors ([5e56d0e](https://github.com/stryker-mutator/stryker/commit/5e56d0ea6982faf11048c8ca4bbb912ee17e88eb)) +* **checker:** add checker api ([#2240](https://github.com/stryker-mutator/stryker/issues/2240)) ([d463f86](https://github.com/stryker-mutator/stryker/commit/d463f8639437c114da4fe30115652e8a470dd179)), closes [#1514](https://github.com/stryker-mutator/stryker/issues/1514) [#1980](https://github.com/stryker-mutator/stryker/issues/1980) +* **core:** add support for checker plugins ([#2285](https://github.com/stryker-mutator/stryker/issues/2285)) ([69358e1](https://github.com/stryker-mutator/stryker/commit/69358e1423701c730e29d303119a08d74081f340)) +* **core:** support build command ([f71ba87](https://github.com/stryker-mutator/stryker/commit/f71ba87a7adfd85131e1dea5fb1d6f3d8bba76df)) +* **mutator:** remove `Mutator` API ([3ca89cf](https://github.com/stryker-mutator/stryker/commit/3ca89cf7e23af70f83e0c0ac02ab5241fc0790ff)) +* **test-framework:** remove `TestFramework` API ([fe5e200](https://github.com/stryker-mutator/stryker/commit/fe5e200e1f7ad7a24ebceacb2a62c2be58ce6a4f)) +* **transpiler:** remove `Transpiler` API ([06f668b](https://github.com/stryker-mutator/stryker/commit/06f668bf8660f78b12916b2236f3fd9bf86bf23b)) +* **tsconfig:** rewrite tsconfig references ([#2292](https://github.com/stryker-mutator/stryker/issues/2292)) ([4ee4950](https://github.com/stryker-mutator/stryker/commit/4ee4950bebd8db9c2f5a514edee57de55c040526)), closes [#2276](https://github.com/stryker-mutator/stryker/issues/2276) +* **typescript-checker:** a typescript type checker plugin ([#2241](https://github.com/stryker-mutator/stryker/issues/2241)) ([42adb95](https://github.com/stryker-mutator/stryker/commit/42adb9561cdd10172f955fda044854bcc1b7b515)), closes [/github.com/stryker-mutator/stryker/blob/f44008993a543dc3f38ca99516f56d315fdcb735/packages/typescript/src/transpiler/TranspilingLanguageService.ts#L23](https://github.com//github.com/stryker-mutator/stryker/blob/f44008993a543dc3f38ca99516f56d315fdcb735/packages/typescript/src/transpiler/TranspilingLanguageService.ts/issues/L23) [#391](https://github.com/stryker-mutator/stryker/issues/391) + + +### BREAKING CHANGES + +* **core:** * `--maxConcurrentTestRunners` is now deprecated. Please use `--concurrency` instead. + + + + + ## [3.3.1](https://github.com/stryker-mutator/stryker/compare/v3.3.0...v3.3.1) (2020-07-04) diff --git a/packages/api/check.ts b/packages/api/check.ts new file mode 100644 index 0000000000..4899f18645 --- /dev/null +++ b/packages/api/check.ts @@ -0,0 +1,3 @@ +export * from './src/check/Checker'; +export * from './src/check/CheckResult'; +export * from './src/check/CheckStatus'; diff --git a/packages/api/config.ts b/packages/api/config.ts deleted file mode 100644 index d7d06266fc..0000000000 --- a/packages/api/config.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default as Config } from './src/config/Config'; -export { default as ConfigEditor } from './src/config/ConfigEditor'; diff --git a/packages/api/core.ts b/packages/api/core.ts index 425a058f9e..6f37f854a1 100644 --- a/packages/api/core.ts +++ b/packages/api/core.ts @@ -2,8 +2,10 @@ export { default as File } from './src/core/File'; export { default as Position } from './src/core/Position'; export { default as Location } from './src/core/Location'; export { default as Range } from './src/core/Range'; +export { default as Mutant } from './src/core/Mutant'; export * from './src-generated/stryker-core'; export * from './src/core/ReportTypes'; export * from './src/core/StrykerOptionsSchema'; export * from './src/core/PartialStrykerOptions'; -export * from './src/core/OptionsEditor'; +export * from './src/core/instrument'; +export * from './src/core/MutantCoverage'; diff --git a/packages/api/mutant.ts b/packages/api/mutant.ts deleted file mode 100644 index 71a6f27351..0000000000 --- a/packages/api/mutant.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default as Mutant } from './src/mutant/Mutant'; -export { default as Mutator } from './src/mutant/Mutator'; diff --git a/packages/api/package.json b/packages/api/package.json index 2ce58eb251..31c803e680 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -1,6 +1,6 @@ { "name": "@stryker-mutator/api", - "version": "3.3.1", + "version": "4.0.0-beta.10", "description": "The api for the extendable JavaScript mutation testing framework Stryker", "repository": { "type": "git", @@ -8,8 +8,8 @@ }, "scripts": { "stryker": "node ../core/bin/stryker run", - "test": "nyc --exclude-after-remap=false --check-coverage --reporter=html --report-dir=reports/coverage --lines 85 --functions 85 --branches 80 npm run mocha", - "mocha": "mocha \"test/helpers/**/*.js\" \"test/unit/**/*.js\"" + "test": "nyc npm run test:unit", + "test:unit": "mocha \"test/unit/**/*.js\"" }, "keywords": [ "mutation testing", @@ -44,6 +44,6 @@ }, "devDependencies": { "@types/node": "^14.0.1", - "typed-inject": "~2.2.1" + "typed-inject": "~3.0.0" } } diff --git a/packages/api/report.ts b/packages/api/report.ts index 08a75c6655..e1b98a97be 100644 --- a/packages/api/report.ts +++ b/packages/api/report.ts @@ -1,7 +1,7 @@ import * as mutationTestReportSchema from 'mutation-testing-report-schema/dist/src/api'; export { default as Reporter } from './src/report/Reporter'; -export { default as MutantResult } from './src/report/MutantResult'; +export * from './src/report/MutantResult'; export { default as MutantStatus } from './src/report/MutantStatus'; export { default as SourceFile } from './src/report/SourceFile'; export { default as MatchedMutant } from './src/report/MatchedMutant'; diff --git a/packages/api/schema/stryker-core.json b/packages/api/schema/stryker-core.json index b15f9f4b2d..dc43cc3657 100644 --- a/packages/api/schema/stryker-core.json +++ b/packages/api/schema/stryker-core.json @@ -37,6 +37,15 @@ "Trace" ] }, + "coverageAnalysis": { + "title": "CoverageAnalysis", + "type": "string", + "enum": [ + "off", + "all", + "perTest" + ] + }, "reportType": { "title": "ReportType", "type": "string", @@ -159,11 +168,8 @@ "type": "object", "additionalProperties": false, "properties": { - "name": { - "type": "string", - "default": "javascript" - }, "plugins": { + "description": "Override the default babel plugins Stryker uses to parse your JavaScript files. The default list of plugins is extensive and normally doesn't need overriding. Stryker also loads your babel plugins by default (if you have them). If Stryker's default babel plugins conflicts with your plugins, try to override this list with an empty array.", "anyOf": [ { "type": "array", @@ -187,10 +193,7 @@ }, "default": [] } - }, - "required": [ - "name" - ] + } }, "warningOptions": { "title": "WarningOptions", @@ -201,6 +204,11 @@ "description": "decide whether or not to log warnings when additional stryker options are configured", "type": "boolean", "default": true + }, + "preprocessorErrors": { + "description": "decide whether or not to log warnings when a preprocessor error occurs. For example, when the disabling of type errors fails.", + "type": "boolean", + "default": true } } } @@ -211,19 +219,40 @@ "type": "boolean", "default": true }, + "buildCommand": { + "type": "string", + "description": "Configure a build command to run after mutating the code, but before mutants are tested. This is generally used to transpile your code before testing. Only configure this if your test runner doesn't take care of this already and you're not using just-in-time transpiler like `babel/register` or `ts-node`.", + "examples": [ + "tsc -b", + "babel src --out-dir lib", + "npm run build" + ] + }, + "checkers": { + "description": "Enable checker plugins here. A checker plugin will be invoked for each mutant before it is run in a test runner. It can check to see of a given mutant is valid, by for example validate that it won't result in a type error", + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "concurrency": { + "description": "Set the concurrency of workers. Stryker will always run checkers and test runners in parallel by creating worker processes (note, not `worker_threads`). This defaults to n-1 where n is the number of cpu's available on your machine. This is a sane default for most use cases.", + "type": "number" + }, + "maxTestRunnerReuse": { + "description": "Restart each forked threads after runs. Not recommended unless you are experiencing memory leaks that you are unable to resolve. (default: 0)", + "type": "number", + "default": 0 + }, "commandRunner": { "description": "Options used by the command test runner. Note: these options will only be used when the command test runner is activated (this is the default)", "$ref": "#/definitions/commandRunnerOptions", "default": {} }, "coverageAnalysis": { + "$ref": "#/definitions/coverageAnalysis", "description": "Indicates which coverage analysis strategy to use. During mutation testing, stryker will try to only run the tests that cover a particular line of code.\n\n'perTest': Analyse coverage per test.\n'all': Analyse the coverage for the entire test suite.\n'off' (default): Don't use coverage analysis", - "type": "string", - "enum": [ - "off", - "all", - "perTest" - ], "default": "off" }, "clearTextReporter": { @@ -259,7 +288,7 @@ "default": "info" }, "maxConcurrentTestRunners": { - "description": "Specifies the maximum number of concurrent test runners to spawn. Mutation testing is time consuming. By default, Stryker tries to make the most of your CPU's, by spawning as many test runners as you have CPU cores (`Number.MAX_SAFE_INTEGER`).", + "description": "[DEPRECATED please use \"concurrency\" instead]. Specifies the maximum number of concurrent test runners to spawn. Mutation testing is time consuming. By default, Stryker tries to make the most of your CPU's, by spawning as many test runners as you have CPU cores (`Number.MAX_SAFE_INTEGER`).", "type": "number", "default": 9007199254740991 }, @@ -270,27 +299,20 @@ "type": "string" }, "default": [ - "{src,lib}/**/*.js?(x)", - "!{src,lib}/**/__tests__/**/*.js?(x)", - "!{src,lib}/**/?(*.)+(spec|test).js?(x)", - "!{src,lib}/**/*+(Spec|Test).js?(x)" + "{src,lib}/**/!(*.+(s|S)pec|*.+(t|T)est).+(cjs|mjs|js|ts|jsx|tsx|html|vue)", + "!{src,lib}/**/__tests__/**/*.+(cjs|mjs|js|ts|jsx|tsx|html|vue)" ] }, "mutator": { - "description": "With mutator you configure which mutator plugin you want to use, and optionally, which mutation types to exclude from the test run.", - "oneOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/mutatorDescriptor" - } - ], - "default": "javascript", - "errorMessage": "should be an \"object\" describing the mutator or a \"string\". See https://github.com/stryker-mutator/stryker/tree/master/packages/core#mutator." + "description": "Configure how Stryker mutates your code.", + "$ref": "#/definitions/mutatorDescriptor", + "default": {} }, "packageManager": { - "enum": ["npm", "yarn"], + "enum": [ + "npm", + "yarn" + ], "description": "The package manager Stryker can use to install missing dependencies." }, "plugins": { @@ -303,6 +325,14 @@ "@stryker-mutator/*" ] }, + "appendPlugins": { + "description": "A list of additional plugins you want Stryker to load (`require`) without overwriting the (default) `plugins`.", + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, "reporters": { "description": "With reporters, you can set the reporters for stryker to use.", "type": "array", @@ -319,6 +349,20 @@ "description": "The options for the html reporter", "$ref": "#/definitions/htmlReporterOptions" }, + "disableTypeChecks": { + "description": "Configure a pattern that matches the files of which type checking has to be disabled. This is needed because Stryker will create (typescript) type errors when inserting the mutants in your code. Stryker disables type checking by inserting `// @ts-nocheck` atop those files and removing other `// @ts-xxx` directives (so they won't interfere with `@ts-nocheck`). The default setting allows these directives to be stripped from all JavaScript and friend files in `lib`, `src` and `test` directories. You can specify a different glob expression or set it to `false` to completely disable this behavior.", + "anyOf": [ + { + "enum": [ + false + ] + }, + { + "type": "string" + } + ], + "default": "{test,src,lib}/**/*.{js,ts,jsx,tsx,html,vue}" + }, "symlinkNodeModules": { "description": "The 'symlinkNodeModules' value indicates whether Stryker should create a symbolic link to your current node_modules directory in the sandbox directories. This makes running your tests by Stryker behave more like your would run the tests yourself in your project directory. Only disable this setting if you really know what you are doing.", "type": "boolean", @@ -329,9 +373,10 @@ "type": "string", "default": ".stryker-tmp" }, - "testFramework": { - "description": "Configure which test framework you are using. This option is not mandatory, as Stryker is test framework agnostic (it doesn't care what framework you use), However, it is required when coverageAnalysis is set to 'perTest', because Stryker needs to hook into the test framework in order to measure code coverage results per test and filter tests to run.", - "type": "string" + "cleanTempDir": { + "description": "Choose whether or not to clean the temp dir (which is \".stryker-tmp\" inside the current working directory by default) after a successful run. The temp dir will never be removed when the run failed for some reason (for debugging purposes)", + "type": "boolean", + "default": true }, "testRunner": { "description": "With 'testRunner' you specify the test runner that Stryker uses to run your tests. The default value is command. The command runner runs a configurable bash/cmd command and bases the result on the exit code of that program (0 for success, otherwise failed). You can configure this command via the config file using the 'commandRunner: { command: 'npm run mocha' }'. It uses 'npm test' as the command by default.", @@ -353,13 +398,10 @@ "type": "number", "default": 5000 }, - "transpilers": { - "description": "Configure which transpiler plugins should transpile the code before it's executed. This is an array where the transpilers are called in the other of the array. This defaults to an empty array meaning no transpilation will be done.", - "type": "array", - "items": { - "type": "string" - }, - "default": [] + "tsconfigFile": { + "description": "Configure the (root) tsconfig file for typescript projects. This will allow Stryker to rewrite the `extends` and `references` settings in this and related tsconfig files in your sandbox. Defaults to `tsconfig.json`. This setting is also used when you enable the `@stryker-mutator/typescript-checker plugin", + "type": "string", + "default": "tsconfig.json" }, "warnings": { "default": true, diff --git a/packages/api/src/check/CheckResult.ts b/packages/api/src/check/CheckResult.ts new file mode 100644 index 0000000000..ed60dfa8e5 --- /dev/null +++ b/packages/api/src/check/CheckResult.ts @@ -0,0 +1,12 @@ +import { CheckStatus } from './CheckStatus'; + +export interface FailedCheckResult { + reason: string; + status: CheckStatus.CompileError; +} + +export interface PassedCheckResult { + status: CheckStatus.Passed; +} + +export type CheckResult = PassedCheckResult | FailedCheckResult; diff --git a/packages/api/src/check/CheckStatus.ts b/packages/api/src/check/CheckStatus.ts new file mode 100644 index 0000000000..4cb33da6bb --- /dev/null +++ b/packages/api/src/check/CheckStatus.ts @@ -0,0 +1,4 @@ +export enum CheckStatus { + Passed = 'passed', + CompileError = 'compileError', +} diff --git a/packages/api/src/check/Checker.ts b/packages/api/src/check/Checker.ts new file mode 100644 index 0000000000..21401407b8 --- /dev/null +++ b/packages/api/src/check/Checker.ts @@ -0,0 +1,9 @@ +import { Mutant } from '../../core'; + +import { CheckResult } from './CheckResult'; + +export interface Checker { + init(): Promise; + + check(mutant: Mutant): Promise; +} diff --git a/packages/api/src/check/MutantStatus.ts b/packages/api/src/check/MutantStatus.ts new file mode 100644 index 0000000000..fe94b88bb2 --- /dev/null +++ b/packages/api/src/check/MutantStatus.ts @@ -0,0 +1,10 @@ +export enum MutantStatus { + Init = 'init', + Ignored = 'ignored', + NoCoverage = 'noCoverage', + Killed = 'killed', + Survived = 'survived', + TimedOut = 'timedOut', + RuntimeError = 'runtimeError', + CompileError = 'compileError', +} diff --git a/packages/api/src/config/Config.ts b/packages/api/src/config/Config.ts deleted file mode 100644 index 22567b349c..0000000000 --- a/packages/api/src/config/Config.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { StrykerOptions } from '../../core'; -import { PartialStrykerOptions } from '../../core'; - -/** - * @deprecated Use `StrykerOptions` instead - */ -export default interface Config extends StrykerOptions { - set(newConfig: PartialStrykerOptions): void; -} diff --git a/packages/api/src/config/ConfigEditor.ts b/packages/api/src/config/ConfigEditor.ts deleted file mode 100644 index 5c1a952884..0000000000 --- a/packages/api/src/config/ConfigEditor.ts +++ /dev/null @@ -1,25 +0,0 @@ -import Config from './Config'; - -/** - * Represents a ConfigEditor plugin - * - * ConfigEditors can change the content of the stryker runtime configuration - * ConfigEditors are implemented as a chain of ConfigEditors, the result of - * any previous ConfigEditor can be passed thru to the next. Please not that - * editing of the configuration object is done by reference. - * - * @deprecated Please use `OptionsEditor` instead - */ -interface ConfigEditor { - /** - * Extending classes only need to implement the edit method, this method - * receives a writable config object that can be edited in any way. - * Please be aware that editing is done via object reference. Therefore - * the return type is void. - * - * @param config: The stryker configuration object - */ - edit(config: Config): void; -} - -export default ConfigEditor; diff --git a/packages/api/src/core/Mutant.ts b/packages/api/src/core/Mutant.ts new file mode 100644 index 0000000000..192a3944c1 --- /dev/null +++ b/packages/api/src/core/Mutant.ts @@ -0,0 +1,38 @@ +import Range from './Range'; +import Location from './Location'; + +/** + * Represents a mutant + */ +interface Mutant { + /** + * The id of the mutant. Unique within a run. + */ + id: number; + /** + * The name of the mutator that generated this mutant. + */ + mutatorName: string; + /** + * The file name from which this mutant originated + */ + fileName: string; + /** + * The range of this mutant (from/to within the file) + */ + range: Range; + /** + * The line number/column location of this mutant + */ + location: Location; + /** + * The replacement (actual mutated code) + */ + replacement: string; + /** + * If the mutant was ignored during generation, the reason for ignoring it, otherwise `undefined` + */ + ignoreReason?: string; +} + +export default Mutant; diff --git a/packages/api/src/core/MutantCoverage.ts b/packages/api/src/core/MutantCoverage.ts new file mode 100644 index 0000000000..2170c27be9 --- /dev/null +++ b/packages/api/src/core/MutantCoverage.ts @@ -0,0 +1,12 @@ +export interface MutantCoverage { + static: CoverageData; + perTest: CoveragePerTestId; +} + +export interface CoveragePerTestId { + [testId: string]: CoverageData; +} + +export interface CoverageData { + [mutantId: number]: number; +} diff --git a/packages/api/src/core/OptionsEditor.ts b/packages/api/src/core/OptionsEditor.ts deleted file mode 100644 index df61720203..0000000000 --- a/packages/api/src/core/OptionsEditor.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { StrykerOptions } from '../../core'; - -/** - * Represents an OptionsEditor plugin - * - * OptionEditors can change the content of the stryker options at runtime. - * OptionEditors are implemented as a chain of OptionEditors, the result of - * any previous ConfigEditor can be passed thru to the next. Please not that - * editing of the configuration object is done by reference. - * - */ -export interface OptionsEditor { - /** - * Extending classes only need to implement the edit method, this method - * receives a writable config object that can be edited in any way. - * Please be aware that editing is done via object reference. Therefore - * the return type is void. - * - * @param options: The stryker configuration object - */ - edit(options: T): void; -} diff --git a/packages/api/src/core/PartialStrykerOptions.ts b/packages/api/src/core/PartialStrykerOptions.ts index a46f1afd5d..02b571bd23 100644 --- a/packages/api/src/core/PartialStrykerOptions.ts +++ b/packages/api/src/core/PartialStrykerOptions.ts @@ -8,5 +8,5 @@ import { StrykerOptions } from '../../core'; export type PartialStrykerOptions = DeepPartial; type DeepPartial = { - [P in keyof T]?: T[P] extends object ? DeepPartial | undefined : T[P]; + [P in keyof T]?: T[P] extends Record ? DeepPartial | undefined : T[P]; }; diff --git a/packages/api/src/core/Range.ts b/packages/api/src/core/Range.ts index 9eea4e83ff..0bf0bed25d 100644 --- a/packages/api/src/core/Range.ts +++ b/packages/api/src/core/Range.ts @@ -1,6 +1,6 @@ /** - * Represents a location in a file by range [fromInclusive, toExclusive] + * Represents a location in a file by range. */ -type Range = [number, number]; +type Range = [fromInclusive: number, toExclusive: number]; export default Range; diff --git a/packages/api/src/core/StrykerOptionsSchema.ts b/packages/api/src/core/StrykerOptionsSchema.ts index ef0d79c59e..15d264c117 100644 --- a/packages/api/src/core/StrykerOptionsSchema.ts +++ b/packages/api/src/core/StrykerOptionsSchema.ts @@ -1,3 +1,3 @@ -const strykerCoreSchema: object = require('../../schema/stryker-core.json'); +const strykerCoreSchema: Record = require('../../schema/stryker-core.json'); export { strykerCoreSchema }; diff --git a/packages/api/src/core/instrument.ts b/packages/api/src/core/instrument.ts new file mode 100644 index 0000000000..09482037d3 --- /dev/null +++ b/packages/api/src/core/instrument.ts @@ -0,0 +1,22 @@ +import { MutantCoverage } from './MutantCoverage'; + +/** + * Identifiers used when instrumenting the code + */ +export const INSTRUMENTER_CONSTANTS = Object.freeze({ + NAMESPACE: '__stryker__', + MUTATION_COVERAGE_OBJECT: identity('mutantCoverage'), + ACTIVE_MUTANT: identity('activeMutant'), + CURRENT_TEST_ID: identity('currentTestId'), + ACTIVE_MUTANT_ENV_VARIABLE: '__STRYKER_ACTIVE_MUTANT__', +} as const); + +export interface InstrumenterContext { + activeMutant?: number; + currentTestId?: string; + mutantCoverage?: MutantCoverage; +} + +function identity(key: T): T { + return key; +} diff --git a/packages/api/src/mutant/Mutant.ts b/packages/api/src/mutant/Mutant.ts deleted file mode 100644 index 3acf19b452..0000000000 --- a/packages/api/src/mutant/Mutant.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Range } from '../../core'; - -interface Mutant { - mutatorName: string; - fileName: string; - range: Range; - replacement: string; -} - -export default Mutant; diff --git a/packages/api/src/mutant/Mutator.ts b/packages/api/src/mutant/Mutator.ts deleted file mode 100644 index 21e6050162..0000000000 --- a/packages/api/src/mutant/Mutator.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { File } from '../../core'; - -import Mutant from './Mutant'; - -export default interface Mutator { - mutate(inputFiles: readonly File[]): readonly Mutant[]; -} diff --git a/packages/api/src/plugin/Contexts.ts b/packages/api/src/plugin/Contexts.ts index b27e4a7f41..084d9c505b 100644 --- a/packages/api/src/plugin/Contexts.ts +++ b/packages/api/src/plugin/Contexts.ts @@ -1,7 +1,6 @@ -import { MutatorDescriptor, StrykerOptions } from '../../core'; +import { StrykerOptions } from '../../core'; import { Logger, LoggerFactoryMethod } from '../../logging'; -import { PluginKind } from './PluginKind'; import { PluginResolver } from './Plugins'; import { commonTokens } from './tokens'; @@ -18,34 +17,6 @@ export interface BaseContext { * The dependency injection context for most of Stryker's plugins. * Can inject basic stuff as well as the Stryker options */ -export interface OptionsContext extends BaseContext { +export interface PluginContext extends BaseContext { [commonTokens.options]: StrykerOptions; - [commonTokens.mutatorDescriptor]: MutatorDescriptor; -} - -/** - * The dependency injection context for a `TranspilerPlugin` - */ -export interface TranspilerPluginContext extends OptionsContext { - [commonTokens.produceSourceMaps]: boolean; -} - -/** - * The dependency injection context for a `TestRunnerPlugin` - */ -export interface TestRunnerPluginContext extends OptionsContext { - [commonTokens.sandboxFileNames]: readonly string[]; -} - -/** - * Lookup type for plugin contexts by kind. - */ -export interface PluginContexts { - [PluginKind.ConfigEditor]: BaseContext; - [PluginKind.OptionsEditor]: BaseContext; - [PluginKind.Mutator]: OptionsContext; - [PluginKind.Reporter]: OptionsContext; - [PluginKind.TestFramework]: OptionsContext; - [PluginKind.TestRunner]: TestRunnerPluginContext; - [PluginKind.Transpiler]: TranspilerPluginContext; } diff --git a/packages/api/src/plugin/PluginKind.ts b/packages/api/src/plugin/PluginKind.ts index d9e8133696..f3d190029d 100644 --- a/packages/api/src/plugin/PluginKind.ts +++ b/packages/api/src/plugin/PluginKind.ts @@ -2,14 +2,7 @@ * The plugin kinds supported by Stryker */ export enum PluginKind { - /** - * @deprecated, please use `OptionsEditor` - */ - ConfigEditor = 'ConfigEditor', - OptionsEditor = 'OptionsEditor', + Checker = 'Checker', TestRunner = 'TestRunner', - TestFramework = 'TestFramework', - Transpiler = 'Transpiler', - Mutator = 'Mutator', Reporter = 'Reporter', } diff --git a/packages/api/src/plugin/Plugins.ts b/packages/api/src/plugin/Plugins.ts index 9b5e8f0dd7..f54be0cfb7 100644 --- a/packages/api/src/plugin/Plugins.ts +++ b/packages/api/src/plugin/Plugins.ts @@ -1,46 +1,42 @@ import { InjectableClass, InjectableFunction, InjectionToken } from 'typed-inject'; -import { ConfigEditor } from '../../config'; -import { Mutator } from '../../mutant'; import { Reporter } from '../../report'; -import { TestFramework } from '../../test_framework'; import { TestRunner } from '../../test_runner'; -import { Transpiler } from '../../transpile'; -import { OptionsEditor } from '../core/OptionsEditor'; +import { Checker } from '../../check'; -import { PluginContexts } from './Contexts'; +import { PluginContext } from './Contexts'; import { PluginKind } from './PluginKind'; /** * Represents a StrykerPlugin */ export type Plugin = - | FactoryPlugin>> - | ClassPlugin>>; + | FactoryPlugin>> + | ClassPlugin>>; /** * Represents a plugin that is created with a factory method */ -export interface FactoryPlugin>> { +export interface FactoryPlugin>> { readonly kind: TPluginKind; readonly name: string; /** * The factory method used to create the plugin */ - readonly factory: InjectableFunction; + readonly factory: InjectableFunction; } /** * Represents a plugin that is created by instantiating a class. */ -export interface ClassPlugin>> { +export interface ClassPlugin>> { readonly kind: TPluginKind; readonly name: string; /** * The prototype function (class) used to create the plugin. * Not called `class` here, because that is a keyword */ - readonly injectableClass: InjectableClass; + readonly injectableClass: InjectableClass; } /** @@ -49,10 +45,10 @@ export interface ClassPlugin>>( +export function declareClassPlugin>>( kind: TPluginKind, name: string, - injectableClass: InjectableClass + injectableClass: InjectableClass ): ClassPlugin { return { injectableClass, @@ -67,10 +63,10 @@ export function declareClassPlugin>>( +export function declareFactoryPlugin>>( kind: TPluginKind, name: string, - factory: InjectableFunction + factory: InjectableFunction ): FactoryPlugin { return { factory, @@ -83,13 +79,9 @@ export function declareFactoryPlugin(kind: T, name: string): Plugins[T]; resolveAll(kind: T): Array; - resolveValidationSchemaContributions(): object[]; + resolveValidationSchemaContributions(): Array>; } diff --git a/packages/api/src/plugin/tokens.ts b/packages/api/src/plugin/tokens.ts index 89ff3500a4..897044e71e 100644 --- a/packages/api/src/plugin/tokens.ts +++ b/packages/api/src/plugin/tokens.ts @@ -16,11 +16,9 @@ export const commonTokens = Object.freeze({ getLogger: stringLiteral('getLogger'), injector, logger: stringLiteral('logger'), - mutatorDescriptor: stringLiteral('mutatorDescriptor'), options: stringLiteral('options'), pluginResolver: stringLiteral('pluginResolver'), produceSourceMaps: stringLiteral('produceSourceMaps'), - sandboxFileNames: stringLiteral('sandboxFileNames'), target, }); diff --git a/packages/api/src/report/MatchedMutant.ts b/packages/api/src/report/MatchedMutant.ts index 8c3a2c300f..f16953aed0 100644 --- a/packages/api/src/report/MatchedMutant.ts +++ b/packages/api/src/report/MatchedMutant.ts @@ -14,7 +14,7 @@ interface MatchedMutant { /** * If not all tests will run for this mutant, this array will contain the ids of the tests that will run. */ - readonly scopedTestIds: number[]; + readonly testFilter: string[] | undefined; /** * The time spent on the tests that will run in initial test run */ diff --git a/packages/api/src/report/MutantResult.ts b/packages/api/src/report/MutantResult.ts index bf18035639..5c6012d262 100644 --- a/packages/api/src/report/MutantResult.ts +++ b/packages/api/src/report/MutantResult.ts @@ -2,17 +2,40 @@ import { Location, Range } from '../../core'; import MutantStatus from './MutantStatus'; -interface MutantResult { +export interface BaseMutantResult { id: string; - sourceFilePath: string; + fileName: string; mutatorName: string; - status: MutantStatus; replacement: string; originalLines: string; mutatedLines: string; - testsRan: string[]; + nrOfTestsRan: number; location: Location; range: Range; } -export default MutantResult; +export interface KilledMutantResult extends BaseMutantResult { + status: MutantStatus.Killed; + killedBy: string; +} + +export interface InvalidMutantResult extends BaseMutantResult { + status: MutantStatus.RuntimeError | MutantStatus.CompileError; + errorMessage: string; +} + +export interface IgnoredMutantResult extends BaseMutantResult { + status: MutantStatus.Ignored; + ignoreReason: string; +} + +export interface UndetectedMutantResult extends BaseMutantResult { + status: MutantStatus.NoCoverage | MutantStatus.Survived; + testFilter: string[] | undefined; +} + +export interface TimeoutMutantResult extends BaseMutantResult { + status: MutantStatus.TimedOut; +} + +export type MutantResult = TimeoutMutantResult | UndetectedMutantResult | InvalidMutantResult | KilledMutantResult | IgnoredMutantResult; diff --git a/packages/api/src/report/MutantStatus.ts b/packages/api/src/report/MutantStatus.ts index 71122292db..009f508f46 100644 --- a/packages/api/src/report/MutantStatus.ts +++ b/packages/api/src/report/MutantStatus.ts @@ -21,28 +21,26 @@ enum MutantStatus { /** * The status of a mutant of which the tests resulted in a runtime error. - * - * For example: the following piece of javascript code will result in a runtime error: - * + * @example * ```javascript * const fs = require('f' - 's'); // mutated code * ``` - * - * Mutants that result in a runtime error are not taken into account during score calculation. */ RuntimeError, /** - * The status of a mutant which could not be transpiled. - * For example: the following piece of typescript code will give a TranspileError: - * + * The status of a mutant which could not be compiled. + * @example * ```typescript - * const a: 5 = 0; // mutated code + * const foo = 'foo' - 'bar'; // mutated code * ``` - * - * Mutants that result in a TranspileError are not taken into account during score calculation. */ - TranspileError, + CompileError, + + /** + * The status of a mutant that is ignored. For example, by user configuration. + */ + Ignored, } export default MutantStatus; diff --git a/packages/api/src/report/Reporter.ts b/packages/api/src/report/Reporter.ts index ae8e098db6..386c563d52 100644 --- a/packages/api/src/report/Reporter.ts +++ b/packages/api/src/report/Reporter.ts @@ -1,7 +1,7 @@ import { MutationTestResult } from 'mutation-testing-report-schema'; import MatchedMutant from './MatchedMutant'; -import MutantResult from './MutantResult'; +import { MutantResult } from './MutantResult'; import SourceFile from './SourceFile'; /** @@ -51,7 +51,7 @@ interface Reporter { * Stryker will not close until the promise is either resolved or rejected. * @return a promise which will resolve when the reporter is done reporting */ - wrapUp?(): void | Promise; + wrapUp?(): void | Promise | Promise; } export default Reporter; diff --git a/packages/api/src/test_framework/TestFramework.ts b/packages/api/src/test_framework/TestFramework.ts deleted file mode 100644 index 4da00e02a1..0000000000 --- a/packages/api/src/test_framework/TestFramework.ts +++ /dev/null @@ -1,30 +0,0 @@ -import TestSelection from './TestSelection'; - -/** - * Represents a TestFramework which can select one or more tests to be executed. - */ -interface TestFramework { - /** - * Creates a code fragment which, if included in a test run, - * is ran before a particular test is run. - */ - beforeEach(codeFragment: string): string; - - /** - * Creates a code fragment which, if included in a test run, - * is ran before a particular test is run. - */ - afterEach(codeFragment: string): string; - - /** - * Creates a code fragment which, if included in a test run, - * will be responsible for filtering out tests with given test selector. - * If te test selection array is empty it should reset the filtering for the next test run. - * - * @param selections A list indicating the tests to select. - * @returns A script which, if included in the test run, will filter out the correct tests. - */ - filter(selections: TestSelection[]): string; -} - -export default TestFramework; diff --git a/packages/api/src/test_framework/TestSelection.ts b/packages/api/src/test_framework/TestSelection.ts deleted file mode 100644 index 2edf46c511..0000000000 --- a/packages/api/src/test_framework/TestSelection.ts +++ /dev/null @@ -1,4 +0,0 @@ -export default interface TestSelection { - id: number; - name: string; -} diff --git a/packages/api/src/test_runner/Coverage.ts b/packages/api/src/test_runner/Coverage.ts deleted file mode 100644 index a85a6cf013..0000000000 --- a/packages/api/src/test_runner/Coverage.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { Location } from '../../core'; - -/** - * Represents a collection of code coverage results per test run. - */ -export interface CoveragePerTestResult { - /** - * The baseline coverage which is true for each test run. - * This baseline should be taken when all files all loaded, but before tests are ran. - */ - baseline: CoverageCollection; - /** - * The deviations with respect to the baseline per test. - */ - deviations: CoverageCollectionPerTest; -} - -/** - * Represents a collection of code coverage results per test run. - */ -export interface CoverageCollectionPerTest { - [testId: number]: CoverageCollection; -} - -/** - * Represents a collection of Coverage results for a set of files. - */ -export interface CoverageCollection { - /** - * An array of CoverageResults for files. - */ - [filename: string]: CoverageResult; -} - -/** - * Represents the coverage result for a single file. - */ -export interface CoverageResult { - /** - * Hash of statement counts, where keys are statement IDs. - */ - s: CoverageData; - /** - * Hash of function counts, where keys are statement IDs. - */ - f: CoverageData; -} - -/** - * Indicates the amount of time a certain type of data was covered. - * The key depends on the context. This can for example be a line number, making the value the amount of times the line was covered. - */ -export interface CoverageData { - [ref: string]: number; -} - -/** - * Hash where keys are statement IDs, and values are Location objects for each statement. - * The Location for a function definition is really an assignment, and should include the entire function. - */ -export interface StatementMap { - [ref: string]: Location; -} diff --git a/packages/api/src/test_runner/DryRunResult.ts b/packages/api/src/test_runner/DryRunResult.ts new file mode 100644 index 0000000000..df71fb73aa --- /dev/null +++ b/packages/api/src/test_runner/DryRunResult.ts @@ -0,0 +1,38 @@ +import { MutantCoverage } from '../core/MutantCoverage'; + +import { DryRunStatus } from './DryRunStatus'; +import { TestResult } from './TestResult'; + +export type DryRunResult = CompleteDryRunResult | TimeoutDryRunResult | ErrorDryRunResult; + +export interface CompleteDryRunResult { + /** + * The individual test results. + */ + tests: TestResult[]; + + mutantCoverage?: MutantCoverage; + + /** + * The status of the run + */ + status: DryRunStatus.Complete; +} +export interface TimeoutDryRunResult { + /** + * The status of the run + */ + status: DryRunStatus.Timeout; +} + +export interface ErrorDryRunResult { + /** + * The status of the run + */ + status: DryRunStatus.Error; + + /** + * If `state` is `error`, this collection should contain the error messages + */ + errorMessage: string; +} diff --git a/packages/api/src/test_runner/DryRunStatus.ts b/packages/api/src/test_runner/DryRunStatus.ts new file mode 100644 index 0000000000..7c17b022ac --- /dev/null +++ b/packages/api/src/test_runner/DryRunStatus.ts @@ -0,0 +1,14 @@ +export enum DryRunStatus { + /** + * Indicates that a test run is completed with failed or succeeded tests + */ + Complete = 'complete', + /** + * Indicates that a test run cut off early with an error + */ + Error = 'error', + /** + * Indicates that a test run timed out + */ + Timeout = 'timeout', +} diff --git a/packages/api/src/test_runner/MutantRunResult.ts b/packages/api/src/test_runner/MutantRunResult.ts new file mode 100644 index 0000000000..603018cd0e --- /dev/null +++ b/packages/api/src/test_runner/MutantRunResult.ts @@ -0,0 +1,41 @@ +export enum MutantRunStatus { + Killed = 'killed', + Survived = 'survived', + Timeout = 'timeout', + Error = 'error', +} + +export type MutantRunResult = KilledMutantRunResult | SurvivedMutantRunResult | TimeoutMutantRunResult | ErrorMutantRunResult; + +export interface TimeoutMutantRunResult { + status: MutantRunStatus.Timeout; +} + +export interface KilledMutantRunResult { + status: MutantRunStatus.Killed; + /** + * The id of the test that killed this mutant + */ + killedBy: string; + /** + * The failure message that was reported by the test + */ + failureMessage: string; + /** + * The number of total tests ran in this test run. + */ + nrOfTests: number; +} + +export interface SurvivedMutantRunResult { + status: MutantRunStatus.Survived; + /** + * The number of total tests ran in this test run. + */ + nrOfTests: number; +} + +export interface ErrorMutantRunResult { + status: MutantRunStatus.Error; + errorMessage: string; +} diff --git a/packages/api/src/test_runner/RunOptions.ts b/packages/api/src/test_runner/RunOptions.ts index 4474c12b9a..c66b0a4f7d 100644 --- a/packages/api/src/test_runner/RunOptions.ts +++ b/packages/api/src/test_runner/RunOptions.ts @@ -1,19 +1,23 @@ -/** - * Represents an options object for a single run of a TestRunner. - */ -interface RunOptions { +import { Mutant, CoverageAnalysis } from '../../core'; + +export interface RunOptions { /** * The amount of time (in milliseconds) the TestRunner has to complete the test run before a timeout occurs. */ timeout: number; +} +export interface DryRunOptions extends RunOptions { /** - * The hooks JavaScript code that has to be loaded in the testing environment. - * It should be loaded right after the test framework but right before any tests can run. + * Indicates whether or not mutant coverage should be collected. */ - testHooks?: string; + coverageAnalysis: CoverageAnalysis; +} - mutatedFileName?: string; +export interface MutantRunOptions extends RunOptions { + testFilter?: string[]; + activeMutant: Mutant; + sandboxFileName: string; } export default RunOptions; diff --git a/packages/api/src/test_runner/RunResult.ts b/packages/api/src/test_runner/RunResult.ts deleted file mode 100644 index d554e86f33..0000000000 --- a/packages/api/src/test_runner/RunResult.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { CoverageCollection, CoveragePerTestResult } from './Coverage'; -import RunStatus from './RunStatus'; -import TestResult from './TestResult'; - -/** - * Represents the result of a test run. - */ -interface RunResult { - /** - * The individual test results. - */ - tests: TestResult[]; - - /** - * If `state` is `error`, this collection should contain the error messages - */ - errorMessages?: string[]; - - /** - * The status of the run - */ - status: RunStatus; - - /** - * Optional: the code coverage result of the run. - */ - coverage?: CoverageCollection | CoveragePerTestResult; -} - -export default RunResult; diff --git a/packages/api/src/test_runner/RunStatus.ts b/packages/api/src/test_runner/RunStatus.ts deleted file mode 100644 index 2650e2c405..0000000000 --- a/packages/api/src/test_runner/RunStatus.ts +++ /dev/null @@ -1,16 +0,0 @@ -enum RunStatus { - /** - * Indicates that a test run is completed with failed or succeeded tests - */ - Complete, - /** - * Indicates that a test run cut off early with an error - */ - Error, - /** - * Indicates that a test run timed out - */ - Timeout, -} - -export default RunStatus; diff --git a/packages/api/src/test_runner/TestResult.ts b/packages/api/src/test_runner/TestResult.ts index 7ee997e336..046fcf49bd 100644 --- a/packages/api/src/test_runner/TestResult.ts +++ b/packages/api/src/test_runner/TestResult.ts @@ -1,25 +1,34 @@ -import TestStatus from './TestStatus'; +import { TestStatus } from './TestStatus'; /** * Indicates the result of a single test */ -interface TestResult { +interface BaseTestResult { /** - * The full human readable name of the test + * The id of this test. Can be the name if the test runner doesn't have an 'id' */ - name: string; + id: string; /** - * The status of the test + * The full human readable name of the test */ - status: TestStatus; + name: string; /** * The time it took to run the test */ timeSpentMs: number; - /** - * Optional: messages in case of status: Failed - */ - failureMessages?: string[]; } -export default TestResult; +export interface FailedTestResult extends BaseTestResult { + status: TestStatus.Failed; + failureMessage: string; +} + +export interface SkippedTestResult extends BaseTestResult { + status: TestStatus.Skipped; +} + +export interface SuccessTestResult extends BaseTestResult { + status: TestStatus.Success; +} + +export type TestResult = SuccessTestResult | FailedTestResult | SkippedTestResult; diff --git a/packages/api/src/test_runner/TestRunner.ts b/packages/api/src/test_runner/TestRunner.ts index ddbdecca41..1075b55121 100644 --- a/packages/api/src/test_runner/TestRunner.ts +++ b/packages/api/src/test_runner/TestRunner.ts @@ -1,58 +1,10 @@ -import RunOptions from './RunOptions'; -import RunResult from './RunResult'; - -/** - * Represents a TestRunner which can execute tests, resulting in a RunResult. - * - * A test runner should: - * - Report a `testResult` per test. See `TestResult` interface to know what is expected. - * - Report on code coverage after the initial test run (maybe, see below). - * - * ## A note on code coverage: - * - * TL;DR - * If the test runner ran the tests in the same process as the test runner is spawned in, it doesn't have to do anything. - * If it runs in a different process (i.e. a worker process) or uses a browser (i.e. karma) it needs to do something, see below. - * - * Collecting code coverage can improve the performance of a mutation test run quite a bit. Instead of running all tests for all mutants, - * it can select which tests to run per mutant. Code coverage is a shared responsibility between Stryker and the test runner depending on the - * `coverageStrategy`: - * - * 1. If `coverageAnalysis: 'off'`: No code coverage should be collected. - * 2. If `coverageStrategy: 'all'`: Coverage should be collected for the entire test run. - * 3. If `coverageStrategy: 'perTest'`: Coverage should be collected per test. - * - * For 2 and 3, Stryker will instrument the code with the istanbul code coverage engine during initial run. - * In case of 3, Stryker will also inject beforeEach and afterEach hooks (specific to each test framework) in distinct between specific tests. - * - * At the end of the test run, the code coverage report is ready in a global variable called `__coverage__`. Node based test runners - * which run their tests in the same process as the test runner is spawned in actually don't have to do any work, Stryker will be able - * to pick up the report globally. However, if running in worker processes or a browser, it is the test runner's responsibility to - * report the `__coverage__` at the end of the test run. - * - * If it doesn't exists globally, you don't have to do anything. In that case it's not an initial test run and there was no code instrumented. - */ -interface TestRunner { - /** - * Optional. When implemented, will be called before runs are done on this test runner. - * @returns A promise if stuff is initialized asynchronously, runs will not start until the promise is resolved. - * Otherwise void - */ - init?(): Promise | void; - - /** - * Executes a test run. - * @param options The options for this test run. - * @returns A promise to eventually complete the test run and deliver a RunResult. - */ - run(options: RunOptions): Promise; - - /** - * Optional. When implemented, will be called before the test runner's process is killed. - * @returns A promise if stuff is destroyed asynchronously, the runners process will not end until the promise is resolved. - * Otherwise void - */ - dispose?(): Promise | void; +import { DryRunOptions, MutantRunOptions } from './RunOptions'; +import { DryRunResult } from './DryRunResult'; +import { MutantRunResult } from './MutantRunResult'; + +export interface TestRunner { + init?(): Promise; + dryRun(options: DryRunOptions): Promise; + mutantRun(options: MutantRunOptions): Promise; + dispose?(): Promise; } - -export default TestRunner; diff --git a/packages/api/src/test_runner/TestStatus.ts b/packages/api/src/test_runner/TestStatus.ts index 69bc8a823a..a25850dfe2 100644 --- a/packages/api/src/test_runner/TestStatus.ts +++ b/packages/api/src/test_runner/TestStatus.ts @@ -1,7 +1,7 @@ /** * Indicates what the result of a single test was. */ -enum TestStatus { +export enum TestStatus { /** * The test succeeded */ @@ -15,5 +15,3 @@ enum TestStatus { */ Skipped, } - -export default TestStatus; diff --git a/packages/api/src/test_runner/runResultHelpers.ts b/packages/api/src/test_runner/runResultHelpers.ts new file mode 100644 index 0000000000..e23784da1d --- /dev/null +++ b/packages/api/src/test_runner/runResultHelpers.ts @@ -0,0 +1,37 @@ +import { TestStatus } from './TestStatus'; +import { DryRunResult } from './DryRunResult'; +import { MutantRunResult } from './MutantRunResult'; +import { DryRunStatus } from './DryRunStatus'; +import { MutantRunStatus } from './MutantRunResult'; +import { FailedTestResult } from './TestResult'; + +export function toMutantRunResult(dryRunResult: DryRunResult): MutantRunResult { + switch (dryRunResult.status) { + case DryRunStatus.Complete: { + const killedBy = dryRunResult.tests.find((test): test is FailedTestResult => test.status === TestStatus.Failed); + const nrOfTests = dryRunResult.tests.filter((test) => test.status !== TestStatus.Skipped).length; + if (killedBy) { + return { + status: MutantRunStatus.Killed, + failureMessage: killedBy.failureMessage, + killedBy: killedBy.id, + nrOfTests, + }; + } else { + return { + status: MutantRunStatus.Survived, + nrOfTests, + }; + } + } + case DryRunStatus.Error: + return { + status: MutantRunStatus.Error, + errorMessage: dryRunResult.errorMessage, + }; + case DryRunStatus.Timeout: + return { + status: MutantRunStatus.Timeout, + }; + } +} diff --git a/packages/api/src/transpile/Transpiler.ts b/packages/api/src/transpile/Transpiler.ts deleted file mode 100644 index 231e66c3b4..0000000000 --- a/packages/api/src/transpile/Transpiler.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { File } from '../../core'; - -/** - * Represents a transpiler plugin. - * - * Transpilers can change the content of input files before testing. - * To ensure the max performance all actions are done in-memory, no file IO. - * Transpilers are implemented as a chain of transpilers, - * the result of any previous compiler can be passed thru to the next - * - * Transpilers are stateful. They are expected to keep track of any state needed to perform mutations on existing files. - * They are also expected to keep track of any source-maps if `keepSourceMaps` is set to true, in order to implement `getMappedLocation` - */ -export default interface Transpiler { - /** - * Transpile each file and return the result. - * Should also return any untouched files in the result. - * - * Any consecutive calls to transpile will not include all files, instead only the changed files in relation to the previous call. - * This makes any Transpiler stateful. - * - * @example An example of consecutive transpiler calls: - * - * call 1: [foo.es6, bar.es6, fooSpec.es6, barSpec.es6, image.png] - * call 2: [foo.es6 (mutated)] - * call 3: [foo.es6 (mutated)] - * call 4: [foo.es6, bar.es6 (mutated)] - * call 5: [bar.es6 (mutated)] - * - * @returns an rejection (if transpiling failed) or the output files to be used as input for the next transpiler - */ - transpile(files: readonly File[]): Promise; -} diff --git a/packages/api/stryker.conf.js b/packages/api/stryker.conf.js index fa5a53f3c4..b22c4a4195 100644 --- a/packages/api/stryker.conf.js +++ b/packages/api/stryker.conf.js @@ -1,5 +1,7 @@ const path = require('path'); const settings = require('../../stryker.parent.conf'); const moduleName = __dirname.split(path.sep).pop(); +settings.plugins = settings.plugins.map(p => path.resolve(p)); settings.dashboard.module = moduleName; +settings.files = ['{src-generated,src,test,schema}/**/*.{ts,json}', '*.{ts,json}'] module.exports = settings; diff --git a/packages/api/test/setup.ts b/packages/api/test/setup.ts new file mode 100644 index 0000000000..ca7bc2aaa8 --- /dev/null +++ b/packages/api/test/setup.ts @@ -0,0 +1,14 @@ +import 'source-map-support/register'; +import * as chai from 'chai'; +import * as chaiAsPromised from 'chai-as-promised'; +import * as sinonChai from 'sinon-chai'; +import * as sinon from 'sinon'; + +chai.use(sinonChai); +chai.use(chaiAsPromised); + +export const mochaHooks = { + afterEach() { + sinon.restore(); + }, +}; diff --git a/packages/api/test/unit/plugin/Plugins.spec.ts b/packages/api/test/unit/plugin/Plugins.spec.ts index 3e92402fa7..8499cbdd9e 100644 --- a/packages/api/test/unit/plugin/Plugins.spec.ts +++ b/packages/api/test/unit/plugin/Plugins.spec.ts @@ -4,42 +4,42 @@ import { declareClassPlugin, declareFactoryPlugin } from '../../../src/plugin/Pl import { PluginKind } from '../../../src/plugin/PluginKind'; import { tokens, commonTokens } from '../../../src/plugin/tokens'; import { Logger } from '../../../logging'; -import { Mutant } from '../../../mutant'; +import { MutantResult } from '../../../report'; describe('plugins', () => { describe(declareClassPlugin.name, () => { it('should declare a class plugin', () => { - class MyMutator { + class MyReporter { constructor(private readonly log: Logger) {} public static inject = tokens(commonTokens.logger); - public mutate(): readonly Mutant[] { - this.log.info(''); - return []; + public onMutantTested(result: MutantResult) { + this.log.info(JSON.stringify(result)); } } - expect(declareClassPlugin(PluginKind.Mutator, 'mut', MyMutator)).deep.eq({ - injectableClass: MyMutator, - kind: PluginKind.Mutator, - name: 'mut', + expect(declareClassPlugin(PluginKind.Reporter, 'rep', MyReporter)).deep.eq({ + injectableClass: MyReporter, + kind: PluginKind.Reporter, + name: 'rep', }); }); }); describe(declareFactoryPlugin.name, () => { it('should declare a factory plugin', () => { - function myMutator() { + function createReporter(log: Logger) { return { - mutate(): readonly Mutant[] { - return []; + onMutantTested(result: MutantResult) { + log.info(JSON.stringify(result)); }, }; } + createReporter.inject = tokens(commonTokens.logger); - expect(declareFactoryPlugin(PluginKind.Mutator, 'mut', myMutator)).deep.eq({ - factory: myMutator, - kind: PluginKind.Mutator, - name: 'mut', + expect(declareFactoryPlugin(PluginKind.Reporter, 'rep', createReporter)).deep.eq({ + factory: createReporter, + kind: PluginKind.Reporter, + name: 'rep', }); }); }); diff --git a/packages/api/test/unit/plugin/tokens.spec.ts b/packages/api/test/unit/plugin/tokens.spec.ts index aa13c15a61..253d13725a 100644 --- a/packages/api/test/unit/plugin/tokens.spec.ts +++ b/packages/api/test/unit/plugin/tokens.spec.ts @@ -21,6 +21,5 @@ describe('commonTokens', () => { itShouldProvideToken('logger'); itShouldProvideToken('pluginResolver'); itShouldProvideToken('produceSourceMaps'); - itShouldProvideToken('sandboxFileNames'); itShouldProvideToken('getLogger'); }); diff --git a/packages/api/test/unit/test_runner/runResultHelpers.spec.ts b/packages/api/test/unit/test_runner/runResultHelpers.spec.ts new file mode 100644 index 0000000000..772992ed07 --- /dev/null +++ b/packages/api/test/unit/test_runner/runResultHelpers.spec.ts @@ -0,0 +1,69 @@ +import { expect } from 'chai'; + +import { toMutantRunResult, DryRunStatus, MutantRunResult, MutantRunStatus } from '../../../test_runner'; +import { TestStatus } from '../../../src/test_runner/TestStatus'; + +describe('runResultHelpers', () => { + describe(toMutantRunResult.name, () => { + it('should convert "timeout" to "timeout"', () => { + const expected: MutantRunResult = { status: MutantRunStatus.Timeout }; + expect(toMutantRunResult({ status: DryRunStatus.Timeout })).deep.eq(expected); + }); + + it('should convert "error" to "error"', () => { + const expected: MutantRunResult = { status: MutantRunStatus.Error, errorMessage: 'some error' }; + expect(toMutantRunResult({ status: DryRunStatus.Error, errorMessage: 'some error' })).deep.eq(expected); + }); + + it('should report a failed test as "killed"', () => { + const expected: MutantRunResult = { status: MutantRunStatus.Killed, failureMessage: 'expected foo to be bar', killedBy: '42', nrOfTests: 3 }; + expect( + toMutantRunResult({ + status: DryRunStatus.Complete, + tests: [ + { status: TestStatus.Success, id: 'success1', name: 'success1', timeSpentMs: 42 }, + { status: TestStatus.Failed, id: '42', name: 'error', timeSpentMs: 42, failureMessage: 'expected foo to be bar' }, + { status: TestStatus.Success, id: 'success2', name: 'success2', timeSpentMs: 42 }, + ], + }) + ).deep.eq(expected); + }); + + it('should report only succeeded tests as "survived"', () => { + const expected: MutantRunResult = { status: MutantRunStatus.Survived, nrOfTests: 3 }; + expect( + toMutantRunResult({ + status: DryRunStatus.Complete, + tests: [ + { status: TestStatus.Success, id: 'success1', name: 'success1', timeSpentMs: 42 }, + { status: TestStatus.Success, id: '42', name: 'error', timeSpentMs: 42 }, + { status: TestStatus.Success, id: 'success2', name: 'success2', timeSpentMs: 42 }, + ], + }) + ).deep.eq(expected); + }); + + it('should report an empty suite as "survived"', () => { + const expected: MutantRunResult = { status: MutantRunStatus.Survived, nrOfTests: 0 }; + expect( + toMutantRunResult({ + status: DryRunStatus.Complete, + tests: [], + }) + ).deep.eq(expected); + }); + + it("should set nrOfTests with the amount of tests that weren't `skipped`", () => { + const expected: MutantRunResult = { nrOfTests: 2, failureMessage: '', killedBy: '1', status: MutantRunStatus.Killed }; + const actual = toMutantRunResult({ + status: DryRunStatus.Complete, + tests: [ + { id: '1', name: '', status: TestStatus.Failed, timeSpentMs: 42, failureMessage: '' }, + { id: '1', name: '', status: TestStatus.Skipped, timeSpentMs: 42 }, + { id: '1', name: '', status: TestStatus.Success, timeSpentMs: 42 }, + ], + }); + expect(actual).deep.eq(expected); + }); + }); +}); diff --git a/packages/api/test_framework.ts b/packages/api/test_framework.ts deleted file mode 100644 index 952e5bfa8f..0000000000 --- a/packages/api/test_framework.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { default as TestFramework } from './src/test_framework/TestFramework'; -export { default as TestSelection } from './src/test_framework/TestSelection'; diff --git a/packages/api/test_runner.ts b/packages/api/test_runner.ts index 89476679a9..2ffa029645 100644 --- a/packages/api/test_runner.ts +++ b/packages/api/test_runner.ts @@ -1,7 +1,8 @@ -export * from './src/test_runner/Coverage'; -export { default as TestResult } from './src/test_runner/TestResult'; -export { default as TestRunner } from './src/test_runner/TestRunner'; -export { default as TestStatus } from './src/test_runner/TestStatus'; -export { default as RunResult } from './src/test_runner/RunResult'; -export { default as RunOptions } from './src/test_runner/RunOptions'; -export { default as RunStatus } from './src/test_runner/RunStatus'; +export * from './src/test_runner/TestResult'; +export * from './src/test_runner/TestRunner'; +export * from './src/test_runner/TestStatus'; +export * from './src/test_runner/DryRunResult'; +export * from './src/test_runner/RunOptions'; +export * from './src/test_runner/MutantRunResult'; +export * from './src/test_runner/DryRunStatus'; +export * from './src/test_runner/runResultHelpers'; diff --git a/packages/api/transpile.ts b/packages/api/transpile.ts deleted file mode 100644 index 37524beb9c..0000000000 --- a/packages/api/transpile.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as Transpiler } from './src/transpile/Transpiler'; diff --git a/packages/api/tsconfig.src.json b/packages/api/tsconfig.src.json index b20098295e..2737cb60fe 100644 --- a/packages/api/tsconfig.src.json +++ b/packages/api/tsconfig.src.json @@ -7,6 +7,7 @@ "src", "src-generated", "schema/*.json", + "check.ts", "config.ts", "core.ts", "logging.ts", @@ -14,6 +15,7 @@ "report.ts", "test_framework.ts", "test_runner.ts", + "test_runner.ts", "transpile.ts", "plugin.ts" ], diff --git a/packages/api/tsconfig.stryker.json b/packages/api/tsconfig.stryker.json deleted file mode 100644 index f1fd99264f..0000000000 --- a/packages/api/tsconfig.stryker.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "extends": "./tsconfig.test.json", - "compilerOptions": { - "rootDir": ".", - "types": [ - "node", - "mocha" - ], - }, - "include": [ - "src", - "src-generated", - "schema/*.json", - "test", - "config.ts", - "core.ts", - "logging.ts", - "mutant.ts", - "report.ts", - "test_framework.ts", - "test_runner.ts", - "transpile.ts", - "plugin.ts" - ], -} diff --git a/packages/babel-transpiler/CHANGELOG.md b/packages/babel-transpiler/CHANGELOG.md index 5feb242892..1680ed11fa 100644 --- a/packages/babel-transpiler/CHANGELOG.md +++ b/packages/babel-transpiler/CHANGELOG.md @@ -3,6 +3,97 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [4.0.0-beta.10](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.9...v4.0.0-beta.10) (2020-10-05) + +**Note:** Version bump only for package @stryker-mutator/babel-transpiler + + + + + +# [4.0.0-beta.9](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.8...v4.0.0-beta.9) (2020-09-30) + +**Note:** Version bump only for package @stryker-mutator/babel-transpiler + + + + + +# [4.0.0-beta.8](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.7...v4.0.0-beta.8) (2020-09-22) + +**Note:** Version bump only for package @stryker-mutator/babel-transpiler + + + + + +# [4.0.0-beta.7](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.6...v4.0.0-beta.7) (2020-09-17) + +**Note:** Version bump only for package @stryker-mutator/babel-transpiler + + + + + +# [4.0.0-beta.6](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.5...v4.0.0-beta.6) (2020-09-10) + +**Note:** Version bump only for package @stryker-mutator/babel-transpiler + + + + + +# [4.0.0-beta.5](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.4...v4.0.0-beta.5) (2020-09-09) + +**Note:** Version bump only for package @stryker-mutator/babel-transpiler + + + + + +# [4.0.0-beta.4](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.3...v4.0.0-beta.4) (2020-08-29) + +**Note:** Version bump only for package @stryker-mutator/babel-transpiler + + + + + +# [4.0.0-beta.3](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.2...v4.0.0-beta.3) (2020-08-19) + +**Note:** Version bump only for package @stryker-mutator/babel-transpiler + + + + + +# [4.0.0-beta.2](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.1...v4.0.0-beta.2) (2020-08-07) + +**Note:** Version bump only for package @stryker-mutator/babel-transpiler + + + + + +# [4.0.0-beta.1](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.0...v4.0.0-beta.1) (2020-07-17) + +**Note:** Version bump only for package @stryker-mutator/babel-transpiler + + + + + +# [4.0.0-beta.0](https://github.com/stryker-mutator/stryker/compare/v3.3.1...v4.0.0-beta.0) (2020-07-10) + + +### Features + +* **transpiler:** remove `Transpiler` API ([06f668b](https://github.com/stryker-mutator/stryker/commit/06f668bf8660f78b12916b2236f3fd9bf86bf23b)) + + + + + ## [3.3.1](https://github.com/stryker-mutator/stryker/compare/v3.3.0...v3.3.1) (2020-07-04) **Note:** Version bump only for package @stryker-mutator/babel-transpiler diff --git a/packages/babel-transpiler/package.json b/packages/babel-transpiler/package.json index 3cf280a7e0..293399765d 100644 --- a/packages/babel-transpiler/package.json +++ b/packages/babel-transpiler/package.json @@ -1,13 +1,9 @@ { "name": "@stryker-mutator/babel-transpiler", - "version": "3.3.1", + "version": "4.0.0-beta.10", "description": "A plugin for babel projects using Stryker", "main": "src/index.js", - "scripts": { - "test": "nyc --exclude-after-remap=false --check-coverage --reporter=html --report-dir=reports/coverage --lines 90 --functions 80 --branches 80 npm run mocha", - "mocha": "mocha \"test/helpers/**/*.js\" \"test/unit/**/*.js\" && mocha --timeout 100000 \"test/helpers/**/*.js\" \"test/integration/**/*.js\"", - "stryker": "node ../core/bin/stryker run" - }, + "scripts": {}, "nyc": { "exclude": [ "test", @@ -23,7 +19,6 @@ }, "keywords": [ "stryker", - "@stryker-mutator/transpiler-plugin", "javascript", "babel" ], @@ -41,39 +36,5 @@ "Thomas Peters " ], "homepage": "https://github.com/stryker-mutator/stryker/tree/master/packages/babel-transpiler#readme", - "license": "Apache-2.0", - "dependencies": { - "@stryker-mutator/api": "^3.3.1", - "@stryker-mutator/util": "^3.3.1", - "minimatch": "~3.0.4" - }, - "peerDependencies": { - "@babel/core": "^7", - "@stryker-mutator/core": "^3.0.0" - }, - "devDependencies": { - "@babel/cli": "~7.8.3", - "@babel/core": "~7.9.0", - "@babel/plugin-transform-typescript": "^7.8.3", - "@babel/preset-env": "~7.9.5", - "@babel/preset-flow": "^7.8.3", - "@babel/preset-stage-2": "^7.8.3", - "@babel/preset-typescript": "^7.8.3", - "@stryker-mutator/test-helpers": "^3.3.1", - "@types/babel__core": "~7.1.0", - "@types/babel__generator": "~7.6.0", - "@types/babel__template": "~7.0.1", - "@types/babel__traverse": "~7.0.5", - "@types/glob": "~7.1.0", - "@types/minimatch": "~3.0.3", - "@types/node": "^14.0.1", - "babel-plugin-transform-es2015-spread": "~6.22.0", - "glob": "~7.1.2" - }, - "initStrykerConfig": { - "babel": { - "optionsFile": ".babelrc" - }, - "coverageAnalysis": "off" - } + "license": "Apache-2.0" } diff --git a/packages/babel-transpiler/schema/babel-transpiler-options.json b/packages/babel-transpiler/schema/babel-transpiler-options.json deleted file mode 100644 index 8c108c018e..0000000000 --- a/packages/babel-transpiler/schema/babel-transpiler-options.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "type": "object", - "title": "BabelTranspilerOptions", - "additionalProperties": false, - "properties": { - "babel": { - "description": "Configuration for @stryker-mutator/babel-transpiler", - "title": "StrykerBabelConfig", - "default": {}, - "type": "object", - "additionalProperties": false, - "properties": { - "extensions": { - "description": "Load additional extensions here. By default only these extensions get picked up by babel: `\".js\", \".jsx\", \".es6\", \".es\", \".mjs\"`.\nFor example: if you want to enable typescript transpilation, set extensions to `[\"ts\", \"tsx\"]`.", - "type": "array", - "default": [], - "items": { - "type": "string" - } - }, - "optionsFile": { - "description": "The location of your babelrc file. Set this value to `null` to disable loading of a babel config file.", - "default": ".babelrc", - "type": [ - "string", - "null" - ] - }, - "options": { - "description": "Override babel options from your config file here. Please see [babel's documentation](https://babeljs.io/docs/en/options) to see what is available.\n\nSome options are restricted to be set, because the @stryker-mutator/babel-transpiler takes control of it. These options are: `filename`, `filenameRelative` and `cwd`.", - "$ref": "http://json.schemastore.org/babelrc", - "type": "object" - } - } - } - } -} diff --git a/packages/babel-transpiler/src/BabelConfigReader.ts b/packages/babel-transpiler/src/BabelConfigReader.ts deleted file mode 100644 index d3f4c424d7..0000000000 --- a/packages/babel-transpiler/src/BabelConfigReader.ts +++ /dev/null @@ -1,76 +0,0 @@ -import * as fs from 'fs'; -import * as path from 'path'; - -import { Logger } from '@stryker-mutator/api/logging'; -import { commonTokens, tokens } from '@stryker-mutator/api/plugin'; - -import { StrykerBabelConfig } from '../src-generated/babel-transpiler-options'; - -import * as babel from './helpers/babelWrapper'; -import { BabelTranspilerWithStrykerOptions } from './BabelTranspilerWithStrykerOptions'; -import { ConfigAPI } from './helpers/babelWrapper'; - -export class BabelConfigReader { - public static inject = tokens(commonTokens.logger); - constructor(private readonly log: Logger) {} - - public readConfig(strykerOptions: BabelTranspilerWithStrykerOptions): StrykerBabelConfig { - const babelConfig = { ...strykerOptions.babel }; - babelConfig.options = { - ...this.readBabelOptionsFromFile(babelConfig.optionsFile), - ...babelConfig.options, - }; - this.log.debug(`Babel config is: ${JSON.stringify(babelConfig, null, 2)}`); - return babelConfig; - } - - private readBabelOptionsFromFile(relativeFileName: string | null): babel.TransformOptions { - if (relativeFileName) { - const babelrcPath = path.resolve(relativeFileName); - this.log.debug(`Reading .babelrc file from path "${babelrcPath}"`); - if (fs.existsSync(babelrcPath)) { - try { - if (path.basename(babelrcPath) === '.babelrc.js') { - return require(babelrcPath) as babel.TransformOptions; - } - if (path.basename(babelrcPath) === 'babel.config.js') { - const config = require(babelrcPath); - if (typeof config === 'function') { - const configFunction = config as babel.ConfigFunction; - return configFunction(noopBabelConfigApi); - } else { - return config as babel.TransformOptions; - } - } - return JSON.parse(fs.readFileSync(babelrcPath, 'utf8')) as babel.TransformOptions; - } catch (error) { - this.log.error(`Error while reading "${babelrcPath}" file: ${error}`); - } - } else { - this.log.error(`babelrc file does not exist at: ${babelrcPath}`); - } - } - return {}; - } -} - -function noop() {} - -const noopBabelConfigApi: ConfigAPI = { - assertVersion() { - return true; - }, - cache: { - forever: noop, - invalidate() { - return noop as any; - }, - never: noop, - using() { - return noop as any; - }, - }, - env: noop as any, - caller: noop as any, - version: noop as any, -}; diff --git a/packages/babel-transpiler/src/BabelTranspiler.ts b/packages/babel-transpiler/src/BabelTranspiler.ts deleted file mode 100644 index d18893679c..0000000000 --- a/packages/babel-transpiler/src/BabelTranspiler.ts +++ /dev/null @@ -1,81 +0,0 @@ -import * as path from 'path'; - -import { File, StrykerOptions } from '@stryker-mutator/api/core'; -import { commonTokens, Injector, tokens, TranspilerPluginContext } from '@stryker-mutator/api/plugin'; -import { Transpiler } from '@stryker-mutator/api/transpile'; -import { StrykerError } from '@stryker-mutator/util'; - -import { StrykerBabelConfig } from '../src-generated/babel-transpiler-options'; - -import { BabelConfigReader } from './BabelConfigReader'; -import * as babel from './helpers/babelWrapper'; -import { toJSFileName } from './helpers/helpers'; -import { BabelTranspilerWithStrykerOptions } from './BabelTranspilerWithStrykerOptions'; - -const DEFAULT_EXTENSIONS: readonly string[] = babel.DEFAULT_EXTENSIONS; - -export function babelTranspilerFactory(injector: Injector) { - return injector.provideClass('babelConfigReader', BabelConfigReader).injectClass(BabelTranspiler); -} -babelTranspilerFactory.inject = tokens(commonTokens.injector); - -export class BabelTranspiler implements Transpiler { - private readonly babelConfig: StrykerBabelConfig; - private readonly projectRoot: string; - private readonly extensions: readonly string[]; - - public static inject = tokens(commonTokens.options, commonTokens.produceSourceMaps, 'babelConfigReader'); - constructor(options: StrykerOptions, produceSourceMaps: boolean, babelConfigReader: BabelConfigReader) { - if (produceSourceMaps) { - throw new Error( - `Invalid \`coverageAnalysis\` "${options.coverageAnalysis}" is not supported by the stryker-babel-transpiler. Not able to produce source maps yet. Please set it to "off".` - ); - } - this.babelConfig = babelConfigReader.readConfig(options as BabelTranspilerWithStrykerOptions); - this.projectRoot = this.determineProjectRoot(); - this.extensions = [...DEFAULT_EXTENSIONS, ...this.babelConfig.extensions]; - } - - public async transpile(files: readonly File[]): Promise { - return files.map((file) => this.transpileFileIfNeeded(file)); - } - - private transpileFileIfNeeded(file: File): File { - if (this.extensions.some((ext) => ext === path.extname(file.name))) { - try { - return this.transpileFile(file); - } catch (error) { - throw new StrykerError(`Error while transpiling "${file.name}"`, error); - } - } else { - return file; // pass through - } - } - - private transpileFile(file: File) { - const relativeOptions: babel.TransformOptions = { - cwd: this.projectRoot, - filename: file.name, - filenameRelative: path.relative(this.projectRoot, file.name), - }; - const options: babel.TransformOptions = { ...this.babelConfig.options, ...relativeOptions }; - const result: babel.BabelFileResult | null = babel.transformSync(file.textContent, options); - if (!result) { - // File is ignored by babel - return file; - } else if (result.code === undefined || result.code === null) { - throw new Error(`Could not transpile file "${file.name}". Babel transform function delivered \`undefined\`.`); - } else { - return new File(toJSFileName(file.name), result.code); - } - } - - private determineProjectRoot(): string { - const configFile = this.babelConfig.optionsFile; - if (configFile) { - return path.dirname(configFile); - } else { - return process.cwd(); - } - } -} diff --git a/packages/babel-transpiler/src/BabelTranspilerWithStrykerOptions.ts b/packages/babel-transpiler/src/BabelTranspilerWithStrykerOptions.ts deleted file mode 100644 index fe4b9aba1a..0000000000 --- a/packages/babel-transpiler/src/BabelTranspilerWithStrykerOptions.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { StrykerOptions } from '@stryker-mutator/api/core'; - -import { BabelTranspilerOptions } from '../src-generated/babel-transpiler-options'; - -export interface BabelTranspilerWithStrykerOptions extends BabelTranspilerOptions, StrykerOptions {} diff --git a/packages/babel-transpiler/src/helpers/babelWrapper.ts b/packages/babel-transpiler/src/helpers/babelWrapper.ts deleted file mode 100644 index a673c41ec8..0000000000 --- a/packages/babel-transpiler/src/helpers/babelWrapper.ts +++ /dev/null @@ -1,10 +0,0 @@ -/** - * This wrapper is needed because babel/core only exports - * non-stubbable es6 properties. See node_modules/@babel/core/lib/index.js - */ -import * as babel from '@babel/core'; - -export type { BabelFileResult, TransformOptions, ConfigFunction, ConfigAPI } from '@babel/core'; - -export const transformSync = babel.transformSync; -export const DEFAULT_EXTENSIONS = babel.DEFAULT_EXTENSIONS; diff --git a/packages/babel-transpiler/src/helpers/helpers.ts b/packages/babel-transpiler/src/helpers/helpers.ts deleted file mode 100644 index 26cec3ec0a..0000000000 --- a/packages/babel-transpiler/src/helpers/helpers.ts +++ /dev/null @@ -1,7 +0,0 @@ -import * as path from 'path'; - -export function toJSFileName(fileName: string) { - const fileNameInfo = path.parse(fileName); - const newFileName = path.join(fileNameInfo.dir, fileNameInfo.name + '.js'); - return newFileName; -} diff --git a/packages/babel-transpiler/src/index.ts b/packages/babel-transpiler/src/index.ts index 4ae9c5f1cb..33d7361fd6 100644 --- a/packages/babel-transpiler/src/index.ts +++ b/packages/babel-transpiler/src/index.ts @@ -1,8 +1,3 @@ -import { declareFactoryPlugin, PluginKind } from '@stryker-mutator/api/plugin'; - -import * as strykerValidationSchema from '../schema/babel-transpiler-options.json'; - -import { babelTranspilerFactory } from './BabelTranspiler'; - -export const strykerPlugins = [declareFactoryPlugin(PluginKind.Transpiler, 'babel', babelTranspilerFactory)]; -export { strykerValidationSchema }; +console.warn( + 'Transpiler plugins are no longer supported since Stryker 4.0. Please use `"buildCommand": "babel"` instead. You can remove "@stryker-mutator/babel-transpiler" from your devDependencies.' +); diff --git a/packages/babel-transpiler/test/helpers/factories.ts b/packages/babel-transpiler/test/helpers/factories.ts deleted file mode 100644 index 79321441a8..0000000000 --- a/packages/babel-transpiler/test/helpers/factories.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { StrykerBabelConfig } from '../../src-generated/babel-transpiler-options'; - -export function createStrykerBabelConfig(overrides?: Partial): StrykerBabelConfig { - return { - extensions: ['.js', '.jsx', '.es6', '.es', '.mjs'], - optionsFile: '.babelrc', - options: {}, - ...overrides, - }; -} diff --git a/packages/babel-transpiler/test/helpers/initSinon.ts b/packages/babel-transpiler/test/helpers/initSinon.ts deleted file mode 100644 index 73a77d9d18..0000000000 --- a/packages/babel-transpiler/test/helpers/initSinon.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { testInjector } from '@stryker-mutator/test-helpers'; -import * as chai from 'chai'; -import * as chaiAsPromised from 'chai-as-promised'; -import * as sinon from 'sinon'; -import * as sinonChai from 'sinon-chai'; - -chai.use(chaiAsPromised); -chai.use(sinonChai); -afterEach(() => { - testInjector.reset(); - sinon.restore(); -}); diff --git a/packages/babel-transpiler/test/helpers/initSourceMapSupport.ts b/packages/babel-transpiler/test/helpers/initSourceMapSupport.ts deleted file mode 100644 index fcfbfda16c..0000000000 --- a/packages/babel-transpiler/test/helpers/initSourceMapSupport.ts +++ /dev/null @@ -1 +0,0 @@ -import 'source-map-support/register'; diff --git a/packages/babel-transpiler/test/helpers/mock.ts b/packages/babel-transpiler/test/helpers/mock.ts deleted file mode 100644 index ca22fd7eb1..0000000000 --- a/packages/babel-transpiler/test/helpers/mock.ts +++ /dev/null @@ -1,10 +0,0 @@ -import * as sinon from 'sinon'; - -export type Mock = { - [P in keyof T]: sinon.SinonStub; -}; - -export function mock(constructorFn: new (...args: any[]) => T | any): Mock; -export function mock(constructorFn: new (...args: any[]) => T): Mock { - return sinon.createStubInstance(constructorFn) as Mock; -} diff --git a/packages/babel-transpiler/test/helpers/projectLoader.ts b/packages/babel-transpiler/test/helpers/projectLoader.ts deleted file mode 100644 index 10b72d2075..0000000000 --- a/packages/babel-transpiler/test/helpers/projectLoader.ts +++ /dev/null @@ -1,50 +0,0 @@ -import * as fs from 'fs'; -import * as path from 'path'; - -import { File } from '@stryker-mutator/api/core'; -import * as glob from 'glob'; - -const CARRIAGE_RETURN = '\r'.charCodeAt(0); - -function readFile(fileName: string) { - return new Promise((res, rej) => { - fs.readFile(fileName, (err, result) => { - if (err) { - rej(err); - } else { - res(result); - } - }); - }); -} - -export class ProjectLoader { - public static getFiles(basePath: string) { - return this.load(basePath).then((files) => files.sort((a, b) => a.name.localeCompare(b.name))); - } - - private static load(basePath: string): Promise { - return this.glob(basePath) - .then((fileNames) => fileNames.map((fileName) => path.join(basePath, fileName))) - .then((fileNames) => - Promise.all(fileNames.map((fileName) => readFile(fileName).then((content) => new File(fileName, this.normalize(content))))) - ); - } - - private static normalize(content: Buffer) { - // Remove carriage returns from the content buffer - return Buffer.from(content.filter((byte) => byte !== CARRIAGE_RETURN) as any); - } - - private static glob(basePath: string): Promise { - return new Promise((res, rej) => - glob('**/*.*', { cwd: basePath }, (err, matches) => { - if (err) { - rej(err); - } else { - res(matches); - } - }) - ); - } -} diff --git a/packages/babel-transpiler/test/integration/BabelProjects.it.spec.ts b/packages/babel-transpiler/test/integration/BabelProjects.it.spec.ts deleted file mode 100644 index 9e8ca36ad7..0000000000 --- a/packages/babel-transpiler/test/integration/BabelProjects.it.spec.ts +++ /dev/null @@ -1,86 +0,0 @@ -import * as path from 'path'; - -import { File } from '@stryker-mutator/api/core'; -import { commonTokens } from '@stryker-mutator/api/plugin'; -import { testInjector } from '@stryker-mutator/test-helpers'; -import { expect } from 'chai'; - -import { BabelTranspiler, babelTranspilerFactory } from '../../src/BabelTranspiler'; -import { ProjectLoader } from '../helpers/projectLoader'; -import { StrykerBabelConfig } from '../../src-generated/babel-transpiler-options'; -import { BabelTranspilerWithStrykerOptions } from '../../src/BabelTranspilerWithStrykerOptions'; -import { createStrykerBabelConfig } from '../helpers/factories'; - -function describeIntegrationTest(projectName: string, babelConfig: Partial = {}) { - const projectDir = path.resolve(__dirname, '..', '..', 'testResources', projectName); - babelConfig.optionsFile = path.join(projectDir, babelConfig.optionsFile || '.babelrc'); - let projectFiles: File[] = []; - let resultFiles: File[] = []; - let babelTranspiler: BabelTranspiler; - - beforeEach(async () => { - projectFiles = await ProjectLoader.getFiles(path.join(projectDir, 'source')); - resultFiles = await ProjectLoader.getFiles(path.join(projectDir, 'expectedResult')); - ((testInjector.options as unknown) as BabelTranspilerWithStrykerOptions).babel = createStrykerBabelConfig(babelConfig); - babelTranspiler = testInjector.injector.provideValue(commonTokens.produceSourceMaps, false).injectFunction(babelTranspilerFactory); - }); - - it('should be able to transpile the input files', async () => { - const actualResultFiles = await babelTranspiler.transpile(projectFiles); - const expectedResultFiles = resultFiles.map((file) => new File(file.name.replace('expectedResult', 'source'), file.content)); - expectFilesEqual(actualResultFiles, expectedResultFiles); - }); - - it('should have project files', () => { - expect(projectFiles).not.to.be.empty; - }); - - function expectFilesEqual(actual: readonly File[], expected: readonly File[]) { - expect(actual).lengthOf(expected.length); - expected.forEach((expectedFile, index) => { - expect(actual[index].name).deep.eq(expectedFile.name); - expect(actual[index].textContent, expectedFile.name).deep.eq(expectedFile.textContent); - expect(actual[index].content, expectedFile.name).deep.eq(expectedFile.content); - }); - } -} - -describe('A babel project with the `only` option enabled', () => { - describeIntegrationTest('babelOnlyOption'); -}); -describe('A babel project with a plugin', () => { - describeIntegrationTest('babelPluginProject'); -}); -describe('A Babel project with typescript preset', () => { - describeIntegrationTest('babelTypescriptProject', { extensions: ['.ts'] }); -}); -describe('A Babel project with flow preset', () => { - describeIntegrationTest('babelFlowProject'); -}); -describe('A Babel project', () => { - describeIntegrationTest('babelProject'); -}); -describe('Project with binary files', () => { - describeIntegrationTest('babelProjectWithBinaryFiles'); -}); -describe('Different extensions', () => { - describeIntegrationTest('differentExtensions'); -}); -describe('A Babel project with babel.config.js config file that exports function', () => { - describeIntegrationTest('babelProjectWithBabelConfigJs', { - extensions: ['.ts'], - optionsFile: 'babel.config.js', - }); -}); -describe('A Babel project with babel.config.js config file that exports object', () => { - describeIntegrationTest('babelProjectWithBabelConfigJsObject', { - extensions: ['.ts'], - optionsFile: 'babel.config.js', - }); -}); -describe('A Babel project with .babelrc.js config file', () => { - describeIntegrationTest('babelProjectWithBabelRcJs', { - extensions: ['.ts'], - optionsFile: '.babelrc.js', - }); -}); diff --git a/packages/babel-transpiler/test/unit/BabelConfigReader.spec.ts b/packages/babel-transpiler/test/unit/BabelConfigReader.spec.ts deleted file mode 100644 index 11946e413c..0000000000 --- a/packages/babel-transpiler/test/unit/BabelConfigReader.spec.ts +++ /dev/null @@ -1,90 +0,0 @@ -import * as fs from 'fs'; -import * as path from 'path'; - -import { factory, testInjector } from '@stryker-mutator/test-helpers'; -import { expect } from 'chai'; -import * as sinon from 'sinon'; - -import { BabelConfigReader } from '../../src/BabelConfigReader'; -import { BabelTranspilerOptions, StrykerBabelConfig } from '../../src-generated/babel-transpiler-options'; -import { createStrykerBabelConfig } from '../helpers/factories'; - -describe(BabelConfigReader.name, () => { - let sut: BabelConfigReader; - - beforeEach(() => { - sut = testInjector.injector.injectClass(BabelConfigReader); - }); - - it('should read babel configuration from StrykerOptions', () => { - const babelConfig: StrykerBabelConfig = { - extensions: ['.ts'], - options: { - presets: ['env'], - }, - optionsFile: null, - }; - const options = factory.strykerWithPluginOptions({ babel: babelConfig }); - const result = sut.readConfig(options); - expect(result).deep.eq(babelConfig); - }); - - it('should read the .babelrc file from disk by default', () => { - // Arrange - const babelOptions = { presets: ['env'] }; - arrangeBabelOptionsFile(babelOptions, '.babelrc'); - const result = sut.readConfig(factory.strykerWithPluginOptions({ babel: createStrykerBabelConfig() })); - expect(result.options).deep.eq(babelOptions); - expect(result.optionsFile).deep.eq('.babelrc'); - }); - - it('should log the path to the babelrc file', () => { - arrangeBabelOptionsFile({}); - sut.readConfig(factory.strykerWithPluginOptions({ babel: createStrykerBabelConfig() })); - expect(testInjector.logger.debug).calledWith(`Reading .babelrc file from path "${path.resolve('.babelrc')}"`); - }); - - it('should log the babel config', () => { - const expectedConfig: StrykerBabelConfig = { - extensions: ['.ts'], - options: { presets: ['env'] }, - optionsFile: null, - }; - sut.readConfig(factory.strykerWithPluginOptions({ babel: expectedConfig })); - expect(testInjector.logger.debug).calledWith(`Babel config is: ${JSON.stringify(expectedConfig, null, 2)}`); - }); - - it('should log a warning if the babelrc file does not exist', () => { - const babelConfig = { - optionsFile: '.nonExistingBabelrc', - }; - sut.readConfig(factory.strykerWithPluginOptions({ babel: createStrykerBabelConfig(babelConfig) })); - expect(testInjector.logger.error).calledWith(`babelrc file does not exist at: ${path.resolve(babelConfig.optionsFile)}`); - }); - - it('should log a warning if the babelrc file cannot be read', () => { - sinon.stub(fs, 'existsSync').returns(true); - sinon.stub(fs, 'readFileSync').withArgs(path.resolve('.babelrc'), 'utf8').returns('something, not json'); - sut.readConfig( - factory.strykerWithPluginOptions({ babel: createStrykerBabelConfig() }) - ); - expect(testInjector.logger.error).calledWith( - `Error while reading "${path.resolve('.babelrc')}" file: SyntaxError: Unexpected token s in JSON at position 0` - ); - }); - - it("should set the babelConfig to an empty object if nothing is configured and .babelrc file didn't exits", () => { - const expected: StrykerBabelConfig = { - extensions: [], - options: {}, - optionsFile: '.babelrc', - }; - const result = sut.readConfig(factory.strykerWithPluginOptions({ babel: expected })); - expect(result).deep.equal(expected); - }); - - function arrangeBabelOptionsFile(babelOptions: babel.TransformOptions, fileName = '.babelrc') { - sinon.stub(fs, 'existsSync').returns(true); - sinon.stub(fs, 'readFileSync').withArgs(path.resolve(fileName), 'utf8').returns(JSON.stringify(babelOptions)); - } -}); diff --git a/packages/babel-transpiler/test/unit/BabelTranspiler.spec.ts b/packages/babel-transpiler/test/unit/BabelTranspiler.spec.ts deleted file mode 100644 index bac953c67e..0000000000 --- a/packages/babel-transpiler/test/unit/BabelTranspiler.spec.ts +++ /dev/null @@ -1,166 +0,0 @@ -import * as path from 'path'; - -import { File, StrykerOptions } from '@stryker-mutator/api/core'; -import { commonTokens } from '@stryker-mutator/api/plugin'; -import { factory, testInjector } from '@stryker-mutator/test-helpers'; -import { expect } from 'chai'; -import * as sinon from 'sinon'; - -import { BabelConfigReader } from '../../src/BabelConfigReader'; -import { BabelTranspiler } from '../../src/BabelTranspiler'; -import * as babel from '../../src/helpers/babelWrapper'; -import { Mock, mock } from '../helpers/mock'; -import { StrykerBabelConfig } from '../../src-generated/babel-transpiler-options'; - -describe(BabelTranspiler.name, () => { - let sut: BabelTranspiler; - let files: File[]; - let transformStub: sinon.SinonStub; - let options: StrykerOptions; - let babelConfigReaderMock: Mock; - let babelConfig: StrykerBabelConfig; - - beforeEach(() => { - babelConfig = { - extensions: [], - options: {}, - optionsFile: null, - }; - babelConfigReaderMock = mock(BabelConfigReader); - transformStub = sinon.stub(); - sinon.stub(babel, 'transformSync').value(transformStub); - options = factory.strykerOptions(); - files = [ - new File(path.resolve('main.js'), 'const main = () => { sum(2); divide(2); }'), - new File(path.resolve('sum.js'), 'const sum = (number) => number + number;'), - new File(path.resolve('divide.js'), 'const divide = (number) => number / number;'), - ]; - babelConfigReaderMock.readConfig.returns(babelConfig); - }); - - function createSut(produceSourceMaps = false) { - return testInjector.injector - .provideValue(commonTokens.produceSourceMaps, produceSourceMaps) - .provideValue('babelConfigReader', (babelConfigReaderMock as unknown) as BabelConfigReader) - .injectClass(BabelTranspiler); - } - - describe('constructor', () => { - function arrangeHappyFlow() { - babelConfigReaderMock.readConfig.returns(babelConfig); - sut = createSut(); - } - - it('should read babel config using the BabelConfigReader', () => { - arrangeHappyFlow(); - expect(babelConfigReaderMock.readConfig).calledWith(options); - }); - - it('should throw if `produceSourceMaps` was true and coverage analysis is "perTest"', () => { - options.coverageAnalysis = 'perTest'; - expect(() => new BabelTranspiler(options, /*produceSourceMaps:*/ true, (babelConfigReaderMock as unknown) as BabelConfigReader)).throws( - 'Invalid `coverageAnalysis` "perTest" is not supported by the stryker-babel-transpiler. Not able to produce source maps yet. Please set it to "off".' - ); - }); - }); - - describe('transpile', () => { - function arrangeHappyFlow(transformResult: babel.BabelFileResult | null = { code: 'code' }) { - sut = new BabelTranspiler(options, /*produceSourceMaps:*/ false, (babelConfigReaderMock as unknown) as BabelConfigReader); - transformStub.returns(transformResult); - } - - it('should call the babel transform function for js files', async () => { - arrangeHappyFlow(); - const actualResultFiles = await sut.transpile(files); - expect(transformStub).calledThrice; - files.forEach((file) => { - expect(transformStub).calledWith(file.textContent, { - cwd: process.cwd(), - filename: file.name, - filenameRelative: path.relative(process.cwd(), file.name), - }); - }); - expect(actualResultFiles).deep.eq(files.map((file) => new File(file.name, 'code'))); - }); - - it('should allow users to define babel options', async () => { - const plugins = ['fooPlugin', 'barPlugin']; - babelConfig.options!.plugins = plugins.slice(); - arrangeHappyFlow(); - await sut.transpile(files); - files.forEach((file) => { - expect(transformStub).calledWith(file.textContent, { - cwd: process.cwd(), - filename: file.name, - filenameRelative: path.relative(process.cwd(), file.name), - plugins, - }); - }); - }); - - it('should not allow a user to override the file name', async () => { - babelConfig.options!.filename = 'override'; - babelConfig.options!.filenameRelative = 'override'; - arrangeHappyFlow(); - sut = new BabelTranspiler(options, /*produceSourceMaps:*/ false, (babelConfigReaderMock as unknown) as BabelConfigReader); - await sut.transpile([files[0]]); - expect(transformStub).calledWith(files[0].textContent, { - cwd: process.cwd(), - filename: files[0].name, - filenameRelative: path.relative(process.cwd(), files[0].name), - }); - }); - - it('should not transpile binary files', async () => { - arrangeHappyFlow(); - // eslint-disable-next-line - const inputFile = new File('myBinaryFile.png', 'S�L!##���XLDDDDDDDD\K�'); - const actualResultFiles = await sut.transpile([inputFile]); - expect(actualResultFiles[0]).eq(inputFile); - expect(transformStub).not.called; - }); - - it('should not transpile ignored files', async () => { - arrangeHappyFlow(null); - const inputFiles = [new File('file.es6', 'pass through')]; - const actualResultFiles = await sut.transpile(inputFiles); - expect(actualResultFiles).deep.eq(inputFiles); - }); - - it('should report an error if transpiled code was undefined', async () => { - arrangeHappyFlow({ code: undefined }); - return expect(sut.transpile([new File('f.js', '')])).rejectedWith( - 'Could not transpile file "f.js". Babel transform function delivered `undefined`.' - ); - }); - - it('should only call the transform function when the file extension is a known file extension', async () => { - arrangeHappyFlow(); - const inputFiles: File[] = [ - new File('es6.es6', 'es6 = true'), - new File('js.js', 'js = true'), - new File('es.es', 'es = true'), - new File('jsx.jsx', 'jsx = true'), - new File('ignored.njs', 'ignored'), - ]; - const actualResultFiles = await sut.transpile(inputFiles); - expect(transformStub).callCount(inputFiles.length - 1); - expect(transformStub).calledWith('es6 = true'); - expect(transformStub).calledWith('js = true'); - expect(transformStub).calledWith('es = true'); - expect(transformStub).calledWith('jsx = true'); - expect(actualResultFiles.map((file) => file.name)).deep.eq(['es6.js', 'js.js', 'es.js', 'jsx.js', 'ignored.njs']); - }); - - it('should return with an error when the babel transform fails', async () => { - const error = new Error('Syntax error'); - transformStub.throws(error); - sut = createSut(); - // eslint-disable-next-line - return expect(sut.transpile([new File('picture.js', 'S�L!##���XLDDDDDDDD\K�')])).rejectedWith( - 'Error while transpiling "picture.js". Inner error: Error: Syntax error' - ); - }); - }); -}); diff --git a/packages/babel-transpiler/testResources/babelFlowProject/.babelrc b/packages/babel-transpiler/testResources/babelFlowProject/.babelrc deleted file mode 100644 index 1e7d47e649..0000000000 --- a/packages/babel-transpiler/testResources/babelFlowProject/.babelrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "presets": [ - "@babel/preset-flow" - ] -} \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelFlowProject/expectedResult/bar.js b/packages/babel-transpiler/testResources/babelFlowProject/expectedResult/bar.js deleted file mode 100644 index c4ad81e932..0000000000 --- a/packages/babel-transpiler/testResources/babelFlowProject/expectedResult/bar.js +++ /dev/null @@ -1 +0,0 @@ -const x = 0; \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelFlowProject/expectedResult/foo.js b/packages/babel-transpiler/testResources/babelFlowProject/expectedResult/foo.js deleted file mode 100644 index d4ded9454a..0000000000 --- a/packages/babel-transpiler/testResources/babelFlowProject/expectedResult/foo.js +++ /dev/null @@ -1 +0,0 @@ -function foo(one, two, three) {} \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelFlowProject/source/bar.js b/packages/babel-transpiler/testResources/babelFlowProject/source/bar.js deleted file mode 100644 index cacb9b4964..0000000000 --- a/packages/babel-transpiler/testResources/babelFlowProject/source/bar.js +++ /dev/null @@ -1 +0,0 @@ -const x: number = 0; \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelFlowProject/source/foo.js b/packages/babel-transpiler/testResources/babelFlowProject/source/foo.js deleted file mode 100644 index 5a01c6ede4..0000000000 --- a/packages/babel-transpiler/testResources/babelFlowProject/source/foo.js +++ /dev/null @@ -1 +0,0 @@ -function foo(one: any, two: number, three?): string {} \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelOnlyOption/.babelrc b/packages/babel-transpiler/testResources/babelOnlyOption/.babelrc deleted file mode 100644 index 442c4334f8..0000000000 --- a/packages/babel-transpiler/testResources/babelOnlyOption/.babelrc +++ /dev/null @@ -1,6 +0,0 @@ -{ - "presets": ["@babel/env"] , - "only": [ - "source/only/*.js" - ] -} diff --git a/packages/babel-transpiler/testResources/babelOnlyOption/expectedResult/ignored/lib.js b/packages/babel-transpiler/testResources/babelOnlyOption/expectedResult/ignored/lib.js deleted file mode 100644 index 0df8ff5dea..0000000000 --- a/packages/babel-transpiler/testResources/babelOnlyOption/expectedResult/ignored/lib.js +++ /dev/null @@ -1,3 +0,0 @@ -console.log('long file, we don\'t want to transpile'); - -also there are errors in here, babel won't like that \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelOnlyOption/expectedResult/only/only.js b/packages/babel-transpiler/testResources/babelOnlyOption/expectedResult/only/only.js deleted file mode 100644 index e1885122a7..0000000000 --- a/packages/babel-transpiler/testResources/babelOnlyOption/expectedResult/only/only.js +++ /dev/null @@ -1,5 +0,0 @@ -"use strict"; - -var divide = function divide(num, dividend) { - return num / dividend; -}; \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelOnlyOption/source/ignored/lib.js b/packages/babel-transpiler/testResources/babelOnlyOption/source/ignored/lib.js deleted file mode 100644 index 0df8ff5dea..0000000000 --- a/packages/babel-transpiler/testResources/babelOnlyOption/source/ignored/lib.js +++ /dev/null @@ -1,3 +0,0 @@ -console.log('long file, we don\'t want to transpile'); - -also there are errors in here, babel won't like that \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelOnlyOption/source/only/only.js b/packages/babel-transpiler/testResources/babelOnlyOption/source/only/only.js deleted file mode 100644 index f04e5419d7..0000000000 --- a/packages/babel-transpiler/testResources/babelOnlyOption/source/only/only.js +++ /dev/null @@ -1,2 +0,0 @@ - -const divide = (num, dividend) => num / dividend; \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelPluginProject/.babelrc b/packages/babel-transpiler/testResources/babelPluginProject/.babelrc deleted file mode 100644 index 1cc9d552aa..0000000000 --- a/packages/babel-transpiler/testResources/babelPluginProject/.babelrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "plugins": [ - "transform-es2015-spread" - ] -} \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelPluginProject/expectedResult/main.js b/packages/babel-transpiler/testResources/babelPluginProject/expectedResult/main.js deleted file mode 100644 index c6bb4ab9f2..0000000000 --- a/packages/babel-transpiler/testResources/babelPluginProject/expectedResult/main.js +++ /dev/null @@ -1,2 +0,0 @@ -var a = ['a', 'b', 'c']; -var b = [].concat(a, ['foo']); \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelPluginProject/source/main.js b/packages/babel-transpiler/testResources/babelPluginProject/source/main.js deleted file mode 100644 index a41a99a632..0000000000 --- a/packages/babel-transpiler/testResources/babelPluginProject/source/main.js +++ /dev/null @@ -1,2 +0,0 @@ -var a = ['a', 'b', 'c']; -var b = [...a, 'foo']; \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelProject/.babelrc b/packages/babel-transpiler/testResources/babelProject/.babelrc deleted file mode 100644 index 544b7b4ddd..0000000000 --- a/packages/babel-transpiler/testResources/babelProject/.babelrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - -} \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelProject/expectedResult/lib/divide.js b/packages/babel-transpiler/testResources/babelProject/expectedResult/lib/divide.js deleted file mode 100644 index ece859f045..0000000000 --- a/packages/babel-transpiler/testResources/babelProject/expectedResult/lib/divide.js +++ /dev/null @@ -1,3 +0,0 @@ -export const divide = number => { - return number / number; -}; \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelProject/expectedResult/lib/sum.js b/packages/babel-transpiler/testResources/babelProject/expectedResult/lib/sum.js deleted file mode 100644 index dd485cc115..0000000000 --- a/packages/babel-transpiler/testResources/babelProject/expectedResult/lib/sum.js +++ /dev/null @@ -1,3 +0,0 @@ -export const sum = number => { - return number + number; -}; \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelProject/expectedResult/main.js b/packages/babel-transpiler/testResources/babelProject/expectedResult/main.js deleted file mode 100644 index b45213c4ca..0000000000 --- a/packages/babel-transpiler/testResources/babelProject/expectedResult/main.js +++ /dev/null @@ -1,4 +0,0 @@ -import sum from './lib/sum'; -import divide from './lib/divide'; -console.log([1, 2, 3, 4].map(divide)); -console.log([1, 2, 3, 4].map(sum)); \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelProject/source/lib/divide.js b/packages/babel-transpiler/testResources/babelProject/source/lib/divide.js deleted file mode 100644 index ece859f045..0000000000 --- a/packages/babel-transpiler/testResources/babelProject/source/lib/divide.js +++ /dev/null @@ -1,3 +0,0 @@ -export const divide = number => { - return number / number; -}; \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelProject/source/lib/sum.js b/packages/babel-transpiler/testResources/babelProject/source/lib/sum.js deleted file mode 100644 index dd485cc115..0000000000 --- a/packages/babel-transpiler/testResources/babelProject/source/lib/sum.js +++ /dev/null @@ -1,3 +0,0 @@ -export const sum = number => { - return number + number; -}; \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelProject/source/main.js b/packages/babel-transpiler/testResources/babelProject/source/main.js deleted file mode 100644 index b45213c4ca..0000000000 --- a/packages/babel-transpiler/testResources/babelProject/source/main.js +++ /dev/null @@ -1,4 +0,0 @@ -import sum from './lib/sum'; -import divide from './lib/divide'; -console.log([1, 2, 3, 4].map(divide)); -console.log([1, 2, 3, 4].map(sum)); \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelProjectWithBabelConfigJs/babel.config.js b/packages/babel-transpiler/testResources/babelProjectWithBabelConfigJs/babel.config.js deleted file mode 100644 index a34a6a5a4a..0000000000 --- a/packages/babel-transpiler/testResources/babelProjectWithBabelConfigJs/babel.config.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = (api) => { - api.cache.forever(); - - return { - presets: ["@babel/preset-typescript"] - } -} diff --git a/packages/babel-transpiler/testResources/babelProjectWithBabelConfigJs/expectedResult/foo.js b/packages/babel-transpiler/testResources/babelProjectWithBabelConfigJs/expectedResult/foo.js deleted file mode 100644 index c95d6c53a9..0000000000 --- a/packages/babel-transpiler/testResources/babelProjectWithBabelConfigJs/expectedResult/foo.js +++ /dev/null @@ -1 +0,0 @@ -export const foo = 4; \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelProjectWithBabelConfigJs/expectedResult/main.js b/packages/babel-transpiler/testResources/babelProjectWithBabelConfigJs/expectedResult/main.js deleted file mode 100644 index c4ad81e932..0000000000 --- a/packages/babel-transpiler/testResources/babelProjectWithBabelConfigJs/expectedResult/main.js +++ /dev/null @@ -1 +0,0 @@ -const x = 0; \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelProjectWithBabelConfigJs/source/foo.ts b/packages/babel-transpiler/testResources/babelProjectWithBabelConfigJs/source/foo.ts deleted file mode 100644 index 914e3092cb..0000000000 --- a/packages/babel-transpiler/testResources/babelProjectWithBabelConfigJs/source/foo.ts +++ /dev/null @@ -1 +0,0 @@ -export const foo: number = 4; \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelProjectWithBabelConfigJs/source/main.ts b/packages/babel-transpiler/testResources/babelProjectWithBabelConfigJs/source/main.ts deleted file mode 100644 index cacb9b4964..0000000000 --- a/packages/babel-transpiler/testResources/babelProjectWithBabelConfigJs/source/main.ts +++ /dev/null @@ -1 +0,0 @@ -const x: number = 0; \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelProjectWithBabelConfigJsObject/babel.config.js b/packages/babel-transpiler/testResources/babelProjectWithBabelConfigJsObject/babel.config.js deleted file mode 100644 index b64fcf0f34..0000000000 --- a/packages/babel-transpiler/testResources/babelProjectWithBabelConfigJsObject/babel.config.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - presets: ["@babel/preset-typescript"] -} diff --git a/packages/babel-transpiler/testResources/babelProjectWithBabelConfigJsObject/expectedResult/foo.js b/packages/babel-transpiler/testResources/babelProjectWithBabelConfigJsObject/expectedResult/foo.js deleted file mode 100644 index c95d6c53a9..0000000000 --- a/packages/babel-transpiler/testResources/babelProjectWithBabelConfigJsObject/expectedResult/foo.js +++ /dev/null @@ -1 +0,0 @@ -export const foo = 4; \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelProjectWithBabelConfigJsObject/expectedResult/main.js b/packages/babel-transpiler/testResources/babelProjectWithBabelConfigJsObject/expectedResult/main.js deleted file mode 100644 index c4ad81e932..0000000000 --- a/packages/babel-transpiler/testResources/babelProjectWithBabelConfigJsObject/expectedResult/main.js +++ /dev/null @@ -1 +0,0 @@ -const x = 0; \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelProjectWithBabelConfigJsObject/source/foo.ts b/packages/babel-transpiler/testResources/babelProjectWithBabelConfigJsObject/source/foo.ts deleted file mode 100644 index 914e3092cb..0000000000 --- a/packages/babel-transpiler/testResources/babelProjectWithBabelConfigJsObject/source/foo.ts +++ /dev/null @@ -1 +0,0 @@ -export const foo: number = 4; \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelProjectWithBabelConfigJsObject/source/main.ts b/packages/babel-transpiler/testResources/babelProjectWithBabelConfigJsObject/source/main.ts deleted file mode 100644 index cacb9b4964..0000000000 --- a/packages/babel-transpiler/testResources/babelProjectWithBabelConfigJsObject/source/main.ts +++ /dev/null @@ -1 +0,0 @@ -const x: number = 0; \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelProjectWithBabelRcJs/.babelrc.js b/packages/babel-transpiler/testResources/babelProjectWithBabelRcJs/.babelrc.js deleted file mode 100644 index e9ae953d06..0000000000 --- a/packages/babel-transpiler/testResources/babelProjectWithBabelRcJs/.babelrc.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - presets: ["@babel/preset-typescript"] -} diff --git a/packages/babel-transpiler/testResources/babelProjectWithBabelRcJs/expectedResult/foo.js b/packages/babel-transpiler/testResources/babelProjectWithBabelRcJs/expectedResult/foo.js deleted file mode 100644 index c95d6c53a9..0000000000 --- a/packages/babel-transpiler/testResources/babelProjectWithBabelRcJs/expectedResult/foo.js +++ /dev/null @@ -1 +0,0 @@ -export const foo = 4; \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelProjectWithBabelRcJs/expectedResult/main.js b/packages/babel-transpiler/testResources/babelProjectWithBabelRcJs/expectedResult/main.js deleted file mode 100644 index c4ad81e932..0000000000 --- a/packages/babel-transpiler/testResources/babelProjectWithBabelRcJs/expectedResult/main.js +++ /dev/null @@ -1 +0,0 @@ -const x = 0; \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelProjectWithBabelRcJs/source/foo.ts b/packages/babel-transpiler/testResources/babelProjectWithBabelRcJs/source/foo.ts deleted file mode 100644 index 914e3092cb..0000000000 --- a/packages/babel-transpiler/testResources/babelProjectWithBabelRcJs/source/foo.ts +++ /dev/null @@ -1 +0,0 @@ -export const foo: number = 4; \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelProjectWithBabelRcJs/source/main.ts b/packages/babel-transpiler/testResources/babelProjectWithBabelRcJs/source/main.ts deleted file mode 100644 index cacb9b4964..0000000000 --- a/packages/babel-transpiler/testResources/babelProjectWithBabelRcJs/source/main.ts +++ /dev/null @@ -1 +0,0 @@ -const x: number = 0; \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/.babelrc b/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/.babelrc deleted file mode 100644 index 70da709728..0000000000 --- a/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/.babelrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "presets": ["@babel/env"] -} diff --git a/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/expectedResult/main.js b/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/expectedResult/main.js deleted file mode 100644 index 15b3d90eba..0000000000 --- a/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/expectedResult/main.js +++ /dev/null @@ -1,11 +0,0 @@ -"use strict"; - -function add() { - for (var _len = arguments.length, varArgs = new Array(_len), _key = 0; _key < _len; _key++) { - varArgs[_key] = arguments[_key]; - } - - return varArgs.reduce(function (a, b) { - return a + b; - }); -} \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/expectedResult/resources/pixel.gif b/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/expectedResult/resources/pixel.gif deleted file mode 100644 index 90fc402120..0000000000 Binary files a/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/expectedResult/resources/pixel.gif and /dev/null differ diff --git a/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/expectedResult/resources/pixel.jpg b/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/expectedResult/resources/pixel.jpg deleted file mode 100644 index 9f574134c6..0000000000 Binary files a/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/expectedResult/resources/pixel.jpg and /dev/null differ diff --git a/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/expectedResult/resources/pixel.png b/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/expectedResult/resources/pixel.png deleted file mode 100644 index b201b72e55..0000000000 Binary files a/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/expectedResult/resources/pixel.png and /dev/null differ diff --git a/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/expectedResult/resources/resources.zip b/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/expectedResult/resources/resources.zip deleted file mode 100644 index 03f147b04c..0000000000 Binary files a/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/expectedResult/resources/resources.zip and /dev/null differ diff --git a/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/source/main.js b/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/source/main.js deleted file mode 100644 index 9de72a3b86..0000000000 --- a/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/source/main.js +++ /dev/null @@ -1,4 +0,0 @@ - -function add(...varArgs) { - return varArgs.reduce((a, b) => a + b); -} \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/source/resources/pixel.gif b/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/source/resources/pixel.gif deleted file mode 100644 index 90fc402120..0000000000 Binary files a/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/source/resources/pixel.gif and /dev/null differ diff --git a/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/source/resources/pixel.jpg b/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/source/resources/pixel.jpg deleted file mode 100644 index 9f574134c6..0000000000 Binary files a/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/source/resources/pixel.jpg and /dev/null differ diff --git a/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/source/resources/pixel.png b/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/source/resources/pixel.png deleted file mode 100644 index b201b72e55..0000000000 Binary files a/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/source/resources/pixel.png and /dev/null differ diff --git a/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/source/resources/resources.zip b/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/source/resources/resources.zip deleted file mode 100644 index 03f147b04c..0000000000 Binary files a/packages/babel-transpiler/testResources/babelProjectWithBinaryFiles/source/resources/resources.zip and /dev/null differ diff --git a/packages/babel-transpiler/testResources/babelTypescriptProject/.babelrc b/packages/babel-transpiler/testResources/babelTypescriptProject/.babelrc deleted file mode 100644 index 66899f2f3a..0000000000 --- a/packages/babel-transpiler/testResources/babelTypescriptProject/.babelrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "presets": ["@babel/preset-typescript"] -} diff --git a/packages/babel-transpiler/testResources/babelTypescriptProject/expectedResult/foo.js b/packages/babel-transpiler/testResources/babelTypescriptProject/expectedResult/foo.js deleted file mode 100644 index c95d6c53a9..0000000000 --- a/packages/babel-transpiler/testResources/babelTypescriptProject/expectedResult/foo.js +++ /dev/null @@ -1 +0,0 @@ -export const foo = 4; \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelTypescriptProject/expectedResult/main.js b/packages/babel-transpiler/testResources/babelTypescriptProject/expectedResult/main.js deleted file mode 100644 index c4ad81e932..0000000000 --- a/packages/babel-transpiler/testResources/babelTypescriptProject/expectedResult/main.js +++ /dev/null @@ -1 +0,0 @@ -const x = 0; \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelTypescriptProject/source/foo.ts b/packages/babel-transpiler/testResources/babelTypescriptProject/source/foo.ts deleted file mode 100644 index 914e3092cb..0000000000 --- a/packages/babel-transpiler/testResources/babelTypescriptProject/source/foo.ts +++ /dev/null @@ -1 +0,0 @@ -export const foo: number = 4; \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/babelTypescriptProject/source/main.ts b/packages/babel-transpiler/testResources/babelTypescriptProject/source/main.ts deleted file mode 100644 index cacb9b4964..0000000000 --- a/packages/babel-transpiler/testResources/babelTypescriptProject/source/main.ts +++ /dev/null @@ -1 +0,0 @@ -const x: number = 0; \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/differentExtensions/.babelrc b/packages/babel-transpiler/testResources/differentExtensions/.babelrc deleted file mode 100644 index 7d878e4e69..0000000000 --- a/packages/babel-transpiler/testResources/differentExtensions/.babelrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "ignore": [ - "source/excluded.es6" - ] -} diff --git a/packages/babel-transpiler/testResources/differentExtensions/expectedResult/es.js b/packages/babel-transpiler/testResources/differentExtensions/expectedResult/es.js deleted file mode 100644 index 4fb849b650..0000000000 --- a/packages/babel-transpiler/testResources/differentExtensions/expectedResult/es.js +++ /dev/null @@ -1,3 +0,0 @@ -function add(...varArgs) { - return varArgs.reduce((a, b) => a + b); -} \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/differentExtensions/expectedResult/es6.js b/packages/babel-transpiler/testResources/differentExtensions/expectedResult/es6.js deleted file mode 100644 index 4fb849b650..0000000000 --- a/packages/babel-transpiler/testResources/differentExtensions/expectedResult/es6.js +++ /dev/null @@ -1,3 +0,0 @@ -function add(...varArgs) { - return varArgs.reduce((a, b) => a + b); -} \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/differentExtensions/expectedResult/js.js b/packages/babel-transpiler/testResources/differentExtensions/expectedResult/js.js deleted file mode 100644 index 4fb849b650..0000000000 --- a/packages/babel-transpiler/testResources/differentExtensions/expectedResult/js.js +++ /dev/null @@ -1,3 +0,0 @@ -function add(...varArgs) { - return varArgs.reduce((a, b) => a + b); -} \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/differentExtensions/expectedResult/jsx.js b/packages/babel-transpiler/testResources/differentExtensions/expectedResult/jsx.js deleted file mode 100644 index 4fb849b650..0000000000 --- a/packages/babel-transpiler/testResources/differentExtensions/expectedResult/jsx.js +++ /dev/null @@ -1,3 +0,0 @@ -function add(...varArgs) { - return varArgs.reduce((a, b) => a + b); -} \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/differentExtensions/source/es.es b/packages/babel-transpiler/testResources/differentExtensions/source/es.es deleted file mode 100644 index 9de72a3b86..0000000000 --- a/packages/babel-transpiler/testResources/differentExtensions/source/es.es +++ /dev/null @@ -1,4 +0,0 @@ - -function add(...varArgs) { - return varArgs.reduce((a, b) => a + b); -} \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/differentExtensions/source/es6.es6 b/packages/babel-transpiler/testResources/differentExtensions/source/es6.es6 deleted file mode 100644 index 665e9fbab3..0000000000 --- a/packages/babel-transpiler/testResources/differentExtensions/source/es6.es6 +++ /dev/null @@ -1,4 +0,0 @@ - -function add(...varArgs) { - return varArgs.reduce((a, b) => a + b); -} \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/differentExtensions/source/js.js b/packages/babel-transpiler/testResources/differentExtensions/source/js.js deleted file mode 100644 index 9de72a3b86..0000000000 --- a/packages/babel-transpiler/testResources/differentExtensions/source/js.js +++ /dev/null @@ -1,4 +0,0 @@ - -function add(...varArgs) { - return varArgs.reduce((a, b) => a + b); -} \ No newline at end of file diff --git a/packages/babel-transpiler/testResources/differentExtensions/source/jsx.jsx b/packages/babel-transpiler/testResources/differentExtensions/source/jsx.jsx deleted file mode 100644 index a6778b4ca6..0000000000 --- a/packages/babel-transpiler/testResources/differentExtensions/source/jsx.jsx +++ /dev/null @@ -1,3 +0,0 @@ -function add(...varArgs) { - return varArgs.reduce((a, b) => a + b); -} diff --git a/packages/babel-transpiler/tsconfig.stryker.json b/packages/babel-transpiler/tsconfig.stryker.json deleted file mode 100644 index 24aa7dc5ff..0000000000 --- a/packages/babel-transpiler/tsconfig.stryker.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "./tsconfig.test.json", - "include": [ - "src", - "src-generated", - "test" - ], -} diff --git a/packages/core/.mocharc.jsonc b/packages/core/.mocharc.jsonc new file mode 100644 index 0000000000..7cee2a58be --- /dev/null +++ b/packages/core/.mocharc.jsonc @@ -0,0 +1,3 @@ +{ + "require": ["./test/setup.js"] +} diff --git a/packages/core/.nycrc.json b/packages/core/.nycrc.json new file mode 100644 index 0000000000..0a316c4dc8 --- /dev/null +++ b/packages/core/.nycrc.json @@ -0,0 +1,11 @@ +{ + "include": [ + "src/**/*.js" + ], + "excludeAfterRemap": false, + "checkCoverage": true, + "lines": 80, + "functions": 80, + "branches": 80, + "statements": 80 +} diff --git a/packages/core/.vscode/launch.json b/packages/core/.vscode/launch.json index d066a50b0f..8e17468252 100644 --- a/packages/core/.vscode/launch.json +++ b/packages/core/.vscode/launch.json @@ -10,42 +10,16 @@ "--timeout", "999999", "--colors", - "${workspaceRoot}/test/helpers/**/*.js", "${workspaceRoot}/test/unit/**/*.js" ], "internalConsoleOptions": "openOnSessionStart", "outFiles": [ "${workspaceRoot}/test/**/*.js", "${workspaceRoot}/src/**/*.js" - ] - }, - { - "type": "node", - "request": "launch", - "name": "Index", - "program": "${workspaceRoot}/index.js", - "args": [ ], - "internalConsoleOptions": "openOnSessionStart", - "outFiles": [ - "${workspaceRoot}/test/**/*.js", - "${workspaceRoot}/src/**/*.js" - ] - }, - { - "type": "node", - "request": "launch", - "name": "e2e command runner", - "program": "${workspaceRoot}/../../e2e/test/angular-project/node_modules/@stryker-mutator/core/bin/stryker", - "args": [ - "run" + "skipFiles": [ + "/**" ], - "cwd": "${workspaceFolder}/../../e2e/test/angular-project", - "internalConsoleOptions": "openOnSessionStart", - "outFiles": [ - "${workspaceRoot}/test/**/*.js", - "${workspaceRoot}/src/**/*.js" - ] }, { "type": "node", @@ -56,38 +30,15 @@ "--timeout", "999999", "--colors", - "${workspaceRoot}/test/helpers/**/*.js", "${workspaceRoot}/test/integration/**/*.js" ], "internalConsoleOptions": "openOnSessionStart", "outFiles": [ "${workspaceRoot}/test/**/*.js", "${workspaceRoot}/src/**/*.js" - ] - }, - { - "name": "Run stryker example", - "type": "node", - "request": "launch", - "program": "${workspaceRoot}/bin/stryker", - // "preLaunchTask": "build", - "stopOnEntry": false, - "args": [ - "run" - ], - "cwd": "${workspaceRoot}/../../sampleProject", - "runtimeExecutable": null, - "runtimeArgs": [ - "--nolazy" ], - "env": { - "NODE_ENV": "development" - }, - "console": "integratedTerminal", - "sourceMaps": true, - "outFiles": [ - "${workspaceRoot}/test/**/*.js", - "${workspaceRoot}/src/**/*.js" + "skipFiles": [ + "/**" ] }, { @@ -98,8 +49,7 @@ // "preLaunchTask": "build", "stopOnEntry": false, "args": [ - "run", - "stryker.conf.js" + "run" ], "cwd": "${workspaceRoot}", "runtimeExecutable": null, @@ -114,33 +64,9 @@ "outFiles": [ "${workspaceRoot}/test/**/*.js", "${workspaceRoot}/src/**/*.js" - ] - }, - { - "name": "Run stryker help", - "type": "node", - "request": "launch", - "program": "${workspaceRoot}/bin/stryker", - // "preLaunchTask": "build", - "stopOnEntry": false, - "args": [ - "--logLevel", - "debug", - "run" - ], - "cwd": "${workspaceRoot}/.", - "runtimeExecutable": null, - "runtimeArgs": [ - "--nolazy" ], - "env": { - "NODE_ENV": "development" - }, - "console": "internalConsole", - "sourceMaps": true, - "outFiles": [ - "${workspaceRoot}/test/**/*.js", - "${workspaceRoot}/src/**/*.js" + "skipFiles": [ + "/**" ] } ] diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index b16211c1e3..b96cfce30a 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -3,6 +3,195 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [4.0.0-beta.10](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.9...v4.0.0-beta.10) (2020-10-05) + + +### Features + +* **instrumenter:** add excludedMutations support ([#2513](https://github.com/stryker-mutator/stryker/issues/2513)) ([bfd714f](https://github.com/stryker-mutator/stryker/commit/bfd714fe1b4f9c3b2468164a95d0c5bd0cbc8fcf)) + + + + + +# [4.0.0-beta.9](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.8...v4.0.0-beta.9) (2020-09-30) + + +### Bug Fixes + +* **config:** deprecate function based config ([#2499](https://github.com/stryker-mutator/stryker/issues/2499)) ([8ea3c18](https://github.com/stryker-mutator/stryker/commit/8ea3c18421929a0724ff99e5bf02ce0f174266cd)) +* **core:** fix "too many open files" ([#2498](https://github.com/stryker-mutator/stryker/issues/2498)) ([5b7c242](https://github.com/stryker-mutator/stryker/commit/5b7c2424dc57b32d390112bcbf8b79bf41c05a11)) + + +### Features + +* **core:** add `appendPlugins` command-line option ([#2385](https://github.com/stryker-mutator/stryker/issues/2385)) ([0dec9b8](https://github.com/stryker-mutator/stryker/commit/0dec9b84b07391752af5514f90a2120c4f01d260)) +* **core:** correct initial test run timing ([#2496](https://github.com/stryker-mutator/stryker/issues/2496)) ([4f5a37e](https://github.com/stryker-mutator/stryker/commit/4f5a37eb63a4e9532022821dac85d68f8939ceab)) +* **test-runner:** Add `--maxTestRunnerReuse` support ([5919484](https://github.com/stryker-mutator/stryker/commit/59194841505e520ddc382ea4affc78ef16978e1b)) + + +### BREAKING CHANGES + +* **config:** exporting a function from stryker.conf.js is deprecated. Please export your config as an object instead, or use a stryker.conf.json file. + +Co-authored-by: Nico Jansen + + + + + +# [4.0.0-beta.8](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.7...v4.0.0-beta.8) (2020-09-22) + + +### Bug Fixes + +* **instrumenter:** ignore `declare` syntax ([b1faa16](https://github.com/stryker-mutator/stryker/commit/b1faa1603f68dded5d694cdb41b6e75b05ac9e1a)) + + +### Features + +* **core:** add `--cleanTempDir` cli option ([6ef792c](https://github.com/stryker-mutator/stryker/commit/6ef792c839c0464c7acbeb72560574dc94480eea)) +* **instrumenter:** improve placement error ([12e097e](https://github.com/stryker-mutator/stryker/commit/12e097e287d24e41656d2b3897335b3f93654e5d)) + + + + + +# [4.0.0-beta.7](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.6...v4.0.0-beta.7) (2020-09-17) + + +### Bug Fixes + +* **core:** allow skipped tests when matching mutants ([#2487](https://github.com/stryker-mutator/stryker/issues/2487)) ([09eacee](https://github.com/stryker-mutator/stryker/commit/09eaceece587e4e583348fbec7682ba77715bd8c)), closes [#2485](https://github.com/stryker-mutator/stryker/issues/2485) + + + + + +# [4.0.0-beta.6](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.5...v4.0.0-beta.6) (2020-09-10) + +**Note:** Version bump only for package @stryker-mutator/core + + + + + +# [4.0.0-beta.5](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.4...v4.0.0-beta.5) (2020-09-09) + + +### Bug Fixes + +* **reporters:** correctly report avg tests/mutants ([#2458](https://github.com/stryker-mutator/stryker/issues/2458)) ([582e01b](https://github.com/stryker-mutator/stryker/commit/582e01befe7ce2effdcde86f2c3123ccaff89c18)) + + +### Features + +* **mutate:** a new default for `mutate` ([#2452](https://github.com/stryker-mutator/stryker/issues/2452)) ([673516d](https://github.com/stryker-mutator/stryker/commit/673516d3fb92534fc3aad62d17243b558fae3ba4)), closes [#2384](https://github.com/stryker-mutator/stryker/issues/2384) +* **typescript:** Disable type checking ([#2446](https://github.com/stryker-mutator/stryker/issues/2446)) ([3ff996b](https://github.com/stryker-mutator/stryker/commit/3ff996b7516b7782434d86aa9aecbee334978a7f)), closes [#2438](https://github.com/stryker-mutator/stryker/issues/2438) + + + + + +# [4.0.0-beta.4](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.3...v4.0.0-beta.4) (2020-08-29) + + +### Bug Fixes + +* **input files:** support emojis in file names ([#2430](https://github.com/stryker-mutator/stryker/issues/2430)) ([139f9f3](https://github.com/stryker-mutator/stryker/commit/139f9f3ea9aa2349198cb824ceb444f7c6b013b6)) +* **input files:** support emojis in file names ([#2433](https://github.com/stryker-mutator/stryker/issues/2433)) ([b5feae2](https://github.com/stryker-mutator/stryker/commit/b5feae2558ade9a1f2d947f7fd046033e4c9d996)) + + +### Features + +* **api:** rename test_runner2 -> test_runner ([#2442](https://github.com/stryker-mutator/stryker/issues/2442)) ([4d3ae97](https://github.com/stryker-mutator/stryker/commit/4d3ae9764dbd689c895b76e44f2eea76c82fabc8)) +* **options:** deprecate old stryker options ([#2395](https://github.com/stryker-mutator/stryker/issues/2395)) ([7c637c8](https://github.com/stryker-mutator/stryker/commit/7c637c8714169a03facd42a7521f7670b7606a32)) +* **reporter-api:** support mutation switching ([67f1ed5](https://github.com/stryker-mutator/stryker/commit/67f1ed52f4d17df4306362064180d267ed5445c7)) + + +### BREAKING CHANGES + +* **api:** Plugin creators should now use `'test_runner'` instead of `'test_runner2'`. +* **reporter-api:** The `onMutantTested` and `onAllMutantsTested` methods on the `Reporter` api have changed + + + + + +# [4.0.0-beta.3](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.2...v4.0.0-beta.3) (2020-08-19) + + +### Bug Fixes + +* **core:** exit process on error ([#2378](https://github.com/stryker-mutator/stryker/issues/2378)) ([af18a59](https://github.com/stryker-mutator/stryker/commit/af18a590fc916d75d54bcfaf2dda1d6a90bd4df8)), closes [#2315](https://github.com/stryker-mutator/stryker/issues/2315) +* **exit prematurely:** exit when no tests were executed ([#2380](https://github.com/stryker-mutator/stryker/issues/2380)) ([6885e16](https://github.com/stryker-mutator/stryker/commit/6885e16fad7699ba93e6ebbbf0755c7d98c50c5a)) + + +### Features + +* **core:** add ability to override file headers ([#2363](https://github.com/stryker-mutator/stryker/issues/2363)) ([430d6d3](https://github.com/stryker-mutator/stryker/commit/430d6d3d17fe2ad8e2cef3b858afa7efb86c2342)) +* **core:** strip comments in sandbox ([#2365](https://github.com/stryker-mutator/stryker/issues/2365)) ([55f27f2](https://github.com/stryker-mutator/stryker/commit/55f27f29b6994096c9aad038958ee93e9fa0f035)), closes [#2364](https://github.com/stryker-mutator/stryker/issues/2364) +* **test runner api:** remove `sandboxFileNames` injectable values ([#2369](https://github.com/stryker-mutator/stryker/issues/2369)) ([92f3bf5](https://github.com/stryker-mutator/stryker/commit/92f3bf528d0b01be1f6c219b37a5f90da0431686)), closes [#2351](https://github.com/stryker-mutator/stryker/issues/2351) + + +### BREAKING CHANGES + +* **exit prematurely:** Stryker will now exit with exit code 1 when no tests were executed in the initial test run. + + + + + +# [4.0.0-beta.2](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.1...v4.0.0-beta.2) (2020-08-07) + + +### Features + +* **command:** Support command test runner with mutation switching ([#2345](https://github.com/stryker-mutator/stryker/issues/2345)) ([59b1cfc](https://github.com/stryker-mutator/stryker/commit/59b1cfc06c4f8f5ec1e55dce4823e0f9c384b16c)) +* **jest-runner:** support mutation switching ([#2350](https://github.com/stryker-mutator/stryker/issues/2350)) ([9e6e6e0](https://github.com/stryker-mutator/stryker/commit/9e6e6e077731344ed0588d64b5c8ba2f19c8492e)) + + + + + +# [4.0.0-beta.1](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.0...v4.0.0-beta.1) (2020-07-17) + +**Note:** Version bump only for package @stryker-mutator/core + + + + + +# [4.0.0-beta.0](https://github.com/stryker-mutator/stryker/compare/v3.3.1...v4.0.0-beta.0) (2020-07-10) + + +### Bug Fixes + +* **buildCommand:** allow for a single command string in posix ([77b6a20](https://github.com/stryker-mutator/stryker/commit/77b6a209955bb71fffee61919cec6b3a14db2eff)) +* **reporter:** report event order ([#2311](https://github.com/stryker-mutator/stryker/issues/2311)) ([ceb73a8](https://github.com/stryker-mutator/stryker/commit/ceb73a83dddce0df1bd1c6b9f7e7e8e75fe77e31)) +* **sandbox:** exec build command before symlink ([bd25cd6](https://github.com/stryker-mutator/stryker/commit/bd25cd6ce2f28fe4b1b1b3ac792d99a9742e438b)) + + +### Features + +* **api:** add id to Mutant interface ([#2255](https://github.com/stryker-mutator/stryker/issues/2255)) ([cfc9053](https://github.com/stryker-mutator/stryker/commit/cfc90537d0b9815cba2b44b9681d171ca602766e)) +* **api:** remove support for options editors ([5e56d0e](https://github.com/stryker-mutator/stryker/commit/5e56d0ea6982faf11048c8ca4bbb912ee17e88eb)) +* **checker:** add checker api ([#2240](https://github.com/stryker-mutator/stryker/issues/2240)) ([d463f86](https://github.com/stryker-mutator/stryker/commit/d463f8639437c114da4fe30115652e8a470dd179)), closes [#1514](https://github.com/stryker-mutator/stryker/issues/1514) [#1980](https://github.com/stryker-mutator/stryker/issues/1980) +* **core:** add support for checker plugins ([#2285](https://github.com/stryker-mutator/stryker/issues/2285)) ([69358e1](https://github.com/stryker-mutator/stryker/commit/69358e1423701c730e29d303119a08d74081f340)) +* **core:** support build command ([f71ba87](https://github.com/stryker-mutator/stryker/commit/f71ba87a7adfd85131e1dea5fb1d6f3d8bba76df)) +* **instrumenter:** allow override of babel plugins ([8758cfd](https://github.com/stryker-mutator/stryker/commit/8758cfdda8ac2bfa761568f55ddee48c2a23f0e0)) +* **sandbox:** add ignore header to js files ([#2291](https://github.com/stryker-mutator/stryker/issues/2291)) ([3adde83](https://github.com/stryker-mutator/stryker/commit/3adde830deb8d4b471ae6fceafd603c9750419d7)), closes [#2276](https://github.com/stryker-mutator/stryker/issues/2276) +* **tsconfig:** rewrite tsconfig references ([#2292](https://github.com/stryker-mutator/stryker/issues/2292)) ([4ee4950](https://github.com/stryker-mutator/stryker/commit/4ee4950bebd8db9c2f5a514edee57de55c040526)), closes [#2276](https://github.com/stryker-mutator/stryker/issues/2276) + + +### BREAKING CHANGES + +* **core:** * `--maxConcurrentTestRunners` is now deprecated. Please use `--concurrency` instead. + + + + + ## [3.3.1](https://github.com/stryker-mutator/stryker/compare/v3.3.0...v3.3.1) (2020-07-04) diff --git a/packages/core/README.md b/packages/core/README.md index 2accd7dd8c..f0351d7cc6 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -51,7 +51,6 @@ The following is an example `stryker.conf.json` file. It specifies running mocha "src/**/*.js", "!src/index.js" ], - "testFramework": "mocha", "testRunner": "mocha", "reporters": ["progress", "clear-text", "html"], "coverageAnalysis": "perTest" @@ -68,7 +67,6 @@ module.exports = { 'src/**/*.js', '!src/index.js' ], - testFramework: 'mocha', testRunner: 'mocha', reporters: ['progress', 'clear-text', 'html'], coverageAnalysis: 'perTest' @@ -103,25 +101,27 @@ You can *ignore* files by adding an exclamation mark (`!`) at the start of an ex ### Available Options * [allowConsoleColors](#allowConsoleColors) +* [buildCommand](#buildCommand) +* [cleanTempDir](#cleanTempDir) * [commandRunner](#commandRunner) * [coverageAnalysis](#coverageAnalysis) * [dashboard.*](#dashboard) * [fileLogLevel](#fileLogLevel) -* [files](#files) +* [files](#files-string) * [logLevel](#logLevel) * [maxConcurrentTestRunners](#maxConcurrentTestRunners) * [mutate](#mutate) * [mutator](#mutator) * [plugins](#plugins) * [reporters](#reporters) +* [sandbox.fileHeaders](#sandbox.fileHeaders) +* [sandbox.stripComments](#sandbox.stripComments) * [symlinkNodeModules](#symlinkNodeModules) * [tempDirName](#tempDirName) -* [testFramework](#testFramework) * [testRunner](#testRunner) * [thresholds](#thresholds) * [timeoutFactor](#timeoutFactor) * [timeoutMS](#timeoutMS) -* [transpilers](#transpilers) ### `allowConsoleColors` [`boolean`] @@ -132,6 +132,26 @@ Config file: `allowConsoleColors: true` The `allowConsoleColors` value indicates whether Stryker should use colors in console. + +### `buildCommand` [`string`] + +Default: `undefined` +Command line: `[-b|--buildCommand] "npm run build"` +Config file: `buildCommand: 'npm run build'` + +Configure a build command to run after mutating the code, but before mutants are tested. This is generally used to transpile your code before testing. +Only configure this if your test runner doesn't take care of this already and you're not using just-in-time transpiler like `babel/register` or `ts-node`. + + +### `cleanTempDir` [`boolean`] + +Default: `true` +Command line: `--cleanTempDir false` +Config file: `cleanTempDir: false` + +Choose whether or not to clean the temp dir (which is ".stryker-tmp" inside the current working directory by default) after a successful run. +The temp dir will never be removed when the run failed for some reason (for debugging purposes). + ### `commandRunner` [`object`] @@ -155,6 +175,7 @@ particular mutation are tested for each mutant. This does *not* influence the resulting mutation testing score. It only improves performance. The possible values are: + * **off**: Stryker will not determine the code covered by tests during the initial test run phase. All tests will be executed for each mutant during the mutation testing phase. @@ -165,10 +186,8 @@ Currently, only the `stryker-mocha-runner` and the `stryker-karma-runner` do thi * **perTest**: Stryker will determine the code covered by your test per executed test during the initial test run phase. Only mutants actually covered by your test suite are tested during the mutation testing phase. Only the tests that cover a particular mutant are tested for each one. This requires your tests to be able to run independently of each other and in random order. -In addition to requiring your test runner to be able to report the code coverage back to Stryker, your chosen `testFramework` also needs to support running code before and after each test, as well as test filtering. - Currently, `stryker-mocha-runner` as well as `stryker-karma-runner` support this. However, `stryker-karma-runner` support is limited to using it with `Jasmine` as the test framework - (`Mocha` is not yet supported). + Currently all test runner plugins, except for `@stryker-mutator/jest-runner`) support this feature. ### `dashboard` [`DashboardOptions`] @@ -182,13 +201,13 @@ Settings for the `dashboard` [reporter](#reporters). See the [stryker handbook f ### `fileLogLevel` [`string`] - Default: `off` - Command line: `--fileLogLevel info` - Config file: `fileLogLevel: 'info'` +Default: `off` +Command line: `--fileLogLevel info` +Config file: `fileLogLevel: 'info'` - Set the log level that Stryker uses to write to the "stryker.log" file. Possible values: `off`, `fatal`, `error`, `warn`, `info`, `debug` and `trace` +Set the log level that Stryker uses to write to the "stryker.log" file. Possible values: `off`, `fatal`, `error`, `warn`, `info`, `debug` and `trace` - + ### `files` [`string[]`] Default: result of `git ls-files --others --exclude-standard --cached --exclude .stryker-tmp` @@ -249,22 +268,18 @@ Generally speaking, these should be your own source files. This is optional, as you can choose to not mutate any files at all and perform a dry-run (running only your tests without mutating). -### `mutator` [`object` | `string`] -Default: `javascript` -Command line: `--mutator javascript` -Config file: `mutator: 'javascript'` or `mutator: { name: 'javascript', plugins: ['classProperties', 'optionalChaining'], excludedMutations: ['BooleanSubstitution', 'StringLiteral'] }` +### `mutator` [`MutatorDescriptor`] -With `mutator` you configure which mutator plugin you want to use, and optionally, which mutation types to exclude from the test run. -The mutator plugin name defaults to `javascript` if not specified. Note: this requires you to have the `@stryker-mutator/javascript-mutator` plugin installed. The list of excluded mutation types defaults to an empty array, meaning all mutation types will be included in the test. -The full list of mutation types varies slightly between mutators (for example, the `javascript` mutator will not use the same mutation types as the `typescript` mutator). Mutation type names are case-sensitive, and can be found either in the source code or in a generated Stryker report. +Default: `{}` +Command line: *none* +Config file: ``mutator: { plugins: ['classProperties', 'optionalChaining'], excludedMutations: ['BooleanSubstitution', 'StringLiteral'] }` -When using the command line, only the mutator name as a string may be provided. -When using the config file, you can provide either a string representing the mutator name, or a `MutatorDescriptor` object, like so: +* `plugins`: allows you to override the default [babel plugins](https://babeljs.io/docs/en/plugins) to use for JavaScript files. +By default, Stryker uses [a default list of babel plugins to parse your JS file](https://github.com/stryker-mutator/stryker/blob/master/packages/instrumenter/src/parsers/js-parser.ts#L8-L32). It also loads any plugins or presets you might have configured yourself with `.babelrc` or `babel.config.js` files. +In the rare situation where the plugins Stryker loads conflict with your own local plugins (for example, when using the decorators and decorators-legacy plugins together), you can override the `plugins` here to `[]`. +* `excludedMutations`: allow you to specify a [list of mutator names](https://github.com/stryker-mutator/stryker-handbook/blob/master/mutator-types.md#supported-mutators) to be excluded (`ignored`) from the test run. -* `MutatorDescriptor` object: `{ name: 'name', plugins: ['classProperties', 'optionalChaining'], excludedMutations: ['mutationType1', 'mutationType2', ...] }`: - * The `name` property is mandatory and contains the name of the mutator plugin to use. - * The `plugins` property is optional and allows you to specify syntax plugins. Please see the README of your mutator to see which plugins are supported. - * The `excludedMutations` property is mandatory and contains the types of mutations to exclude from the test run. +_Note: prior to Stryker version 4, the mutator also needed a `name` (or be defined as `string`). This is removed in version 4. Stryker now supports mutating of JavaScript and friend files out of the box, without the need of a mutator plugin._ ### `plugins` [`string[]`] @@ -277,7 +292,7 @@ Config file: `plugins: ['@stryker-mutator/jasmine-framework', '@stryker-mutator/ With `plugins`, you can add additional Node modules for Stryker to load (or `require`). By default, all `node_modules` starting with `@stryker-mutator/*` will be loaded, so you would normally not need to specify this option. These modules should be installed right next to stryker. For a current list of plugins, -you can consult [npm](https://www.npmjs.com/search?q=%40stryker-plugin) or +you can consult [npm](https://www.npmjs.com/search?q=stryker-plugin) or [stryker-mutator.io](https://stryker-mutator.io). @@ -302,6 +317,30 @@ The `clear-text` reporter supports three additional config options: The `dashboard` reporter sends a report to https://dashboard.stryker-mutator.io, enabling you to add a mutation score badge to your readme, as well as hosting your html report on the dashboard. It uses the [dashboard.*](#dashboard) configuration options. See [the Stryker handbook](https://github.com/stryker-mutator/stryker-handbook/blob/master/dashboard.md) for more info. + +### `sandbox.fileHeaders` [`object`] + +Default: `{ "**/*+(.js|.ts|.cjs|.mjs)?(x)": "/* eslint-disable */\n// @ts-nocheck\n" }` +Command line: *none* +Config file: `sandbox: { fileHeaders: {} }` + +Configure additional headers to be added to files inside your sandbox. These headers will be added after Stryker has instrumented your code with mutants, but before a test runner or build command is executed. This is be used to ignore typescript compile errors and eslint warnings that might have been added in the process of instrumenting your code. + +The key here is a [glob expression](https://globster.xyz/), where the value points to the header to be used for matching files. + +*Note: The default setting should work for most use cases, only change this if you know what you are doing.* + + +### `sandbox.stripComments` [`false` | `string`] + +Default: `"**/*+(.js|.ts|.cjs|.mjs)?(x)"` +Command line: *none* +Config file: `sandbox: { stripComments: "" }` + +Configure files to be stripped of comments (either single line with `//` or multi line with `/**/`. These comments will be stripped after Stryker has instrumented your code with mutants, but before a test runner or build command is executed. This is used to remove any lingering `// @ts-check` or `// @ts-expect-error` comments that interfere with typescript compilation. The default setting allows comments to be stripped from all JavaScript and friend files in your sandbox, you can specify a different [glob expression](https://globster.xyz/) or set it to `false` to completely disable this behavior. + +*Note: The default setting should work for most use cases, only change this if you know what you are doing.* + ### `symlinkNodeModules` [`boolean`] @@ -336,17 +375,8 @@ It is advised to use a directory inside the directory that holds your repository not check-in your chosen temp directory in your `.gitignore` file. -### `testFramework` [`string`] - -Default: *none* -Command line: `--testFramework jasmine` -Config file: `testFramework: 'jasmine'` -Configure which test framework you are using. -This option is not mandatory, as Stryker is test framework agnostic (it doesn't care what framework you use), -However, it is required when `coverageAnalysis` is set to `'perTest'`, because Stryker needs to hook into the test framework in order to measure code coverage results per test and filter tests to run. - -Make sure the plugin is installed for your chosen test framework. E.g. install `stryker-mocha-framework` to use `'mocha'` as a test framework. +_Note: Use of "testFramework" is no longer needed. You can remove it from your configuration. Your test runner plugin now handles its own test framework integration_ ### `testRunner` [`string`] @@ -411,9 +441,5 @@ With `timeoutFactor` you can configure the allowed deviation relative to the tim `timeoutMS` lets you configure an absolute deviation. Use it, if you run Stryker on a busy machine and you need to wait longer to make sure that the code indeed entered an infinite loop. -### `transpilers` [`string[]`] - -Default: `[]` - -With `transpilers` you configure which transpiler plugins should transpile the code before it's executed. This is an array where the transpilers are called in the other of the array. This defaults to an empty array meaning no transpilation will be done. +_Note: Support for "transpilers" plugins is removed since Stryker 4. You can now configure your own [buildCommand](#buildCommand)_ diff --git a/packages/core/package.json b/packages/core/package.json index f2402993c4..f1353ba47c 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,12 +1,14 @@ { "name": "@stryker-mutator/core", - "version": "3.3.1", + "version": "4.0.0-beta.10", "description": "The extendable JavaScript mutation testing framework", "main": "src/Stryker.js", "scripts": { "start": "tsc -w", - "test": "nyc --exclude-after-remap=false --check-coverage --reporter=html --report-dir=reports/coverage --lines 80 --functions 80 --branches 75 npm run mocha", - "mocha": "mocha \"test/helpers/**/*.js\" \"test/unit/**/*.js\" && mocha --timeout 60000 \"test/helpers/**/*.js\" \"test/integration/**/*.js\"", + "test": "nyc npm run test:all", + "test:all": "npm run test:unit && npm run test:integration", + "test:unit": "mocha 'test/unit/**/*.js'", + "test:integration": "mocha --timeout 60000 'test/integration/**/*.js'", "stryker": "node bin/stryker run" }, "repository": { @@ -53,41 +55,46 @@ "stryker": "./bin/stryker" }, "dependencies": { - "@stryker-mutator/api": "^3.3.1", - "@stryker-mutator/util": "^3.3.1", - "ajv": "^6.12.0", - "chalk": "~4.0.0", - "commander": "~5.1.0", + "@stryker-mutator/api": "4.0.0-beta.10", + "@stryker-mutator/instrumenter": "4.0.0-beta.10", + "@stryker-mutator/util": "4.0.0-beta.10", + "ajv": "~6.12.0", + "chalk": "~4.1.0", + "commander": "~6.1.0", + "execa": "~4.0.2", "file-url": "~3.0.0", "get-port": "~5.0.0", "glob": "~7.1.2", - "inquirer": "~7.1.0", - "istanbul-lib-instrument": "~3.3.0", - "lodash.flatmap": "^4.5.0", - "lodash.groupby": "^4.6.0", - "log4js": "6.2.1", + "inquirer": "~7.3.2", + "lodash.flatmap": "~4.5.0", + "lodash.groupby": "~4.6.0", + "log4js": "~6.2.1", + "minimatch": "~3.0.4", "mkdirp": "~1.0.3", "mutation-testing-elements": "~1.4.0", "mutation-testing-metrics": "~1.4.0", + "npm-run-path": "~4.0.1", "progress": "~2.0.0", "rimraf": "~3.0.0", "rxjs": "~6.6.0", "source-map": "~0.7.3", + "strip-comments": "~2.0.1", "surrial": "~2.0.2", "tree-kill": "~1.2.2", "tslib": "~2.0.0", - "typed-inject": "~2.2.1", + "typed-inject": "~3.0.0", "typed-rest-client": "~1.7.1" }, "devDependencies": { - "@stryker-mutator/api": "^0.24.1", - "@stryker-mutator/test-helpers": "^3.3.1", - "@types/inquirer": "~6.0.2", - "@types/istanbul-lib-instrument": "~1.7.0", - "@types/lodash.flatmap": "^4.5.6", - "@types/lodash.groupby": "^4.6.6", + "@stryker-mutator/api": "4.0.0-beta.4", + "@stryker-mutator/test-helpers": "4.0.0-beta.10", + "@types/inquirer": "~7.3.1", + "@types/lodash.flatmap": "~4.5.6", + "@types/lodash.groupby": "~4.6.6", + "@types/minimatch": "~3.0.3", "@types/node": "^14.0.1", "@types/progress": "~2.0.1", - "flatted": "^2.0.0" + "@types/strip-comments": "~2.0.0", + "flatted": "~3.1.0" } } diff --git a/packages/core/src/FileStatements.ts b/packages/core/src/FileStatements.ts deleted file mode 100644 index 5e8646baf0..0000000000 --- a/packages/core/src/FileStatements.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { StatementMap } from '@stryker-mutator/api/test_runner'; - -interface FileStatements { - path: string; - statements: StatementMap; -} - -export default FileStatements; diff --git a/packages/core/src/Sandbox.ts b/packages/core/src/Sandbox.ts deleted file mode 100644 index 3f5cb0ff65..0000000000 --- a/packages/core/src/Sandbox.ts +++ /dev/null @@ -1,210 +0,0 @@ -import * as path from 'path'; - -import { StrykerOptions } from '@stryker-mutator/api/core'; -import { File } from '@stryker-mutator/api/core'; -import { MutantResult, MutantStatus } from '@stryker-mutator/api/report'; -import { TestFramework } from '@stryker-mutator/api/test_framework'; -import { RunResult, RunStatus, TestRunner, TestStatus } from '@stryker-mutator/api/test_runner'; -import { normalizeWhitespaces } from '@stryker-mutator/util'; -import { getLogger } from 'log4js'; -import * as mkdirp from 'mkdirp'; - -import LoggingClientContext from './logging/LoggingClientContext'; -import ResilientTestRunnerFactory from './test-runner/ResilientTestRunnerFactory'; -import TestableMutant, { TestSelectionResult } from './TestableMutant'; -import TranspiledMutant from './TranspiledMutant'; -import { findNodeModules, symlinkJunction, writeFile } from './utils/fileUtils'; -import { wrapInClosure } from './utils/objectUtils'; -import { TemporaryDirectory } from './utils/TemporaryDirectory'; - -interface FileMap { - [sourceFile: string]: string; -} - -export default class Sandbox { - private readonly log = getLogger(Sandbox.name); - private testRunner: Required; - private fileMap: FileMap; - private readonly workingDirectory: string; - - private constructor( - private readonly options: StrykerOptions, - private readonly index: number, - private readonly files: readonly File[], - private readonly testFramework: TestFramework | null, - private readonly timeOverheadMS: number, - private readonly loggingContext: LoggingClientContext, - temporaryDirectory: TemporaryDirectory - ) { - this.workingDirectory = temporaryDirectory.createRandomDirectory('sandbox'); - this.log.debug('Creating a sandbox for files in %s', this.workingDirectory); - } - - private async initialize(): Promise { - await this.fillSandbox(); - await this.symlinkNodeModulesIfNeeded(); - return this.initializeTestRunner(); - } - - public static create( - options: StrykerOptions, - index: number, - files: readonly File[], - testFramework: TestFramework | null, - timeoutOverheadMS: number, - loggingContext: LoggingClientContext, - temporaryDirectory: TemporaryDirectory - ): Promise { - const sandbox = new Sandbox(options, index, files, testFramework, timeoutOverheadMS, loggingContext, temporaryDirectory); - return sandbox.initialize().then(() => sandbox); - } - - public run(timeout: number, testHooks: string | undefined, mutatedFileName?: string): Promise { - return this.testRunner.run({ timeout, testHooks, mutatedFileName }); - } - - public dispose(): Promise { - return this.testRunner.dispose() || Promise.resolve(); - } - - public async runMutant(transpiledMutant: TranspiledMutant): Promise { - const earlyResult = this.retrieveEarlyResult(transpiledMutant); - if (earlyResult) { - return earlyResult; - } else { - const mutantFiles = transpiledMutant.transpileResult.outputFiles; - if (transpiledMutant.mutant.testSelectionResult === TestSelectionResult.Failed) { - this.log.warn( - `Failed find coverage data for this mutant, running all tests. This might have an impact on performance: ${transpiledMutant.mutant.toString()}` - ); - } - await Promise.all(mutantFiles.map((mutatedFile) => this.writeFileInSandbox(mutatedFile))); - const runResult = await this.run( - this.calculateTimeout(transpiledMutant.mutant), - this.getFilterTestsHooks(transpiledMutant.mutant), - this.fileMap[transpiledMutant.mutant.fileName] - ); - await this.reset(mutantFiles); - return this.collectMutantResult(transpiledMutant.mutant, runResult); - } - } - - private readonly retrieveEarlyResult = (transpiledMutant: TranspiledMutant): MutantResult | null => { - if (transpiledMutant.transpileResult.error) { - if (this.log.isDebugEnabled()) { - this.log.debug( - `Transpile error occurred: "${transpiledMutant.transpileResult.error}" during transpiling of mutant ${transpiledMutant.mutant.toString()}` - ); - } - const result = transpiledMutant.mutant.createResult(MutantStatus.TranspileError, []); - return result; - } else if (!transpiledMutant.mutant.runAllTests && !transpiledMutant.mutant.selectedTests.length) { - const result = transpiledMutant.mutant.createResult(MutantStatus.NoCoverage, []); - return result; - } else if (!transpiledMutant.changedAnyTranspiledFiles) { - const result = transpiledMutant.mutant.createResult(MutantStatus.Survived, []); - return result; - } else { - // No early result possible, need to run in the sandbox later - return null; - } - }; - - private collectMutantResult(mutant: TestableMutant, runResult: RunResult): MutantResult { - const status: MutantStatus = this.determineMutantState(runResult); - const testNames = runResult.tests.filter((t) => t.status !== TestStatus.Skipped).map((t) => t.name); - if (this.log.isDebugEnabled() && status === MutantStatus.RuntimeError) { - const error = runResult.errorMessages ? runResult.errorMessages.toString() : '(undefined)'; - this.log.debug('A runtime error occurred: %s during execution of mutant: %s', error, mutant.toString()); - } - return mutant.createResult(status, testNames); - } - - private determineMutantState(runResult: RunResult): MutantStatus { - switch (runResult.status) { - case RunStatus.Timeout: - return MutantStatus.TimedOut; - case RunStatus.Error: - return MutantStatus.RuntimeError; - case RunStatus.Complete: - if (runResult.tests.some((t) => t.status === TestStatus.Failed)) { - return MutantStatus.Killed; - } else { - return MutantStatus.Survived; - } - } - } - - private reset(mutatedFiles: readonly File[]) { - const originalFiles = this.files.filter((originalFile) => mutatedFiles.some((mutatedFile) => mutatedFile.name === originalFile.name)); - - return Promise.all(originalFiles.map((file) => writeFile(this.fileMap[file.name], file.content))); - } - - private writeFileInSandbox(file: File): Promise { - const fileNameInSandbox = this.fileMap[file.name]; - return writeFile(fileNameInSandbox, file.content); - } - - private fillSandbox(): Promise { - this.fileMap = Object.create(null); - const copyPromises = this.files.map((file) => this.fillFile(file)); - return Promise.all(copyPromises); - } - - private async symlinkNodeModulesIfNeeded(): Promise { - if (this.options.symlinkNodeModules) { - // TODO: Change with this.options.basePath when we have it - const basePath = process.cwd(); - const nodeModules = await findNodeModules(basePath); - if (nodeModules) { - await symlinkJunction(nodeModules, path.join(this.workingDirectory, 'node_modules')).catch((error: NodeJS.ErrnoException) => { - if (error.code === 'EEXIST') { - this.log.warn( - normalizeWhitespaces(`Could not symlink "${nodeModules}" in sandbox directory, - it is already created in the sandbox. Please remove the node_modules from your sandbox files. - Alternatively, set \`symlinkNodeModules\` to \`false\` to disable this warning.`) - ); - } else { - this.log.warn(`Unexpected error while trying to symlink "${nodeModules}" in sandbox directory.`, error); - } - }); - } else { - this.log.warn(`Could not find a node_modules folder to symlink into the sandbox directory. Search "${basePath}" and its parent directories`); - } - } - } - - private fillFile(file: File): Promise { - const relativePath = path.relative(process.cwd(), file.name); - const folderName = path.join(this.workingDirectory, path.dirname(relativePath)); - mkdirp.sync(folderName); - const targetFile = path.join(folderName, path.basename(relativePath)); - this.fileMap[file.name] = targetFile; - return writeFile(targetFile, file.content); - } - - private async initializeTestRunner(): Promise { - const fileNames = Object.keys(this.fileMap).map((sourceFileName) => this.fileMap[sourceFileName]); - this.log.debug('Creating test runner %s', this.index); - this.testRunner = ResilientTestRunnerFactory.create(this.options, fileNames, this.workingDirectory, this.loggingContext); - await this.testRunner.init(); - } - - private calculateTimeout(mutant: TestableMutant) { - const baseTimeout = mutant.timeSpentScopedTests; - return this.options.timeoutFactor * baseTimeout + this.options.timeoutMS + this.timeOverheadMS; - } - - private getFilterTestsHooks(mutant: TestableMutant): string | undefined { - if (this.testFramework) { - if (mutant.runAllTests) { - return wrapInClosure(this.testFramework.filter([])); - } else { - return wrapInClosure(this.testFramework.filter(mutant.selectedTests)); - } - } else { - return undefined; - } - } -} diff --git a/packages/core/src/SandboxPool.ts b/packages/core/src/SandboxPool.ts deleted file mode 100644 index ae5a48b830..0000000000 --- a/packages/core/src/SandboxPool.ts +++ /dev/null @@ -1,112 +0,0 @@ -import * as os from 'os'; - -import { File, StrykerOptions } from '@stryker-mutator/api/core'; -import { Logger } from '@stryker-mutator/api/logging'; -import { commonTokens, tokens } from '@stryker-mutator/api/plugin'; -import { MutantResult } from '@stryker-mutator/api/report'; -import { TestFramework } from '@stryker-mutator/api/test_framework'; -import { Observable, range, Subject } from 'rxjs'; -import { filter, flatMap, map, merge, tap, zip } from 'rxjs/operators'; -import { Disposable } from 'typed-inject'; - -import { coreTokens } from './di'; -import LoggingClientContext from './logging/LoggingClientContext'; -import { InitialTestRunResult } from './process/InitialTestExecutor'; -import Sandbox from './Sandbox'; -import TranspiledMutant from './TranspiledMutant'; -import { TemporaryDirectory } from './utils/TemporaryDirectory'; - -const MAX_CONCURRENT_INITIALIZING_SANDBOXES = 2; - -export class SandboxPool implements Disposable { - private readonly allSandboxes: Array> = []; - private readonly overheadTimeMS: number; - - public static inject = tokens( - commonTokens.logger, - commonTokens.options, - coreTokens.testFramework, - coreTokens.initialRunResult, - coreTokens.transpiledFiles, - coreTokens.loggingContext, - coreTokens.temporaryDirectory - ); - constructor( - private readonly log: Logger, - private readonly options: StrykerOptions, - private readonly testFramework: TestFramework | null, - initialRunResult: InitialTestRunResult, - private readonly initialFiles: readonly File[], - private readonly loggingContext: LoggingClientContext, - private readonly tempDir: TemporaryDirectory - ) { - this.overheadTimeMS = initialRunResult.overheadTimeMS; - } - - public runMutants(mutants: Observable): Observable { - const recycledSandboxes = new Subject(); - // Make sure sandboxes get recycled - const sandboxes = this.startSandboxes().pipe(merge(recycledSandboxes)); - return mutants.pipe( - zip(sandboxes), - flatMap(this.runInSandbox), - tap(({ sandbox }) => { - recycledSandboxes.next(sandbox); - }), - map(({ result }) => result) - ); - } - - private readonly runInSandbox = async ([mutant, sandbox]: [TranspiledMutant, Sandbox]) => { - const result = await sandbox.runMutant(mutant); - return { result, sandbox }; - }; - - private startSandboxes(): Observable { - const concurrency = this.determineConcurrency(); - - return range(0, concurrency).pipe( - flatMap(async (n) => { - if (this.isDisposed) { - return null; - } else { - return this.registerSandbox( - Sandbox.create(this.options, n, this.initialFiles, this.testFramework, this.overheadTimeMS, this.loggingContext, this.tempDir) - ); - } - }, MAX_CONCURRENT_INITIALIZING_SANDBOXES), - filter((sandboxOrNull) => !!sandboxOrNull), - map((sandbox) => sandbox as Sandbox) - ); - } - - private determineConcurrency() { - let numConcurrentRunners = os.cpus().length; - if (this.options.transpilers.length) { - // If transpilers are configured, one core is reserved for the compiler (for now) - numConcurrentRunners--; - } - let numConcurrentRunnersSource = 'CPU count'; - if (numConcurrentRunners > this.options.maxConcurrentTestRunners && this.options.maxConcurrentTestRunners > 0) { - numConcurrentRunners = this.options.maxConcurrentTestRunners; - numConcurrentRunnersSource = 'maxConcurrentTestRunners config'; - } - if (numConcurrentRunners <= 0) { - numConcurrentRunners = 1; - } - this.log.info(`Creating ${numConcurrentRunners} test runners (based on ${numConcurrentRunnersSource})`); - return numConcurrentRunners; - } - - private readonly registerSandbox = async (promisedSandbox: Promise): Promise => { - this.allSandboxes.push(promisedSandbox); - return promisedSandbox; - }; - - private isDisposed = false; - public async dispose() { - this.isDisposed = true; - const sandboxes = await Promise.all(this.allSandboxes); - await Promise.all(sandboxes.map((sandbox) => sandbox.dispose())); - } -} diff --git a/packages/core/src/SourceFile.ts b/packages/core/src/SourceFile.ts deleted file mode 100644 index cf49c08133..0000000000 --- a/packages/core/src/SourceFile.ts +++ /dev/null @@ -1,128 +0,0 @@ -import { File, Location, Position, Range } from '@stryker-mutator/api/core'; - -const enum CharacterCodes { - MaxAsciiCharacter = 0x7f, - LineFeed = 0x0a, // \n - CarriageReturn = 0x0d, // \r - LineSeparator = 0x2028, - ParagraphSeparator = 0x2029, -} - -export function isLineBreak(ch: number): boolean { - // ES5 7.3: - // The ECMAScript line terminator characters are listed in Table 3. - // Table 3: Line Terminator Characters - // Code Unit Value Name Formal Name - // \u000A Line Feed - // \u000D Carriage Return - // \u2028 Line separator - // \u2029 Paragraph separator - // Only the characters in Table 3 are treated as line terminators. Other new line or line - // breaking characters are treated as white space but not as line terminators. - - return ( - ch === CharacterCodes.LineFeed || - ch === CharacterCodes.CarriageReturn || - ch === CharacterCodes.LineSeparator || - ch === CharacterCodes.ParagraphSeparator - ); -} - -export default class SourceFile { - private readonly lineStarts: number[]; - - constructor(public file: File) { - this.lineStarts = this.computeLineStarts(); - } - - public get name() { - return this.file.name; - } - - public get content(): string { - return this.file.textContent; - } - - public getLocation(range: Range): Location { - return { - end: this.getPosition(range[1]), - start: this.getPosition(range[0]), - }; - } - - public getPosition(pos: number): Position { - let lineNumber = this.binarySearch(pos); - if (lineNumber < 0) { - // If the actual position was not found, - // the binary search returns the 2's-complement of the next line start - // e.g. if the line starts at [5, 10, 23, 80] and the position requested was 20 - // then the search will return -2. - // - // We want the index of the previous line start, so we subtract 1. - // Review 2's-complement if this is confusing. - lineNumber = ~lineNumber - 1; - } - return { - column: pos - this.lineStarts[lineNumber], - line: lineNumber, - }; - } - - /** - * Performs a binary search, finding the index at which 'value' occurs in 'array'. - * If no such index is found, returns the 2's-complement of first index at which - * number[index] exceeds number. - * @param array A sorted array whose first element must be no larger than number - * @param number The value to be searched for in the array. - */ - private binarySearch(position: number, offset = 0): number { - let low = offset; - let high = this.lineStarts.length - 1; - - while (low <= high) { - const middle = low + ((high - low) >> 1); - const midValue = this.lineStarts[middle]; - - if (midValue === position) { - return middle; - } else if (midValue > position) { - high = middle - 1; - } else { - low = middle + 1; - } - } - - return ~low; - } - private computeLineStarts(): number[] { - const result: number[] = []; - let pos = 0; - let lineStart = 0; - const markLineStart = () => { - result.push(lineStart); - lineStart = pos; - }; - while (pos < this.file.textContent.length) { - const ch = this.file.textContent.charCodeAt(pos); - pos++; - switch (ch) { - case CharacterCodes.CarriageReturn: - if (this.file.textContent.charCodeAt(pos) === CharacterCodes.LineFeed) { - pos++; - } - markLineStart(); - break; - case CharacterCodes.LineFeed: - markLineStart(); - break; - default: - if (ch > CharacterCodes.MaxAsciiCharacter && isLineBreak(ch)) { - markLineStart(); - } - break; - } - } - result.push(lineStart); - return result; - } -} diff --git a/packages/core/src/Stryker.ts b/packages/core/src/Stryker.ts index 1d9fc7b180..efdf023106 100644 --- a/packages/core/src/Stryker.ts +++ b/packages/core/src/Stryker.ts @@ -1,119 +1,70 @@ -import { StrykerOptions, PartialStrykerOptions } from '@stryker-mutator/api/core'; -import { Logger } from '@stryker-mutator/api/logging'; -import { commonTokens, PluginKind } from '@stryker-mutator/api/plugin'; +import { PartialStrykerOptions } from '@stryker-mutator/api/core'; import { MutantResult } from '@stryker-mutator/api/report'; -import { Injector } from 'typed-inject'; +import { createInjector } from 'typed-inject'; -import { buildMainInjector, coreTokens, MainContext, PluginCreator } from './di'; -import InputFileCollection from './input/InputFileCollection'; -import InputFileResolver from './input/InputFileResolver'; -import LogConfigurator from './logging/LogConfigurator'; -import { MutantTestMatcher } from './mutants/MutantTestMatcher'; -import { MutatorFacade } from './mutants/MutatorFacade'; -import InitialTestExecutor from './process/InitialTestExecutor'; -import { MutationTestExecutor } from './process/MutationTestExecutor'; -import { MutationTestReportCalculator } from './reporters/MutationTestReportCalculator'; -import { SandboxPool } from './SandboxPool'; -import { transpilerFactory } from './transpiler'; -import { MutantTranspileScheduler } from './transpiler/MutantTranspileScheduler'; -import { TranspilerFacade } from './transpiler/TranspilerFacade'; +import { commonTokens } from '@stryker-mutator/api/plugin'; -export default class Stryker { - private readonly log: Logger; - private readonly injector: Injector; - - private get reporter() { - return this.injector.resolve(coreTokens.reporter); - } - - private get options(): Readonly { - return this.injector.resolve(commonTokens.options); - } - - private get timer() { - return this.injector.resolve(coreTokens.timer); - } - - private get temporaryDirectory() { - return this.injector.resolve(coreTokens.temporaryDirectory); - } +import { LogConfigurator } from './logging'; +import { PrepareExecutor, MutantInstrumenterExecutor, DryRunExecutor, MutationTestExecutor } from './process'; +import { coreTokens, provideLogger } from './di'; +import { retrieveCause, ConfigError } from './errors'; +/** + * The main Stryker class. + * It provides a single `runMutationTest()` function which runs mutation testing: + */ +export default class Stryker { /** - * The Stryker mutation tester. * @constructor - * @param {Object} [cliOptions] - Optional options. + * @param cliOptions The cli options. + * @param injectorFactory The injector factory, for testing purposes only */ - constructor(cliOptions: PartialStrykerOptions) { - LogConfigurator.configureMainProcess(cliOptions.logLevel, cliOptions.fileLogLevel, cliOptions.allowConsoleColors); - this.injector = buildMainInjector(cliOptions); - this.log = this.injector.resolve(commonTokens.getLogger)(Stryker.name); - // Log level may have changed - LogConfigurator.configureMainProcess(this.options.logLevel, this.options.fileLogLevel, this.options.allowConsoleColors); - } + constructor(private readonly cliOptions: PartialStrykerOptions, private readonly injectorFactory = createInjector) {} public async runMutationTest(): Promise { - const loggingContext = await LogConfigurator.configureLoggingServer( - this.options.logLevel, - this.options.fileLogLevel, - this.options.allowConsoleColors - ); - this.timer.reset(); - const inputFiles = await this.injector.injectClass(InputFileResolver).resolve(); - if (inputFiles.files.length) { - this.temporaryDirectory.initialize(); - const inputFileInjector = this.injector.provideValue(coreTokens.loggingContext, loggingContext).provideValue(coreTokens.inputFiles, inputFiles); - const initialTestRunProcess = inputFileInjector - .provideValue(commonTokens.produceSourceMaps, this.options.coverageAnalysis !== 'off') - .provideFactory(coreTokens.pluginCreatorTranspiler, PluginCreator.createFactory(PluginKind.Transpiler)) - .provideClass(coreTokens.transpiler, TranspilerFacade) - .injectClass(InitialTestExecutor); - const initialRunResult = await initialTestRunProcess.run(); - const mutator = inputFileInjector.injectClass(MutatorFacade); - const transpilerProvider = inputFileInjector - .provideValue(coreTokens.initialRunResult, initialRunResult) - .provideValue(commonTokens.produceSourceMaps, false) - .provideFactory(coreTokens.transpiler, transpilerFactory); - const transpiler = transpilerProvider.resolve(coreTokens.transpiler); - const transpiledFiles = await transpiler.transpile(inputFiles.files); - const mutationTestProcessInjector = transpilerProvider - .provideValue(coreTokens.transpiledFiles, transpiledFiles) - .provideClass(coreTokens.mutantTranspileScheduler, MutantTranspileScheduler) - .provideClass(coreTokens.sandboxPool, SandboxPool); - const testableMutants = await mutationTestProcessInjector - .injectClass(MutantTestMatcher) - .matchWithMutants(mutator.mutate(inputFiles.filesToMutate)); + const rootInjector = this.injectorFactory(); + const loggerProvider = provideLogger(rootInjector); + + try { + // 1. Prepare. Load Stryker configuration, load the input files and starts the logging server + const prepareExecutor = loggerProvider.provideValue(coreTokens.cliOptions, this.cliOptions).injectClass(PrepareExecutor); + const mutantInstrumenterInjector = await prepareExecutor.execute(); + try { - if (initialRunResult.runResult.tests.length && testableMutants.length) { - const mutationTestExecutor = mutationTestProcessInjector.injectClass(MutationTestExecutor); - const mutantResults = await mutationTestExecutor.run(testableMutants); - await this.reportResult(mutantResults, inputFileInjector); - this.logDone(); - return mutantResults; - } else { - this.logTraceLogLevelHint(); - } - } finally { - // `injector.dispose` calls `dispose` on all created instances - // Namely the `SandboxPool`, `MutantTranspileScheduler` and `ChildProcessProxy` instances - await mutationTestProcessInjector.dispose(); - await LogConfigurator.shutdown(); - } - } - return Promise.resolve([]); - } + // 2. Mutate and instrument the files and write to the sandbox. + const mutantInstrumenter = mutantInstrumenterInjector.injectClass(MutantInstrumenterExecutor); + const dryRunExecutorInjector = await mutantInstrumenter.execute(); - private logDone() { - this.log.info('Done in %s.', this.timer.humanReadableElapsed()); - } + // 3. Perform a 'dry run' (initial test run). Runs the tests without active mutants and collects coverage. + const dryRunExecutor = dryRunExecutorInjector.injectClass(DryRunExecutor); + const mutationRunExecutorInjector = await dryRunExecutor.execute(); - private logTraceLogLevelHint() { - if (!this.log.isTraceEnabled()) { - this.log.info('Trouble figuring out what went wrong? Try `npx stryker run --fileLogLevel trace --logLevel debug` to get some more info.'); - } - } + // 4. Actual mutation testing. Will check every mutant and if valid run it in an available test runner. + const mutationRunExecutor = mutationRunExecutorInjector.injectClass(MutationTestExecutor); + const mutantResults = await mutationRunExecutor.execute(); - private async reportResult(mutantResults: MutantResult[], inputFileInjector: Injector) { - inputFileInjector.injectClass(MutationTestReportCalculator).report(mutantResults); - await this.reporter.wrapUp(); + return mutantResults; + } catch (error) { + const log = loggerProvider.resolve(commonTokens.getLogger)(Stryker.name); + log.debug('Not removing the temp dir because an error occurred'); + mutantInstrumenterInjector.resolve(coreTokens.temporaryDirectory).removeDuringDisposal = false; + throw error; + } + } catch (error) { + const log = loggerProvider.resolve(commonTokens.getLogger)(Stryker.name); + const cause = retrieveCause(error); + if (cause instanceof ConfigError) { + log.error(cause.message); + } else { + log.error(error); + if (!log.isTraceEnabled()) { + log.info('Trouble figuring out what went wrong? Try `npx stryker run --fileLogLevel trace --logLevel debug` to get some more info.'); + } + } + throw cause; + } finally { + await rootInjector.dispose(); + await LogConfigurator.shutdown(); + } } } diff --git a/packages/core/src/StrykerCli.ts b/packages/core/src/StrykerCli.ts index 3511442117..32639c5232 100644 --- a/packages/core/src/StrykerCli.ts +++ b/packages/core/src/StrykerCli.ts @@ -1,13 +1,12 @@ import * as commander from 'commander'; -import { getLogger } from 'log4js'; import { DashboardOptions, ALL_REPORT_TYPES, PartialStrykerOptions } from '@stryker-mutator/api/core'; -import { Logger } from '@stryker-mutator/api/logging'; + +import { MutantResult } from '@stryker-mutator/api/report'; import { initializerFactory } from './initializer'; -import LogConfigurator from './logging/LogConfigurator'; +import { LogConfigurator } from './logging'; import Stryker from './Stryker'; import { defaultOptions } from './config/OptionsValidator'; -import { retrieveCause, ConfigError } from './errors'; /** * Interpret a command line argument and add it to an object. @@ -31,14 +30,13 @@ function parseBoolean(val: string) { } export default class StrykerCli { - private command: string = ''; + private command = ''; private strykerConfig: string | null = null; constructor( private readonly argv: string[], private readonly program: commander.Command = new commander.Command(), - private readonly runMutationTest = async (options: PartialStrykerOptions) => new Stryker(options).runMutationTest(), - private readonly log: Logger = getLogger(StrykerCli.name) + private readonly runMutationTest = async (options: PartialStrykerOptions) => new Stryker(options).runMutationTest() ) {} public run() { @@ -61,29 +59,44 @@ export default class StrykerCli { }) .option( '-f, --files ', - `A comma separated list of globbing expression used for selecting all files needed to run the tests. For a more detailed way of selecting input files, please use a configFile. - Example: node_modules/a-lib/**/*.js,src/**/*.js,!src/index.js,a.js,test/**/*.js`, + 'A comma separated list of globbing expression used for selecting all files needed to run the tests. For a more detailed way of selecting input files, please use a configFile. Example: node_modules/a-lib/**/*.js,src/**/*.js,!src/index.js,a.js,test/**/*.js', list ) .option( '-m, --mutate ', - `A comma separated list of globbing expression used for selecting the files that should be mutated. - Example: src/**/*.js,a.js`, + 'A comma separated list of globbing expression used for selecting the files that should be mutated. Example: src/**/*.js,a.js', list ) + .option( + '-b, --buildCommand ', + 'Configure a build command to run after mutating the code, but before mutants are tested. This is generally used to transpile your code before testing.' + + " Only configure this if your test runner doesn't take care of this already and you're not using just-in-time transpiler like `babel/register` or `ts-node`." + ) .option( '--coverageAnalysis ', `The coverage analysis strategy you want to use. Default value: "${defaultValues.coverageAnalysis}"` ) - .option('--testFramework ', 'The name of the test framework you want to use.') .option('--testRunner ', 'The name of the test runner you want to use') - .option('--mutator ', 'The name of the mutant generator you want to use') - .option('--transpilers ', 'A comma separated list of transpilers to use.', list) .option('--reporters ', 'A comma separated list of the names of the reporter(s) you want to use', list) .option('--plugins ', 'A list of plugins you want stryker to load (`require`).', list) + .option( + '--appendPlugins ', + 'A list of additional plugins you want Stryker to load (`require`) without overwriting the (default) `plugins`.', + list + ) .option('--timeoutMS ', 'Tweak the absolute timeout used to wait for a test runner to complete', parseInt) .option('--timeoutFactor ', 'Tweak the standard deviation relative to the normal test run of a mutated test', parseFloat) .option('--maxConcurrentTestRunners ', 'Set the number of max concurrent test runner to spawn (default: cpuCount)', parseInt) + .option( + '-c, --concurrency ', + 'Set the concurrency of workers. Stryker will always run checkers and test runners in parallel by creating worker processes (default: cpuCount - 1)', + parseInt + ) + .option( + '--maxTestRunnerReuse ', + 'Restart each forked threads after runs. Not recommended unless you are experiencing memory leaks that you are unable to resolve. (default: 0)', + parseInt + ) .option( '--logLevel ', `Set the log level for the console. Possible values: fatal, error, warn, info, debug, trace, all and off. Default is "${defaultValues.logLevel}"` @@ -122,6 +135,11 @@ export default class StrykerCli { '--tempDirName ', 'Set the name of the directory that is used by Stryker as a working directory. This directory will be cleaned after a successful run' ) + .option( + '--cleanTempDir ', + 'Choose whether or not to clean the temp dir (which is ".stryker-tmp" inside the current working directory by default) after a successful run. The temp dir will never be removed when the run failed for some reason (for debugging purposes).', + parseBoolean + ) .parse(this.argv); // Earliest opportunity to configure the log level based on the logLevel argument @@ -141,26 +159,18 @@ export default class StrykerCli { options.dashboard = dashboard; } - const commands: { [cmd: string]: () => Promise } = { + const commands = { init: () => initializerFactory().initialize(), run: () => this.runMutationTest(options), }; if (Object.keys(commands).includes(this.command)) { - commands[this.command]().catch((err) => { - const error = retrieveCause(err); - if (error instanceof ConfigError) { - this.log.error(error.message); - } else { - this.log.error('an error occurred', err); - if (!this.log.isTraceEnabled()) { - this.log.info('Trouble figuring out what went wrong? Try `npx stryker run --fileLogLevel trace --logLevel debug` to get some more info.'); - } - } + const promise: Promise = commands[this.command as keyof typeof commands](); + promise.catch((err) => { process.exitCode = 1; }); } else { - this.log.error('Unknown command: "%s", supported commands: [%s], or use `stryker --help`.', this.command, Object.keys(commands)); + console.error('Unknown command: "%s", supported commands: [%s], or use `stryker --help`.', this.command, Object.keys(commands)); } } } diff --git a/packages/core/src/TestFrameworkOrchestrator.ts b/packages/core/src/TestFrameworkOrchestrator.ts deleted file mode 100644 index e56ebf8be1..0000000000 --- a/packages/core/src/TestFrameworkOrchestrator.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { StrykerOptions } from '@stryker-mutator/api/core'; -import { Logger } from '@stryker-mutator/api/logging'; -import { commonTokens, PluginKind, tokens } from '@stryker-mutator/api/plugin'; -import { TestFramework } from '@stryker-mutator/api/test_framework'; - -import { coreTokens } from './di'; -import { PluginCreator } from './di/PluginCreator'; - -export default class TestFrameworkOrchestrator { - public static inject = tokens(commonTokens.logger, commonTokens.options, coreTokens.pluginCreatorTestFramework); - constructor( - private readonly log: Logger, - private readonly options: StrykerOptions, - private readonly pluginCreator: PluginCreator - ) {} - - public determineTestFramework(): TestFramework | null { - if (this.options.coverageAnalysis !== 'perTest') { - this.log.debug( - 'The `coverageAnalysis` setting is "%s", not hooking into the test framework to achieve performance benefits.', - this.options.coverageAnalysis - ); - return null; - } else { - return this.determineFrameworkWithCoverageAnalysis(); - } - } - - private determineFrameworkWithCoverageAnalysis(): TestFramework | null { - let testFramework: TestFramework | null = null; - if (this.options.testFramework) { - try { - testFramework = this.pluginCreator.create(this.options.testFramework); - this.log.debug(`Using testFramework ${this.options.testFramework} based on \`testFramework\` setting`); - } catch (error) { - this.log.warn(`Could not create test framework \`${this.options.testFramework}\``, error); - } - } else { - this.log.warn('Missing config settings `testFramework`. Set `coverageAnalysis` option explicitly to "off" to ignore this warning.'); - } - return testFramework; - } -} diff --git a/packages/core/src/TestableMutant.ts b/packages/core/src/TestableMutant.ts deleted file mode 100644 index ed3f102c5a..0000000000 --- a/packages/core/src/TestableMutant.ts +++ /dev/null @@ -1,137 +0,0 @@ -import { Location } from '@stryker-mutator/api/core'; -import { Mutant } from '@stryker-mutator/api/mutant'; -import { MutantResult, MutantStatus } from '@stryker-mutator/api/report'; -import { TestSelection } from '@stryker-mutator/api/test_framework'; -import { RunResult, TestResult } from '@stryker-mutator/api/test_runner'; -import { deepFreeze } from '@stryker-mutator/util'; - -import SourceFile, { isLineBreak } from './SourceFile'; - -export enum TestSelectionResult { - Failed, - FailedButAlreadyReported, - Success, -} - -class TestFilter { - public timeSpentScopedTests = 0; - public runAllTests = false; - public selectedTests: TestSelection[] = []; - - public selectAllTests(runResult: RunResult) { - this.timeSpentScopedTests = runResult.tests.reduce((time, test) => time + test.timeSpentMs, this.timeSpentScopedTests); - this.runAllTests = true; - } - - public selectTest(testResult: TestResult, index: number) { - this.selectedTests.push({ id: index, name: testResult.name }); - this.timeSpentScopedTests += testResult.timeSpentMs; - this.runAllTests = false; - } -} - -export default class TestableMutant { - public specsRan: string[] = []; - private readonly filter = new TestFilter(); - private _location: Location; - public testSelectionResult = TestSelectionResult.Success; - - public get selectedTests(): TestSelection[] { - return this.filter.selectedTests; - } - - public get runAllTests(): boolean { - return this.filter.runAllTests; - } - - public get timeSpentScopedTests() { - return this.filter.timeSpentScopedTests; - } - - public get fileName() { - return this.mutant.fileName; - } - - public get mutatorName() { - return this.mutant.mutatorName; - } - - public get range() { - return this.mutant.range; - } - - public get replacement() { - return this.mutant.replacement; - } - - public get location() { - if (!this._location) { - this._location = this.sourceFile.getLocation(this.range); - } - return this._location; - } - - public get mutatedCode() { - return this.sourceFile.content.substr(0, this.range[0]) + this.replacement + this.sourceFile.content.substr(this.range[1]); - } - - public get originalCode() { - return this.sourceFile.content; - } - - public selectAllTests(runResult: RunResult, testSelectionResult: TestSelectionResult) { - this.filter.selectAllTests(runResult); - this.testSelectionResult = testSelectionResult; - } - - public selectTest(testResult: TestResult, index: number) { - this.filter.selectTest(testResult, index); - } - - constructor(public readonly id: string, public mutant: Mutant, public sourceFile: SourceFile) {} - - public get originalLines() { - const [startIndex, endIndex] = this.getMutationLineIndexes(); - return this.sourceFile.content.substring(startIndex, endIndex); - } - - public get mutatedLines() { - const [startIndex, endIndex] = this.getMutationLineIndexes(); - return ( - this.sourceFile.content.substring(startIndex, this.mutant.range[0]) + - this.mutant.replacement + - this.sourceFile.content.substring(this.mutant.range[1], endIndex) - ); - } - - private getMutationLineIndexes() { - let startIndexLines = this.mutant.range[0]; - let endIndexLines = this.mutant.range[1]; - while (startIndexLines > 0 && !isLineBreak(this.originalCode.charCodeAt(startIndexLines - 1))) { - startIndexLines--; - } - while (endIndexLines < this.sourceFile.content.length && !isLineBreak(this.originalCode.charCodeAt(endIndexLines))) { - endIndexLines++; - } - return [startIndexLines, endIndexLines]; - } - - public createResult(status: MutantStatus, testsRan: string[]): MutantResult { - return deepFreeze({ - id: this.id, - location: this.location, - mutatedLines: this.mutatedLines, - mutatorName: this.mutatorName, - originalLines: this.originalLines, - range: this.range, - replacement: this.replacement, - sourceFilePath: this.fileName, - status, - testsRan, - }) as MutantResult; - } - - public toString() { - return `${this.mutant.mutatorName}: (${this.replacement}) file://${this.fileName}:${this.location.start.line + 1}:${this.location.start.column}`; - } -} diff --git a/packages/core/src/TranspiledMutant.ts b/packages/core/src/TranspiledMutant.ts deleted file mode 100644 index 7e8a86a4cc..0000000000 --- a/packages/core/src/TranspiledMutant.ts +++ /dev/null @@ -1,12 +0,0 @@ -import TestableMutant from './TestableMutant'; -import TranspileResult from './transpiler/TranspileResult'; - -export default class TranspiledMutant { - /** - * Creates a transpiled mutant - * @param mutant The mutant which is just transpiled - * @param transpileResult The transpile result of the mutant - * @param changedAnyTranspiledFiles Indicated whether or not this mutant changed the transpiled output files. This is not always the case, for example: mutating a TS interface - */ - constructor(public mutant: TestableMutant, public transpileResult: TranspileResult, public changedAnyTranspiledFiles: boolean) {} -} diff --git a/packages/core/src/checker/CheckerFacade.ts b/packages/core/src/checker/CheckerFacade.ts new file mode 100644 index 0000000000..5f5956dc37 --- /dev/null +++ b/packages/core/src/checker/CheckerFacade.ts @@ -0,0 +1,56 @@ +import { Checker, CheckResult, CheckStatus } from '@stryker-mutator/api/check'; +import { Mutant, StrykerOptions } from '@stryker-mutator/api/core'; + +import { tokens, Disposable } from 'typed-inject'; +import { commonTokens } from '@stryker-mutator/api/plugin'; + +import ChildProcessProxy from '../child-proxy/ChildProcessProxy'; +import { LoggingClientContext } from '../logging'; +import { coreTokens } from '../di'; + +import { Worker } from '../concurrent/pool'; + +import { CheckerWorker } from './CheckerWorker'; + +createCheckerFactory.inject = tokens(commonTokens.options, coreTokens.loggingContext); +export function createCheckerFactory(options: StrykerOptions, loggingContext: LoggingClientContext): () => Checker { + return () => new CheckerFacade(options, loggingContext); +} + +export class CheckerFacade implements Checker, Disposable, Worker { + private readonly childProcess?: ChildProcessProxy; + + constructor(options: StrykerOptions, loggingContext: LoggingClientContext) { + if (options.checkers.length) { + this.childProcess = ChildProcessProxy.create( + require.resolve(`./${CheckerWorker.name}`), + loggingContext, + options, + {}, + process.cwd(), + CheckerWorker + ); + } + } + + public async dispose() { + if (this.childProcess) { + await this.childProcess.dispose(); + } + } + + public async init(): Promise { + if (this.childProcess) { + return this.childProcess.proxy.init(); + } + } + + public async check(mutant: Mutant): Promise { + if (this.childProcess) { + return this.childProcess.proxy.check(mutant); + } + return { + status: CheckStatus.Passed, + }; + } +} diff --git a/packages/core/src/checker/CheckerWorker.ts b/packages/core/src/checker/CheckerWorker.ts new file mode 100644 index 0000000000..dab895c8e9 --- /dev/null +++ b/packages/core/src/checker/CheckerWorker.ts @@ -0,0 +1,36 @@ +import { Checker, CheckResult, CheckStatus } from '@stryker-mutator/api/check'; +import { StrykerOptions, Mutant } from '@stryker-mutator/api/core'; + +import { PluginKind, tokens, commonTokens, PluginContext, Injector } from '@stryker-mutator/api/plugin'; + +import { StrykerError } from '@stryker-mutator/util'; + +import { PluginCreator } from '../di'; + +export class CheckerWorker implements Checker { + private readonly innerCheckers: Array<{ name: string; checker: Checker }> = []; + + public static inject = tokens(commonTokens.options, commonTokens.injector); + constructor(options: StrykerOptions, injector: Injector) { + const pluginCreator = injector.injectFunction(PluginCreator.createFactory(PluginKind.Checker)); + this.innerCheckers = options.checkers.map((name) => ({ name, checker: pluginCreator.create(name) })); + } + public async init(): Promise { + for await (const { name, checker } of this.innerCheckers) { + try { + await checker.init(); + } catch (error) { + throw new StrykerError(`An error occurred during initialization of the "${name}" checker`, error); + } + } + } + public async check(mutant: Mutant): Promise { + for await (const { checker } of this.innerCheckers) { + const result = await checker.check(mutant); + if (result.status !== CheckStatus.Passed) { + return result; + } + } + return { status: CheckStatus.Passed }; + } +} diff --git a/packages/core/src/child-proxy/ChildProcessProxy.ts b/packages/core/src/child-proxy/ChildProcessProxy.ts index 096906d7fd..e22453616e 100644 --- a/packages/core/src/child-proxy/ChildProcessProxy.ts +++ b/packages/core/src/child-proxy/ChildProcessProxy.ts @@ -2,15 +2,14 @@ import { ChildProcess, fork } from 'child_process'; import * as os from 'os'; import { File, StrykerOptions } from '@stryker-mutator/api/core'; -import { OptionsContext } from '@stryker-mutator/api/plugin'; -import { isErrnoException } from '@stryker-mutator/util'; +import { PluginContext } from '@stryker-mutator/api/plugin'; +import { isErrnoException, Task, ExpirableTask } from '@stryker-mutator/util'; import { getLogger } from 'log4js'; import { Disposable, InjectableClass, InjectionToken } from 'typed-inject'; -import LoggingClientContext from '../logging/LoggingClientContext'; +import { LoggingClientContext } from '../logging'; import { deserialize, kill, padLeft, serialize } from '../utils/objectUtils'; import StringBuilder from '../utils/StringBuilder'; -import { ExpirableTask, Task } from '../utils/Task'; import ChildProcessCrashedError from './ChildProcessCrashedError'; import { autoStart, ParentMessage, ParentMessageKind, WorkerMessage, WorkerMessageKind } from './messageProtocol'; @@ -72,15 +71,15 @@ export default class ChildProcessProxy implements Disposable { /** * @description Creates a proxy where each function of the object created using the constructorFunction arg is ran inside of a child process */ - public static create>>( + public static create>>( requirePath: string, loggingContext: LoggingClientContext, options: StrykerOptions, additionalInjectableValues: TAdditionalContext, workingDirectory: string, - InjectableClass: InjectableClass + injectableClass: InjectableClass ): ChildProcessProxy { - return new ChildProcessProxy(requirePath, InjectableClass.name, loggingContext, options, additionalInjectableValues, workingDirectory); + return new ChildProcessProxy(requirePath, injectableClass.name, loggingContext, options, additionalInjectableValues, workingDirectory); } private send(message: WorkerMessage) { @@ -103,7 +102,7 @@ export default class ChildProcessProxy implements Disposable { } private forward(methodName: string) { - return (...args: any[]) => { + return async (...args: any[]) => { if (this.currentError) { return Promise.reject(this.currentError); } else { @@ -178,7 +177,6 @@ export default class ChildProcessProxy implements Disposable { private readonly handleUnexpectedExit = (code: number, signal: string) => { this.isDisposed = true; const output = StringBuilder.concat(this.stderrBuilder, this.stdoutBuilder); - if (processOutOfMemory()) { this.currentError = new OutOfMemoryError(this.worker.pid, code); this.log.warn(`Child process [pid ${this.currentError.pid}] ran out of memory. Stdout and stderr are logged on debug level.`); diff --git a/packages/core/src/child-proxy/ChildProcessProxyWorker.ts b/packages/core/src/child-proxy/ChildProcessProxyWorker.ts index d3d13a8fca..32a8988f68 100644 --- a/packages/core/src/child-proxy/ChildProcessProxyWorker.ts +++ b/packages/core/src/child-proxy/ChildProcessProxyWorker.ts @@ -5,10 +5,10 @@ import { errorToString } from '@stryker-mutator/util'; import { getLogger, Logger } from 'log4js'; import { buildChildProcessInjector } from '../di'; -import LogConfigurator from '../logging/LogConfigurator'; +import { LogConfigurator } from '../logging'; import { deserialize, serialize } from '../utils/objectUtils'; -import { autoStart, CallMessage, ParentMessage, ParentMessageKind, WorkerMessage, WorkerMessageKind } from './messageProtocol'; +import { autoStart, CallMessage, ParentMessage, ParentMessageKind, WorkerMessage, WorkerMessageKind, InitMessage } from './messageProtocol'; export default class ChildProcessProxyWorker { private log: Logger; @@ -31,40 +31,11 @@ export default class ChildProcessProxyWorker { const message = deserialize(serializedMessage, [File]); switch (message.kind) { case WorkerMessageKind.Init: - LogConfigurator.configureChildProcess(message.loggingContext); - this.log = getLogger(ChildProcessProxyWorker.name); - this.handlePromiseRejections(); - let injector = buildChildProcessInjector(message.options); - const locals = message.additionalInjectableValues as any; - for (const token of Object.keys(locals)) { - injector = injector.provideValue(token, locals[token]); - } - const RealSubjectClass = require(message.requirePath)[message.requireName]; - const workingDir = path.resolve(message.workingDirectory); - if (process.cwd() !== workingDir) { - this.log.debug(`Changing current working directory for this process to ${workingDir}`); - process.chdir(workingDir); - } - this.realSubject = injector.injectClass(RealSubjectClass); - this.send({ kind: ParentMessageKind.Initialized }); + this.handleInit(message); this.removeAnyAdditionalMessageListeners(this.handleMessage); break; case WorkerMessageKind.Call: - new Promise((resolve) => resolve(this.doCall(message))) - .then((result) => { - this.send({ - correlationId: message.correlationId, - kind: ParentMessageKind.Result, - result, - }); - }) - .catch((error) => { - this.send({ - correlationId: message.correlationId, - error: errorToString(error), - kind: ParentMessageKind.Rejection, - }); - }); + this.handleCall(message); this.removeAnyAdditionalMessageListeners(this.handleMessage); break; case WorkerMessageKind.Dispose: @@ -76,7 +47,43 @@ export default class ChildProcessProxyWorker { } } - private doCall(message: CallMessage): {} | PromiseLike<{}> | undefined { + private handleInit(message: InitMessage) { + LogConfigurator.configureChildProcess(message.loggingContext); + this.log = getLogger(ChildProcessProxyWorker.name); + this.handlePromiseRejections(); + let injector = buildChildProcessInjector(message.options); + const locals = message.additionalInjectableValues as Record; + for (const token in locals) { + injector = injector.provideValue(token, locals[token]); + } + const RealSubjectClass = require(message.requirePath)[message.requireName]; + const workingDir = path.resolve(message.workingDirectory); + if (process.cwd() !== workingDir) { + this.log.debug(`Changing current working directory for this process to ${workingDir}`); + process.chdir(workingDir); + } + this.realSubject = injector.injectClass(RealSubjectClass); + this.send({ kind: ParentMessageKind.Initialized }); + } + + private async handleCall(message: CallMessage) { + try { + const result = await this.doCall(message); + this.send({ + correlationId: message.correlationId, + kind: ParentMessageKind.Result, + result, + }); + } catch (err) { + this.send({ + correlationId: message.correlationId, + error: errorToString(err), + kind: ParentMessageKind.Rejection, + }); + } + } + + private doCall(message: CallMessage): Record | PromiseLike> | undefined { if (typeof this.realSubject[message.methodName] === 'function') { return this.realSubject[message.methodName](...message.args); } else { diff --git a/packages/core/src/child-proxy/messageProtocol.ts b/packages/core/src/child-proxy/messageProtocol.ts index ae51f5d503..b56b14343d 100644 --- a/packages/core/src/child-proxy/messageProtocol.ts +++ b/packages/core/src/child-proxy/messageProtocol.ts @@ -1,6 +1,6 @@ import { StrykerOptions } from '@stryker-mutator/api/core'; -import LoggingClientContext from '../logging/LoggingClientContext'; +import { LoggingClientContext } from '../logging'; export enum WorkerMessageKind { 'Init', diff --git a/packages/core/src/concurrent/concurrency-token-provider.ts b/packages/core/src/concurrent/concurrency-token-provider.ts new file mode 100644 index 0000000000..c7f239ee37 --- /dev/null +++ b/packages/core/src/concurrent/concurrency-token-provider.ts @@ -0,0 +1,54 @@ +import os = require('os'); + +import { StrykerOptions } from '@stryker-mutator/api/core'; +import { ReplaySubject, Observable, range } from 'rxjs'; +import { Disposable, tokens } from 'typed-inject'; +import { commonTokens } from '@stryker-mutator/api/plugin'; +import { Logger } from '@stryker-mutator/api/logging'; + +export class ConcurrencyTokenProvider implements Disposable { + private readonly concurrencyCheckers: number; + private readonly concurrencyTestRunners: number; + private readonly testRunnerTokenSubject: ReplaySubject = new ReplaySubject(); + + public get testRunnerToken$(): Observable { + return this.testRunnerTokenSubject; + } + public readonly checkerToken$: Observable; + public static readonly inject = tokens(commonTokens.options, commonTokens.logger); + + constructor(options: Pick, private readonly log: Logger) { + const concurrency = options.concurrency ?? os.cpus().length - 1; + if (options.checkers.length > 0) { + this.concurrencyCheckers = Math.max(Math.ceil(concurrency / 2), 1); + this.checkerToken$ = range(this.concurrencyCheckers); + this.concurrencyTestRunners = Math.max(Math.floor(concurrency / 2), 1); + log.info('Creating %s checker process(es) and %s test runner process(es).', this.concurrencyCheckers, this.concurrencyTestRunners); + } else { + this.concurrencyCheckers = 0; + this.checkerToken$ = range(1); // at least one checker, the `CheckerFacade` will not create worker process. + this.concurrencyTestRunners = concurrency; + log.info('Creating %s test runner process(es).', this.concurrencyTestRunners); + } + Array.from({ length: this.concurrencyTestRunners }).forEach(() => this.testRunnerTokenSubject.next(this.tick())); + } + + public freeCheckers() { + if (this.concurrencyCheckers > 0) { + this.log.debug('Checking done, creating %s additional test runner process(es)', this.concurrencyCheckers); + for (let i = 0; i < this.concurrencyCheckers; i++) { + this.testRunnerTokenSubject.next(this.tick()); + } + this.testRunnerTokenSubject.complete(); + } + } + + private count = 0; + private tick() { + return this.count++; + } + + public dispose(): void { + this.testRunnerTokenSubject.complete(); + } +} diff --git a/packages/core/src/concurrent/index.ts b/packages/core/src/concurrent/index.ts new file mode 100644 index 0000000000..ac05227e3e --- /dev/null +++ b/packages/core/src/concurrent/index.ts @@ -0,0 +1,2 @@ +export * from './pool'; +export * from './concurrency-token-provider'; diff --git a/packages/core/src/concurrent/pool.ts b/packages/core/src/concurrent/pool.ts new file mode 100644 index 0000000000..86364bc37b --- /dev/null +++ b/packages/core/src/concurrent/pool.ts @@ -0,0 +1,87 @@ +import { Observable, Subject, merge } from 'rxjs'; +import { flatMap, filter, shareReplay } from 'rxjs/operators'; +import { notEmpty } from '@stryker-mutator/util'; +import { Disposable, tokens } from 'typed-inject'; +import { TestRunner } from '@stryker-mutator/api/test_runner'; +import { Checker } from '@stryker-mutator/api/check'; + +import { coreTokens } from '../di'; + +const MAX_CONCURRENT_INIT = 2; + +export interface Worker { + init?(): Promise; + dispose?(): Promise; +} + +createTestRunnerPool.inject = tokens(coreTokens.testRunnerFactory, coreTokens.testRunnerConcurrencyTokens); +export function createTestRunnerPool(factory: () => TestRunner, concurrencyToken$: Observable): Pool { + return new Pool(factory, concurrencyToken$); +} + +createCheckerPool.inject = tokens(coreTokens.checkerFactory, coreTokens.checkerConcurrencyTokens); +export function createCheckerPool(factory: () => Checker, concurrencyToken$: Observable): Pool { + return new Pool(factory, concurrencyToken$); +} + +/** + * Represents a pool of workers. + * Creates as many workers as the concurrency tokens allow. + * Also takes care of the initialing of the workers (with `init()`) + * Re-emit a worker via `recycle`. + * + * Please recycle! 🚮 + */ +export class Pool implements Disposable { + private readonly recycleBin = new Subject(); + private readonly allWorkers: T[] = []; + public readonly worker$: Observable; + private readonly createdWorker$: Observable; + + constructor(factory: () => T, concurrencyToken$: Observable) { + this.createdWorker$ = concurrencyToken$.pipe( + flatMap(async () => { + if (this.isDisposed) { + return null; + } else { + const worker = factory(); + this.allWorkers.push(worker); + await worker.init?.(); + return worker; + } + }, MAX_CONCURRENT_INIT), + filter(notEmpty), + // We use share replay here. This way the dry run can use a test runner that is later reused during mutation testing + // https://www.learnrxjs.io/learn-rxjs/operators/multicasting/sharereplay + shareReplay() + ); + this.worker$ = merge(this.recycleBin, this.createdWorker$); + } + + /** + * Returns a promise that resolves if all concurrency tokens have resulted in initialized workers. + * This is optional, workers will get initialized either way. + */ + public async init(): Promise { + await this.createdWorker$.toPromise(); + } + + /** + * Recycles a worker so its re-emitted from the `worker$` observable. + * @param worker The worker to recycle + */ + public recycle(worker: T) { + this.recycleBin.next(worker); + } + + private isDisposed = false; + + /** + * Dispose the pool + */ + public async dispose(): Promise { + this.isDisposed = true; + this.recycleBin.complete(); + await Promise.all(this.allWorkers.map((worker) => worker.dispose?.())); + } +} diff --git a/packages/core/src/config/ConfigReader.ts b/packages/core/src/config/ConfigReader.ts index da4c40439f..18a0ca3211 100644 --- a/packages/core/src/config/ConfigReader.ts +++ b/packages/core/src/config/ConfigReader.ts @@ -30,6 +30,9 @@ export default class ConfigReader { const configModule = this.loadConfigModule(); let options: StrykerOptions; if (typeof configModule === 'function') { + this.log.warn( + 'Usage of `module.export = function(config) {}` is deprecated. Please use `module.export = {}` or a "stryker.conf.json" file. For more details, see https://stryker-mutator.io/blog/2020-03-11/stryker-version-3#new-config-format' + ); options = defaultOptions(); configModule(createConfig(options)); } else { @@ -44,8 +47,8 @@ export default class ConfigReader { return options; } - private loadConfigModule(): Function | PartialStrykerOptions { - let configModule: Function | PartialStrykerOptions = {}; + private loadConfigModule(): ((options: StrykerOptions) => void) | PartialStrykerOptions { + let configModule: PartialStrykerOptions | ((config: StrykerOptions) => void) = {}; if (!this.cliOptions.configFile) { try { diff --git a/packages/core/src/config/OptionsEditorApplier.ts b/packages/core/src/config/OptionsEditorApplier.ts deleted file mode 100644 index 926eb542e6..0000000000 --- a/packages/core/src/config/OptionsEditorApplier.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { commonTokens, PluginKind, PluginResolver } from '@stryker-mutator/api/plugin'; -import { tokens } from 'typed-inject'; -import { StrykerOptions } from '@stryker-mutator/api/core'; -import { OptionsEditor } from '@stryker-mutator/api/src/core/OptionsEditor'; - -import { coreTokens } from '../di'; -import { PluginCreator } from '../di/PluginCreator'; - -import { createConfig } from './createConfig'; - -/** - * Class that applies all config editor plugins - */ -export class OptionsEditorApplier implements OptionsEditor { - public static inject = tokens(commonTokens.pluginResolver, coreTokens.pluginCreatorConfigEditor, coreTokens.pluginCreatorOptionsEditor); - - constructor( - private readonly pluginResolver: PluginResolver, - private readonly configEditorPluginCreator: PluginCreator, - private readonly optionsEditorPluginCreator: PluginCreator - ) {} - - public edit(options: StrykerOptions): void { - this.pluginResolver.resolveAll(PluginKind.OptionsEditor).map((plugin) => { - const optionsEditor = this.optionsEditorPluginCreator.create(plugin.name); - optionsEditor.edit(options); - }); - - // Deprecated "config editors" - const configEditors = this.pluginResolver.resolveAll(PluginKind.ConfigEditor); - if (configEditors.length) { - const config = createConfig(options); - configEditors.forEach((plugin) => { - const configEditor = this.configEditorPluginCreator.create(plugin.name); - configEditor.edit(config); - }); - } - } -} diff --git a/packages/core/src/config/OptionsValidator.ts b/packages/core/src/config/OptionsValidator.ts index a8e9e7d063..cddec14c41 100644 --- a/packages/core/src/config/OptionsValidator.ts +++ b/packages/core/src/config/OptionsValidator.ts @@ -1,8 +1,11 @@ +import os = require('os'); + import Ajv = require('ajv'); -import { StrykerOptions, strykerCoreSchema, WarningOptions } from '@stryker-mutator/api/core'; +import { StrykerOptions, strykerCoreSchema } from '@stryker-mutator/api/core'; import { tokens, commonTokens } from '@stryker-mutator/api/plugin'; -import { noopLogger, normalizeWhitespaces, propertyPath } from '@stryker-mutator/util'; +import { noopLogger, propertyPath, deepFreeze, PropertyPathBuilder } from '@stryker-mutator/util'; import { Logger } from '@stryker-mutator/api/logging'; +import type { JSONSchema7 } from 'json-schema'; import { coreTokens } from '../di'; import { ConfigError } from '../errors'; @@ -17,39 +20,74 @@ export class OptionsValidator { public static readonly inject = tokens(coreTokens.validationSchema, commonTokens.logger); - constructor(schema: object, private readonly log: Logger) { + constructor(schema: JSONSchema7, private readonly log: Logger) { this.validateFn = ajv.compile(schema); } - public validate(options: unknown): asserts options is StrykerOptions { + public validate(options: Record): asserts options is StrykerOptions { + this.removeDeprecatedOptions(options); this.schemaValidate(options); this.additionalValidation(options); } + private removeDeprecatedOptions(rawOptions: Record) { + if (typeof rawOptions.mutator === 'string') { + this.log.warn( + 'DEPRECATED. Use of "mutator" as string is no longer needed. You can remove it from your configuration. Stryker now supports mutating of JavaScript and friend files out of the box.' + ); + delete rawOptions.mutator; + } + // @ts-expect-error mutator.name + if (typeof rawOptions.mutator === 'object' && rawOptions.mutator.name) { + this.log.warn( + 'DEPRECATED. Use of "mutator.name" is no longer needed. You can remove "mutator.name" from your configuration. Stryker now supports mutating of JavaScript and friend files out of the box.' + ); + // @ts-expect-error mutator.name + delete rawOptions.mutator.name; + } + if (Object.keys(rawOptions).includes('testFramework')) { + this.log.warn( + 'DEPRECATED. Use of "testFramework" is no longer needed. You can remove it from your configuration. Your test runner plugin now handles its own test framework integration.' + ); + delete rawOptions.testFramework; + } + if (Array.isArray(rawOptions.transpilers)) { + const example = rawOptions.transpilers.includes('babel') + ? 'babel src --out-dir lib' + : rawOptions.transpilers.includes('typescript') + ? 'tsc -b' + : rawOptions.transpilers.includes('webpack') + ? 'webpack --config webpack.config.js' + : 'npm run build'; + this.log.warn( + `DEPRECATED. Support for "transpilers" is removed. You can now configure your own "${propertyPath( + 'buildCommand' + )}". For example, ${example}.` + ); + delete rawOptions.transpilers; + } + } + private additionalValidation(options: StrykerOptions) { const additionalErrors: string[] = []; if (options.thresholds.high < options.thresholds.low) { additionalErrors.push('Config option "thresholds.high" should be higher than "thresholds.low".'); } - if (options.transpilers.length > 1 && options.coverageAnalysis !== 'off') { - additionalErrors.push( - normalizeWhitespaces( - `Config option "coverageAnalysis" is invalid. Coverage analysis "${options.coverageAnalysis}" - is not supported for multiple transpilers (configured transpilers: ${options.transpilers.map((t) => `"${t}"`).join(', ')}). - Change it to "off". Please report this to the Stryker team if you whish this feature to be implemented.` - ) - ); + if (options.maxConcurrentTestRunners !== Number.MAX_SAFE_INTEGER) { + this.log.warn('DEPRECATED. Use of "maxConcurrentTestRunners" is deprecated. Please use "concurrency" instead.'); + if (!options.concurrency && options.maxConcurrentTestRunners < os.cpus().length - 1) { + options.concurrency = options.maxConcurrentTestRunners; + } } - additionalErrors.forEach((error) => this.log.error(error)); this.throwErrorIfNeeded(additionalErrors); } private schemaValidate(options: unknown): asserts options is StrykerOptions { if (!this.validateFn(options)) { - const errors = describeErrors(this.validateFn.errors!); - errors.forEach((error) => this.log.error(error)); - this.throwErrorIfNeeded(errors); + const describedErrors = describeErrors(this.validateFn.errors!); + describedErrors.forEach((error) => this.log.error(error)); + this.throwErrorIfNeeded(describedErrors); } } @@ -63,33 +101,37 @@ export class OptionsValidator { } export function defaultOptions(): StrykerOptions { - const options: unknown = {}; + const options: Record = {}; const validator: OptionsValidator = new OptionsValidator(strykerCoreSchema, noopLogger); validator.validate(options); return options; } validateOptions.inject = tokens(commonTokens.options, coreTokens.optionsValidator); -export function validateOptions(options: unknown, optionsValidator: OptionsValidator): StrykerOptions { +export function validateOptions(options: Record, optionsValidator: OptionsValidator): StrykerOptions { optionsValidator.validate(options); - return options; + return deepFreeze(options) as StrykerOptions; } markUnknownOptions.inject = tokens(commonTokens.options, coreTokens.validationSchema, commonTokens.logger); -export function markUnknownOptions(options: StrykerOptions, schema: object, log: Logger): StrykerOptions { +export function markUnknownOptions(options: StrykerOptions, schema: JSONSchema7, log: Logger): StrykerOptions { const OPTIONS_ADDED_BY_STRYKER = ['set', 'configFile', '$schema']; + if (isWarningEnabled('unknownOptions', options.warnings)) { + const schemaKeys = Object.keys(schema.properties!); const unknownPropertyNames = Object.keys(options) .filter((key) => !key.endsWith('_comment')) .filter((key) => !OPTIONS_ADDED_BY_STRYKER.includes(key)) - .filter((key) => !Object.keys((schema as any).properties).includes(key)); - unknownPropertyNames.forEach((unknownPropertyName) => { - log.warn(`Unknown stryker config option "${unknownPropertyName}".`); - }); - const p = `${propertyPath('warnings')}.${propertyPath('unknownOptions')}`; + .filter((key) => !schemaKeys.includes(key)); + if (unknownPropertyNames.length) { - log.warn(` - Possible causes: + unknownPropertyNames.forEach((unknownPropertyName) => { + log.warn(`Unknown stryker config option "${unknownPropertyName}".`); + }); + + const p = PropertyPathBuilder.create().prop('warnings').prop('unknownOptions').build(); + + log.warn(`Possible causes: * Is it a typo on your end? * Did you only write this property as a comment? If so, please postfix it with "_comment". * You might be missing a plugin that is supposed to use it. Stryker loaded plugins from: ${JSON.stringify(options.plugins)} @@ -97,5 +139,6 @@ export function markUnknownOptions(options: StrykerOptions, schema: object, log: (disable "${p}" to ignore this warning)`); } } + return options; } diff --git a/packages/core/src/config/buildSchemaWithPluginContributions.ts b/packages/core/src/config/buildSchemaWithPluginContributions.ts index 1be72f8314..b31a7815f5 100644 --- a/packages/core/src/config/buildSchemaWithPluginContributions.ts +++ b/packages/core/src/config/buildSchemaWithPluginContributions.ts @@ -1,9 +1,10 @@ import { commonTokens, PluginResolver, tokens } from '@stryker-mutator/api/plugin'; import { Logger } from '@stryker-mutator/api/logging'; +import type { JSONSchema7 } from 'json-schema'; import { coreTokens } from '../di'; -function mergedSchema(mainSchema: any, additionalSchemas: any[]): object { +function mergedSchema(mainSchema: JSONSchema7, additionalSchemas: JSONSchema7[]): JSONSchema7 { const schema = { ...mainSchema, properties: { @@ -19,7 +20,7 @@ function mergedSchema(mainSchema: any, additionalSchemas: any[]): object { return schema; } -export function buildSchemaWithPluginContributions(schema: object, pluginResolver: PluginResolver, logger: Logger): object { +export function buildSchemaWithPluginContributions(schema: JSONSchema7, pluginResolver: PluginResolver, logger: Logger): JSONSchema7 { const additionalSchemas = pluginResolver.resolveValidationSchemaContributions(); logger.debug('Contributing %s schemas from plugins to options validation.', additionalSchemas.length); return mergedSchema(schema, additionalSchemas); diff --git a/packages/core/src/config/createConfig.ts b/packages/core/src/config/createConfig.ts index 7c3002b529..259eee1fa4 100644 --- a/packages/core/src/config/createConfig.ts +++ b/packages/core/src/config/createConfig.ts @@ -1,18 +1,15 @@ import { deepMerge } from '@stryker-mutator/util/src/deepMerge'; import { StrykerOptions, PartialStrykerOptions } from '@stryker-mutator/api/core'; -import { Config } from '@stryker-mutator/api/config'; /** - * Creates a `Config` object for given options. - * `Config` is the same as `StrykerOptions`, but with a `set` function that can be used as a shorthand to - * override options using a deep merge algorithm. This is mostly deprecated. + * Adds a `set` method to the options object that can be used as a shorthand to + * override options using a deep merge algorithm. This is mostly for backward compatibility purposes. * @param options The stryker options use * @deprecated Please use `StrykerOptions` directly instead */ -export function createConfig(options: StrykerOptions): Config { - const config = options as Config; +export function createConfig(options: StrykerOptions): StrykerOptions { options.set = (newConfig: PartialStrykerOptions) => { deepMerge(options, newConfig); }; - return config; + return options; } diff --git a/packages/core/src/config/index.ts b/packages/core/src/config/index.ts index c99985f8b5..8027e13b4a 100644 --- a/packages/core/src/config/index.ts +++ b/packages/core/src/config/index.ts @@ -1,4 +1,3 @@ -export { OptionsEditorApplier } from './OptionsEditorApplier'; export * from './readConfig'; export * from './OptionsValidator'; export * from './buildSchemaWithPluginContributions'; diff --git a/packages/core/src/di/PluginCreator.ts b/packages/core/src/di/PluginCreator.ts index 780fa40226..1dcc1e460f 100644 --- a/packages/core/src/di/PluginCreator.ts +++ b/packages/core/src/di/PluginCreator.ts @@ -3,7 +3,7 @@ import { commonTokens, FactoryPlugin, Plugin, - PluginContexts, + PluginContext, PluginInterfaces, PluginKind, PluginResolver, @@ -15,7 +15,7 @@ export class PluginCreator { private constructor( private readonly kind: TPluginKind, private readonly pluginResolver: PluginResolver, - private readonly injector: Injector + private readonly injector: Injector ) {} public create(name: string): PluginInterfaces[TPluginKind] { @@ -29,14 +29,14 @@ export class PluginCreator { } } - private isFactoryPlugin(plugin: Plugin): plugin is FactoryPlugin>> { - return !!(plugin as FactoryPlugin>>).factory; + private isFactoryPlugin(plugin: Plugin): plugin is FactoryPlugin>> { + return !!(plugin as FactoryPlugin>>).factory; } - private isClassPlugin(plugin: Plugin): plugin is ClassPlugin>> { - return !!(plugin as ClassPlugin>>).injectableClass; + private isClassPlugin(plugin: Plugin): plugin is ClassPlugin>> { + return !!(plugin as ClassPlugin>>).injectableClass; } - public static createFactory( + public static createFactory( kind: TPluginKind ): InjectableFunctionWithInject, [typeof commonTokens.pluginResolver, typeof commonTokens.injector]> { function factory(pluginResolver: PluginResolver, injector: Injector): PluginCreator { diff --git a/packages/core/src/di/PluginLoader.ts b/packages/core/src/di/PluginLoader.ts index 264da952fc..3c153c8885 100644 --- a/packages/core/src/di/PluginLoader.ts +++ b/packages/core/src/di/PluginLoader.ts @@ -12,16 +12,16 @@ import * as coreTokens from './coreTokens'; const IGNORED_PACKAGES = ['core', 'api', 'util']; interface PluginModule { - strykerPlugins: Array>; + strykerPlugins: Array>; } interface SchemaValidationContribution { - strykerValidationSchema: object; + strykerValidationSchema: Record; } export class PluginLoader implements PluginResolver { - private readonly pluginsByKind: Map>> = new Map(); - private readonly contributedValidationSchemas: object[] = []; + private readonly pluginsByKind: Map>> = new Map(); + private readonly contributedValidationSchemas: Array> = []; public static inject = tokens(commonTokens.logger, coreTokens.pluginDescriptors); constructor(private readonly log: Logger, private readonly pluginDescriptors: readonly string[]) {} @@ -32,7 +32,7 @@ export class PluginLoader implements PluginResolver { }); } - public resolveValidationSchemaContributions(): object[] { + public resolveValidationSchemaContributions(): Array> { return this.contributedValidationSchemas; } @@ -41,7 +41,7 @@ export class PluginLoader implements PluginResolver { if (plugins) { const plugin = plugins.find((plugin) => plugin.name.toLowerCase() === name.toLowerCase()); if (plugin) { - return plugin as any; + return plugin as Plugins[T]; } else { throw new Error( `Cannot load ${kind} plugin "${name}". Did you forget to install it? Loaded ${kind} plugins were: ${plugins.map((p) => p.name).join(', ')}` @@ -53,8 +53,8 @@ export class PluginLoader implements PluginResolver { } public resolveAll(kind: T): Array { - const plugins = this.pluginsByKind.get(kind); - return plugins || ([] as any); + const plugins = this.pluginsByKind.get(kind) || []; + return plugins as Array; } private resolvePluginModules() { @@ -110,7 +110,7 @@ export class PluginLoader implements PluginResolver { } } - private loadPlugin(plugin: Plugin) { + private loadPlugin(plugin: Plugin) { let plugins = this.pluginsByKind.get(plugin.kind); if (!plugins) { plugins = []; diff --git a/packages/core/src/di/buildChildProcessInjector.ts b/packages/core/src/di/buildChildProcessInjector.ts index 9e85d85f9a..87a4d8b2e3 100644 --- a/packages/core/src/di/buildChildProcessInjector.ts +++ b/packages/core/src/di/buildChildProcessInjector.ts @@ -1,20 +1,16 @@ import { StrykerOptions } from '@stryker-mutator/api/core'; -import { commonTokens, Injector, OptionsContext, Scope, tokens } from '@stryker-mutator/api/plugin'; -import { getLogger } from 'log4js'; -import { rootInjector } from 'typed-inject'; +import { commonTokens, Injector, PluginContext, tokens } from '@stryker-mutator/api/plugin'; +import { createInjector } from 'typed-inject'; -import { loggerFactory, mutatorDescriptorFactory, pluginResolverFactory } from './factoryMethods'; +import { pluginResolverFactory } from './factoryMethods'; -import { coreTokens } from '.'; +import { coreTokens, provideLogger } from '.'; -export function buildChildProcessInjector(options: StrykerOptions): Injector { - return rootInjector +export function buildChildProcessInjector(options: StrykerOptions): Injector { + return provideLogger(createInjector()) .provideValue(commonTokens.options, options) - .provideValue(commonTokens.getLogger, getLogger) - .provideFactory(commonTokens.logger, loggerFactory, Scope.Transient) .provideFactory(coreTokens.pluginDescriptors, pluginDescriptorsFactory) - .provideFactory(commonTokens.pluginResolver, pluginResolverFactory) - .provideFactory(commonTokens.mutatorDescriptor, mutatorDescriptorFactory); + .provideFactory(commonTokens.pluginResolver, pluginResolverFactory); } function pluginDescriptorsFactory(options: StrykerOptions): readonly string[] { diff --git a/packages/core/src/di/buildMainInjector.ts b/packages/core/src/di/buildMainInjector.ts index c606f7c7c6..c36335eef1 100644 --- a/packages/core/src/di/buildMainInjector.ts +++ b/packages/core/src/di/buildMainInjector.ts @@ -1,62 +1,44 @@ +import execa = require('execa'); import { StrykerOptions, strykerCoreSchema, PartialStrykerOptions } from '@stryker-mutator/api/core'; -import { commonTokens, Injector, OptionsContext, PluginKind, Scope, tokens } from '@stryker-mutator/api/plugin'; +import { commonTokens, Injector, PluginContext, PluginKind, tokens } from '@stryker-mutator/api/plugin'; import { Reporter } from '@stryker-mutator/api/report'; -import { TestFramework } from '@stryker-mutator/api/test_framework'; -import { getLogger } from 'log4js'; -import { rootInjector } from 'typed-inject'; -import { - OptionsEditorApplier, - readConfig, - buildSchemaWithPluginContributions, - OptionsValidator, - validateOptions, - markUnknownOptions, -} from '../config'; +import { readConfig, buildSchemaWithPluginContributions, OptionsValidator, validateOptions, markUnknownOptions } from '../config'; import ConfigReader from '../config/ConfigReader'; import BroadcastReporter from '../reporters/BroadcastReporter'; import { TemporaryDirectory } from '../utils/TemporaryDirectory'; import Timer from '../utils/Timer'; -import { loggerFactory, mutatorDescriptorFactory, applyOptionsEditors, pluginResolverFactory, testFrameworkFactory } from './factoryMethods'; +import { pluginResolverFactory } from './factoryMethods'; import { coreTokens, PluginCreator } from '.'; -export interface MainContext extends OptionsContext { +export interface MainContext extends PluginContext { [coreTokens.reporter]: Required; - [coreTokens.testFramework]: TestFramework | null; [coreTokens.pluginCreatorReporter]: PluginCreator; - [coreTokens.pluginCreatorConfigEditor]: PluginCreator; - [coreTokens.pluginCreatorMutator]: PluginCreator; - [coreTokens.pluginCreatorTestFramework]: PluginCreator; + [coreTokens.pluginCreatorChecker]: PluginCreator; [coreTokens.timer]: Timer; [coreTokens.temporaryDirectory]: TemporaryDirectory; + [coreTokens.execa]: typeof execa; } -type BasicInjector = Injector>; -type PluginResolverInjector = Injector>; +type PluginResolverProvider = Injector; +export type CliOptionsProvider = Injector & { [coreTokens.cliOptions]: PartialStrykerOptions }>; -export function buildMainInjector(cliOptions: PartialStrykerOptions): Injector { - const basicInjector = createBasicInjector(); - const pluginResolverInjector = createPluginResolverInjector(cliOptions, basicInjector); - return pluginResolverInjector - .provideFactory(commonTokens.mutatorDescriptor, mutatorDescriptorFactory) +buildMainInjector.inject = tokens(commonTokens.injector); +export function buildMainInjector(injector: CliOptionsProvider): Injector { + const pluginResolverProvider = createPluginResolverProvider(injector); + return pluginResolverProvider .provideFactory(coreTokens.pluginCreatorReporter, PluginCreator.createFactory(PluginKind.Reporter)) - .provideFactory(coreTokens.pluginCreatorTestFramework, PluginCreator.createFactory(PluginKind.TestFramework)) - .provideFactory(coreTokens.pluginCreatorMutator, PluginCreator.createFactory(PluginKind.Mutator)) + .provideFactory(coreTokens.pluginCreatorChecker, PluginCreator.createFactory(PluginKind.Checker)) .provideClass(coreTokens.reporter, BroadcastReporter) - .provideFactory(coreTokens.testFramework, testFrameworkFactory) .provideClass(coreTokens.temporaryDirectory, TemporaryDirectory) - .provideClass(coreTokens.timer, Timer); + .provideClass(coreTokens.timer, Timer) + .provideValue(coreTokens.execa, execa); } -function createBasicInjector(): BasicInjector { - return rootInjector.provideValue(commonTokens.getLogger, getLogger).provideFactory(commonTokens.logger, loggerFactory, Scope.Transient); -} - -export function createPluginResolverInjector(cliOptions: PartialStrykerOptions, parent: BasicInjector): PluginResolverInjector { +export function createPluginResolverProvider(parent: CliOptionsProvider): PluginResolverProvider { return parent - .provideValue(coreTokens.cliOptions, cliOptions) .provideValue(coreTokens.validationSchema, strykerCoreSchema) .provideClass(coreTokens.optionsValidator, OptionsValidator) .provideClass(coreTokens.configReader, ConfigReader) @@ -66,15 +48,12 @@ export function createPluginResolverInjector(cliOptions: PartialStrykerOptions, .provideFactory(coreTokens.validationSchema, buildSchemaWithPluginContributions) .provideClass(coreTokens.optionsValidator, OptionsValidator) .provideFactory(commonTokens.options, validateOptions) - .provideFactory(commonTokens.options, markUnknownOptions) - .provideFactory(coreTokens.pluginCreatorConfigEditor, PluginCreator.createFactory(PluginKind.ConfigEditor)) - .provideFactory(coreTokens.pluginCreatorOptionsEditor, PluginCreator.createFactory(PluginKind.OptionsEditor)) - .provideClass(coreTokens.configOptionsApplier, OptionsEditorApplier) - .provideFactory(commonTokens.options, applyOptionsEditors); + .provideFactory(commonTokens.options, markUnknownOptions); } function pluginDescriptorsFactory(options: StrykerOptions): readonly string[] { options.plugins.push(require.resolve('../reporters')); + options.plugins = options.plugins.concat(options.appendPlugins); return options.plugins; } pluginDescriptorsFactory.inject = tokens(commonTokens.options); diff --git a/packages/core/src/di/coreTokens.ts b/packages/core/src/di/coreTokens.ts index 17e3cdee2f..005d2b9277 100644 --- a/packages/core/src/di/coreTokens.ts +++ b/packages/core/src/di/coreTokens.ts @@ -1,27 +1,34 @@ +export const checkerPool = 'checkerPool'; +export const checkerFactory = 'checkerFactory'; +export const checkerConcurrencyTokens = 'checkerConcurrencyTokens'; +export const disableTypeChecksHelper = 'disableTypeChecksHelper'; +export const execa = 'execa'; export const cliOptions = 'cliOptions'; export const configReader = 'configReader'; -export const configOptionsApplier = 'configOptionsApplier'; +export const configOptionsApplier = 'configOptionsApplier'; // TODO: Remove if unused post mutation switching export const inputFiles = 'inputFiles'; -export const initialRunResult = 'initialRunResult'; -export const transpiledFiles = 'transpiledFiles'; -export const mutantTranspileScheduler = 'mutantTranspileScheduler'; -export const sandboxPool = 'sandboxPool'; +export const dryRunResult = 'dryRunResult'; +export const transpiledFiles = 'transpiledFiles'; // TODO: Remove if unused post mutation switching +export const files = 'files'; +export const mutants = 'mutants'; +export const mutantsWithTestCoverage = 'mutantsWithTestCoverage'; +export const mutantTranspileScheduler = 'mutantTranspileScheduler'; // TODO: Remove if unused post mutation switching export const temporaryDirectory = 'temporaryDirectory'; -export const testFramework = 'testFramework'; export const timer = 'timer'; export const timeOverheadMS = 'timeOverheadMS'; export const loggingContext = 'loggingContext'; -export const transpiler = 'transpiler'; -export const sandboxIndex = 'sandboxIndex'; +export const mutationTestReportHelper = 'mutationTestReportHelper'; +export const sandbox = 'sandbox'; +export const sandboxWorkingDirectory = 'sandboxWorkingDirectory'; // TODO: Remove if unused post mutation switching +export const concurrencyTokenProvider = 'concurrencyTokenProvider'; +export const testRunnerFactory = 'testRunnerFactory'; +export const testRunnerPool = 'testRunnerPool'; +export const testRunnerConcurrencyTokens = 'testRunnerConcurrencyTokens'; export const reporter = 'reporter'; export const pluginKind = 'pluginKind'; export const pluginDescriptors = 'pluginDescriptors'; export const pluginCreatorReporter = 'pluginCreatorReporter'; -export const pluginCreatorConfigEditor = 'pluginCreatorConfigEditor'; -export const pluginCreatorOptionsEditor = 'pluginCreatorOptionsEditor'; -export const pluginCreatorTranspiler = 'pluginCreatorTranspiler'; +export const pluginCreatorChecker = 'pluginCreatorChecker'; export const pluginCreatorTestRunner = 'pluginCreatorTestRunner'; -export const pluginCreatorMutator = 'pluginCreatorMutator'; -export const pluginCreatorTestFramework = 'pluginCreatorTestFramework'; export const validationSchema = 'validationSchema'; export const optionsValidator = 'optionsValidator'; diff --git a/packages/core/src/di/factoryMethods.ts b/packages/core/src/di/factoryMethods.ts index eb41029a65..8627bc9781 100644 --- a/packages/core/src/di/factoryMethods.ts +++ b/packages/core/src/di/factoryMethods.ts @@ -1,12 +1,7 @@ -import { MutatorDescriptor, StrykerOptions } from '@stryker-mutator/api/core'; -import { Logger, LoggerFactoryMethod } from '@stryker-mutator/api/logging'; -import { commonTokens, Injector, OptionsContext, PluginKind, PluginResolver, tokens } from '@stryker-mutator/api/plugin'; -import { deepFreeze } from '@stryker-mutator/util'; +import { Logger } from '@stryker-mutator/api/logging'; +import { commonTokens, Injector, PluginResolver, tokens } from '@stryker-mutator/api/plugin'; -import { OptionsEditorApplier } from '../config'; -import TestFrameworkOrchestrator from '../TestFrameworkOrchestrator'; - -import { coreTokens, PluginCreator, PluginLoader } from '.'; +import { coreTokens, PluginLoader } from '.'; export function pluginResolverFactory( injector: Injector<{ [commonTokens.logger]: Logger; [coreTokens.pluginDescriptors]: readonly string[] }> @@ -16,41 +11,3 @@ export function pluginResolverFactory( return pluginLoader; } pluginResolverFactory.inject = tokens(commonTokens.injector); - -export function testFrameworkFactory( - injector: Injector }> -) { - return injector.injectClass(TestFrameworkOrchestrator).determineTestFramework(); -} -testFrameworkFactory.inject = tokens(commonTokens.injector); - -export function loggerFactory(getLogger: LoggerFactoryMethod, target: Function | undefined) { - return getLogger(target ? target.name : 'UNKNOWN'); -} -loggerFactory.inject = tokens(commonTokens.getLogger, commonTokens.target); - -export function applyOptionsEditors(options: StrykerOptions, optionsEditorApplier: OptionsEditorApplier): StrykerOptions { - optionsEditorApplier.edit(options); - return deepFreeze(options) as StrykerOptions; -} -applyOptionsEditors.inject = tokens(commonTokens.options, coreTokens.configOptionsApplier); - -export function mutatorDescriptorFactory(options: StrykerOptions): MutatorDescriptor { - const defaults: MutatorDescriptor = { - plugins: null, - name: 'javascript', - excludedMutations: [], - }; - if (typeof options.mutator === 'string') { - return { - ...defaults, - name: options.mutator, - }; - } - - return { - ...defaults, - ...options.mutator, - }; -} -mutatorDescriptorFactory.inject = tokens(commonTokens.options); diff --git a/packages/core/src/di/index.ts b/packages/core/src/di/index.ts index 08690f2326..d7637409fa 100644 --- a/packages/core/src/di/index.ts +++ b/packages/core/src/di/index.ts @@ -5,4 +5,5 @@ export * from './buildChildProcessInjector'; export * from './PluginCreator'; export * from './PluginLoader'; export * from './factoryMethods'; +export * from './provideLogger'; export { coreTokens }; diff --git a/packages/core/src/di/provideLogger.ts b/packages/core/src/di/provideLogger.ts new file mode 100644 index 0000000000..06bb2e1135 --- /dev/null +++ b/packages/core/src/di/provideLogger.ts @@ -0,0 +1,15 @@ +import { Injector, Scope } from 'typed-inject'; +import { commonTokens } from '@stryker-mutator/api/plugin'; +import { LoggerFactoryMethod, Logger } from '@stryker-mutator/api/logging'; +import { getLogger } from 'log4js'; + +export function provideLogger(injector: Injector): LoggerProvider { + return injector.provideValue(commonTokens.getLogger, getLogger).provideFactory(commonTokens.logger, loggerFactory, Scope.Transient); +} +export type LoggerProvider = Injector<{ [commonTokens.getLogger]: LoggerFactoryMethod; [commonTokens.logger]: Logger }>; + +// eslint-disable-next-line @typescript-eslint/ban-types +function loggerFactory(getLogger: LoggerFactoryMethod, target: Function | undefined) { + return getLogger(target ? target.name : 'UNKNOWN'); +} +loggerFactory.inject = [commonTokens.getLogger, commonTokens.target] as const; diff --git a/packages/core/src/globals.ts b/packages/core/src/globals.ts deleted file mode 100644 index a1f763860b..0000000000 --- a/packages/core/src/globals.ts +++ /dev/null @@ -1,11 +0,0 @@ -/** - * These are fake dom type definitions that rxjs depends on - */ -interface EventTarget {} -interface NodeList {} -interface HTMLCollection {} -interface XMLHttpRequest {} -interface Event {} -interface MessageEvent {} -interface CloseEvent {} -interface WebSocket {} diff --git a/packages/core/src/initializer/ChoiceType.ts b/packages/core/src/initializer/ChoiceType.ts new file mode 100644 index 0000000000..7a83fc8af3 --- /dev/null +++ b/packages/core/src/initializer/ChoiceType.ts @@ -0,0 +1,7 @@ +import Separator = require('inquirer/lib/objects/separator'); + +/** + * The "ChoiceType" is used often and is annoying to keep in sync (types change often). + * Defining it once and using it often in an attempt to reduce maintenance. + */ +export type ChoiceType = string | Separator; diff --git a/packages/core/src/initializer/NpmClient.ts b/packages/core/src/initializer/NpmClient.ts index d5921f76b8..5871e55cb2 100644 --- a/packages/core/src/initializer/NpmClient.ts +++ b/packages/core/src/initializer/NpmClient.ts @@ -15,7 +15,7 @@ interface NpmSearchResult { interface NpmPackage { name: string; - initStrykerConfig?: object; + initStrykerConfig?: Record; } const getName = (packageName: string) => { @@ -44,30 +44,11 @@ export default class NpmClient { return this.search('/v2/search?q=keywords:@stryker-mutator/test-runner-plugin').then(mapSearchResultToPromptOption); } - public getTestFrameworkOptions(testRunnerFilter: string | null): Promise { - return this.search('/v2/search?q=keywords:@stryker-mutator/test-framework-plugin') - .then((searchResult) => { - if (testRunnerFilter) { - searchResult.results = searchResult.results.filter((framework) => framework.package.keywords.includes(testRunnerFilter)); - } - return searchResult; - }) - .then(mapSearchResultToPromptOption); - } - - public getMutatorOptions(): Promise { - return this.search('/v2/search?q=keywords:@stryker-mutator/mutator-plugin').then(mapSearchResultToPromptOption); - } - - public getTranspilerOptions(): Promise { - return this.search('/v2/search?q=keywords:@stryker-mutator/transpiler-plugin').then(mapSearchResultToPromptOption); - } - public getTestReporterOptions(): Promise { return this.search('/v2/search?q=keywords:@stryker-mutator/reporter-plugin').then(mapSearchResultToPromptOption); } - public getAdditionalConfig(pkg: PackageInfo): Promise { + public getAdditionalConfig(pkg: PackageInfo): Promise> { const path = `/${pkg.name}@${pkg.version}/package.json`; return this.packageClient .get(path) diff --git a/packages/core/src/initializer/StrykerConfigWriter.ts b/packages/core/src/initializer/StrykerConfigWriter.ts index acc7a6dae9..24982564a3 100644 --- a/packages/core/src/initializer/StrykerConfigWriter.ts +++ b/packages/core/src/initializer/StrykerConfigWriter.ts @@ -1,10 +1,12 @@ import { existsSync, promises as fs } from 'fs'; -import { StrykerOptions } from '@stryker-mutator/api/core'; +import { PartialStrykerOptions, StrykerOptions } from '@stryker-mutator/api/core'; import { Logger } from '@stryker-mutator/api/logging'; import { commonTokens, tokens } from '@stryker-mutator/api/plugin'; import { childProcessAsPromised } from '@stryker-mutator/util'; +import CommandTestRunner from '../test-runner/CommandTestRunner'; + import PresetConfiguration from './presets/PresetConfiguration'; import PromptOption from './PromptOption'; @@ -35,24 +37,19 @@ export default class StrykerConfigWriter { * @function */ public write( - selectedTestRunner: null | PromptOption, - selectedTestFramework: null | PromptOption, - selectedMutator: null | PromptOption, - selectedTranspilers: null | PromptOption[], + selectedTestRunner: PromptOption, selectedReporters: PromptOption[], selectedPackageManager: PromptOption, additionalPiecesOfConfig: Array>, exportAsJson: boolean ): Promise { const configObject: Partial = { - mutator: selectedMutator ? selectedMutator.name : '', packageManager: selectedPackageManager.name as 'npm' | 'yarn', reporters: selectedReporters.map((rep) => rep.name), - testRunner: selectedTestRunner ? selectedTestRunner.name : '', - transpilers: selectedTranspilers ? selectedTranspilers.map((t) => t.name) : [], + testRunner: selectedTestRunner.name, + coverageAnalysis: CommandTestRunner.is(selectedTestRunner.name) ? 'off' : 'perTest', }; - this.configureTestFramework(configObject, selectedTestFramework); Object.assign(configObject, ...additionalPiecesOfConfig); return this.writeStrykerConfig(configObject, exportAsJson); } @@ -63,23 +60,14 @@ export default class StrykerConfigWriter { */ public async writePreset(presetConfig: PresetConfiguration, exportAsJson: boolean) { const config = { - comment: `This config was generated using a preset. Please see the handbook for more information: ${presetConfig.handbookUrl}`, + _comment: `This config was generated using a preset. Please see the handbook for more information: ${presetConfig.handbookUrl}`, ...presetConfig.config, }; return this.writeStrykerConfig(config, exportAsJson); } - private configureTestFramework(configObject: Partial, selectedTestFramework: null | PromptOption) { - if (selectedTestFramework) { - configObject.testFramework = selectedTestFramework.name; - configObject.coverageAnalysis = 'perTest'; - } else { - configObject.coverageAnalysis = 'all'; - } - } - - private writeStrykerConfig(config: Partial, exportAsJson: boolean) { + private writeStrykerConfig(config: PartialStrykerOptions, exportAsJson: boolean) { if (exportAsJson) { return this.writeJsonConfig(config); } else { @@ -87,7 +75,7 @@ export default class StrykerConfigWriter { } } - private async writeJsConfig(commentedConfig: Partial) { + private async writeJsConfig(commentedConfig: PartialStrykerOptions) { this.out(`Writing & formatting ${STRYKER_JS_CONFIG_FILE}...`); const rawConfig = this.stringify(commentedConfig); const formattedConfig = `/** @@ -105,7 +93,7 @@ export default class StrykerConfigWriter { return STRYKER_JS_CONFIG_FILE; } - private async writeJsonConfig(commentedConfig: Partial) { + private async writeJsonConfig(commentedConfig: PartialStrykerOptions) { this.out(`Writing & formatting ${STRYKER_JSON_CONFIG_FILE}...`); const typedConfig = { $schema: './node_modules/@stryker-mutator/core/schema/stryker-schema.json', @@ -117,7 +105,7 @@ export default class StrykerConfigWriter { return STRYKER_JSON_CONFIG_FILE; } - private stringify(input: object): string { + private stringify(input: Record): string { return JSON.stringify(input, undefined, 2); } } diff --git a/packages/core/src/initializer/StrykerInitializer.ts b/packages/core/src/initializer/StrykerInitializer.ts index 2f05622580..c71db612fb 100644 --- a/packages/core/src/initializer/StrykerInitializer.ts +++ b/packages/core/src/initializer/StrykerInitializer.ts @@ -1,11 +1,10 @@ import * as child from 'child_process'; +import { promises as fs } from 'fs'; import { commonTokens, tokens } from '@stryker-mutator/api/plugin'; import { Logger } from '@stryker-mutator/api/logging'; import { notEmpty } from '@stryker-mutator/util'; -import CommandTestRunner from '../test-runner/CommandTestRunner'; - import NpmClient from './NpmClient'; import { PackageInfo } from './PackageInfo'; import Preset from './presets/Preset'; @@ -56,7 +55,7 @@ export default class StrykerInitializer { configFileName = await this.initiateCustom(this.configWriter); } await this.gitignoreWriter.addStrykerTempFolder(); - this.out(`Done configuring stryker. Please review "${configFileName}", you might need to configure transpilers or your test runner correctly.`); + this.out(`Done configuring stryker. Please review "${configFileName}", you might need to configure your test runner correctly.`); this.out("Let's kill some mutants with this command: `stryker run`"); } @@ -89,6 +88,9 @@ export default class StrykerInitializer { const presetConfig = await selectedPreset.createConfig(); const isJsonSelected = await this.selectJsonConfigType(); const configFileName = await configWriter.writePreset(presetConfig, isJsonSelected); + if (presetConfig.additionalConfigFiles) { + await Promise.all(presetConfig.additionalConfigFiles.map(({ name, content }) => fs.writeFile(name, content))); + } const selectedPackageManager = await this.selectPackageManager(); this.installNpmDependencies(presetConfig.dependencies, selectedPackageManager); return configFileName; @@ -96,21 +98,12 @@ export default class StrykerInitializer { private async initiateCustom(configWriter: StrykerConfigWriter) { const selectedTestRunner = await this.selectTestRunner(); - const selectedTestFramework = - selectedTestRunner && !CommandTestRunner.is(selectedTestRunner.name) ? await this.selectTestFramework(selectedTestRunner) : null; - const selectedMutator = await this.selectMutator(); - const selectedTranspilers = await this.selectTranspilers(); const selectedReporters = await this.selectReporters(); const selectedPackageManager = await this.selectPackageManager(); const isJsonSelected = await this.selectJsonConfigType(); - const npmDependencies = this.getSelectedNpmDependencies( - [selectedTestRunner, selectedTestFramework, selectedMutator].concat(selectedTranspilers).concat(selectedReporters) - ); + const npmDependencies = this.getSelectedNpmDependencies([selectedTestRunner].concat(selectedReporters)); const configFileName = await configWriter.write( selectedTestRunner, - selectedTestFramework, - selectedMutator, - selectedTranspilers, selectedReporters, selectedPackageManager, await this.fetchAdditionalConfig(npmDependencies), @@ -123,15 +116,10 @@ export default class StrykerInitializer { return configFileName; } - private async selectTestRunner(): Promise { + private async selectTestRunner(): Promise { const testRunnerOptions = await this.client.getTestRunnerOptions(); - if (testRunnerOptions.length) { - this.log.debug(`Found test runners: ${JSON.stringify(testRunnerOptions)}`); - return this.inquirer.promptTestRunners(testRunnerOptions); - } else { - this.out('Unable to select a test runner. You will need to configure it manually.'); - return null; - } + this.log.debug(`Found test runners: ${JSON.stringify(testRunnerOptions)}`); + return this.inquirer.promptTestRunners(testRunnerOptions); } private async selectReporters(): Promise { @@ -158,49 +146,6 @@ export default class StrykerInitializer { return this.inquirer.promptReporters(reporterOptions); } - private async selectTestFramework(testRunnerOption: PromptOption): Promise { - let selectedTestFramework: PromptOption | null = null; - const testFrameworkOptions = await this.client.getTestFrameworkOptions(testRunnerOption.pkg ? testRunnerOption.pkg.name : null); - if (testFrameworkOptions.length) { - this.log.debug(`Found test frameworks for ${testRunnerOption.name}: ${JSON.stringify(testFrameworkOptions)}`); - const none: PromptOption = { - name: 'None/other', - pkg: null, - }; - testFrameworkOptions.push(none); - selectedTestFramework = await this.inquirer.promptTestFrameworks(testFrameworkOptions); - if (selectedTestFramework === none) { - selectedTestFramework = null; - this.out('OK, downgrading coverageAnalysis to "all"'); - } - } else { - this.out(`No stryker test framework plugin found that is compatible with ${testRunnerOption.name}, downgrading coverageAnalysis to "all"`); - } - return selectedTestFramework; - } - - private async selectMutator(): Promise { - const mutatorOptions = await this.client.getMutatorOptions(); - if (mutatorOptions.length) { - this.log.debug(`Found mutators: ${JSON.stringify(mutatorOptions)}`); - return this.inquirer.promptMutator(mutatorOptions); - } else { - this.out('Unable to select a mutator. You will need to configure it manually.'); - return null; - } - } - - private async selectTranspilers(): Promise { - const options = await this.client.getTranspilerOptions(); - if (options.length) { - this.log.debug(`Found transpilers: ${JSON.stringify(options)}`); - return this.inquirer.promptTranspilers(options); - } else { - this.out('Unable to select transpilers. You will need to configure it manually, if you want to use any.'); - return null; - } - } - private async selectPackageManager(): Promise { return this.inquirer.promptPackageManager([ { @@ -245,7 +190,7 @@ export default class StrykerInitializer { } } - private async fetchAdditionalConfig(dependencies: PackageInfo[]): Promise { + private async fetchAdditionalConfig(dependencies: PackageInfo[]): Promise>> { return (await Promise.all(dependencies.map((dep) => this.client.getAdditionalConfig(dep)))).filter(notEmpty); } } diff --git a/packages/core/src/initializer/StrykerInquirer.ts b/packages/core/src/initializer/StrykerInquirer.ts index 6803adcbff..43bda8980b 100644 --- a/packages/core/src/initializer/StrykerInquirer.ts +++ b/packages/core/src/initializer/StrykerInquirer.ts @@ -2,17 +2,19 @@ import * as inquirer from 'inquirer'; import CommandTestRunner from '../test-runner/CommandTestRunner'; +import { ChoiceType } from './ChoiceType'; + import Preset from './presets/Preset'; import PromptOption from './PromptOption'; export interface PromptResult { additionalNpmDependencies: string[]; - additionalConfig: object; + additionalConfig: Record; } export class StrykerInquirer { public async promptPresets(options: Preset[]): Promise { - const choices: Array> = options.map((_) => _.name); + const choices: ChoiceType[] = options.map((_) => _.name); choices.push(new inquirer.Separator()); choices.push('None/other'); const answers = await inquirer.prompt<{ preset: string }>({ @@ -25,48 +27,21 @@ export class StrykerInquirer { } public async promptTestRunners(options: PromptOption[]): Promise { - const choices: Array> = options.map((_) => _.name); - choices.push(new inquirer.Separator()); - choices.push(CommandTestRunner.runnerName); - const answers = await inquirer.prompt<{ testRunner: string }>({ - choices, - default: 'Mocha', - message: - 'Which test runner do you want to use? If your test runner isn\'t listed here, you can choose "command" (it uses your `npm test` command, but will come with a big performance penalty)', - name: 'testRunner', - type: 'list', - }); - return options.filter((_) => _.name === answers.testRunner)[0] || { name: CommandTestRunner.runnerName, pkg: null }; - } - - public async promptTestFrameworks(options: PromptOption[]): Promise { - const answers = await inquirer.prompt<{ testFramework: string }>({ - choices: options.map((_) => _.name), - message: 'Which test framework do you want to use?', - name: 'testFramework', - type: 'list', - }); - return options.filter((_) => _.name === answers.testFramework)[0]; - } - - public async promptMutator(options: PromptOption[]): Promise { - const answers = await inquirer.prompt<{ mutator: string }>({ - choices: options.map((_) => _.name), - message: 'What kind of code do you want to mutate?', - name: 'mutator', - type: 'list', - }); - return options.filter((_) => _.name === answers.mutator)[0]; - } - - public async promptTranspilers(options: PromptOption[]): Promise { - const answers = await inquirer.prompt<{ transpilers: string[] }>({ - choices: options.map((_) => _.name), - message: '[optional] What kind transformations should be applied to your code?', - name: 'transpilers', - type: 'checkbox', - }); - return options.filter((option) => answers.transpilers.some((transpilerName) => option.name === transpilerName)); + if (options.length) { + const choices: ChoiceType[] = options.map((_) => _.name); + choices.push(new inquirer.Separator()); + choices.push(CommandTestRunner.runnerName); + const answers = await inquirer.prompt<{ testRunner: string }>({ + choices, + message: + 'Which test runner do you want to use? If your test runner isn\'t listed here, you can choose "command" (it uses your `npm test` command, but will come with a big performance penalty)', + name: 'testRunner', + type: 'list', + }); + return options.filter((_) => _.name === answers.testRunner)[0] ?? { name: CommandTestRunner.runnerName, pkg: null }; + } else { + return { name: CommandTestRunner.runnerName, pkg: null }; + } } public async promptReporters(options: PromptOption[]): Promise { diff --git a/packages/core/src/initializer/index.ts b/packages/core/src/initializer/index.ts index 943a94455d..06a0adcdf0 100644 --- a/packages/core/src/initializer/index.ts +++ b/packages/core/src/initializer/index.ts @@ -1,9 +1,7 @@ -import { commonTokens } from '@stryker-mutator/api/plugin'; -import { getLogger } from 'log4js'; -import { rootInjector } from 'typed-inject'; +import { createInjector } from 'typed-inject'; import { RestClient } from 'typed-rest-client'; -import { loggerFactory } from '../di/factoryMethods'; +import { provideLogger } from '../di'; import * as initializerTokens from './initializerTokens'; import NpmClient from './NpmClient'; @@ -17,9 +15,7 @@ const BASE_NPM_SEARCH = 'https://api.npms.io'; const BASE_NPM_PACKAGE = 'https://www.unpkg.com'; export function initializerFactory(): StrykerInitializer { - return rootInjector - .provideValue(commonTokens.getLogger, getLogger) - .provideFactory(commonTokens.logger, loggerFactory) + return provideLogger(createInjector()) .provideValue(initializerTokens.out, console.log) .provideValue(initializerTokens.strykerPresets, strykerPresets) .provideValue(initializerTokens.restClientNpmSearch, new RestClient('npmSearch', BASE_NPM_SEARCH)) diff --git a/packages/core/src/initializer/presets/AngularPreset.ts b/packages/core/src/initializer/presets/AngularPreset.ts index f12193c088..9a7c89328a 100644 --- a/packages/core/src/initializer/presets/AngularPreset.ts +++ b/packages/core/src/initializer/presets/AngularPreset.ts @@ -10,10 +10,9 @@ const handbookUrl = 'https://github.com/stryker-mutator/stryker-handbook/blob/ma export class AngularPreset implements Preset { public readonly name = 'angular-cli'; // Please keep config in sync with handbook - private readonly dependencies = ['@stryker-mutator/core', '@stryker-mutator/karma-runner', '@stryker-mutator/typescript']; + private readonly dependencies = ['@stryker-mutator/karma-runner']; private readonly config: Partial = { mutate: ['src/**/*.ts', '!src/**/*.spec.ts', '!src/test.ts', '!src/environments/*.ts'], - mutator: 'typescript', testRunner: 'karma', karma: { configFile: 'src/karma.conf.js', @@ -23,10 +22,10 @@ export class AngularPreset implements Preset { }, }, reporters: ['progress', 'clear-text', 'html'], - maxConcurrentTestRunners: Math.floor(os.cpus().length / 2), - // eslint-disable-next-line @typescript-eslint/camelcase - maxConcurrentTestRunners_comment: 'Recommended to use about half of your available cores when running stryker with angular', - coverageAnalysis: 'off', + concurrency: Math.floor(os.cpus().length / 2), + // eslint-disable-next-line camelcase + concurrency_comment: 'Recommended to use about half of your available cores when running stryker with angular', + coverageAnalysis: 'perTest', }; public async createConfig(): Promise { diff --git a/packages/core/src/initializer/presets/PresetConfiguration.ts b/packages/core/src/initializer/presets/PresetConfiguration.ts index ac5d0d276b..55c74c67e8 100644 --- a/packages/core/src/initializer/presets/PresetConfiguration.ts +++ b/packages/core/src/initializer/presets/PresetConfiguration.ts @@ -1,7 +1,8 @@ -import { StrykerOptions } from '@stryker-mutator/api/core'; +import { File, PartialStrykerOptions } from '@stryker-mutator/api/core'; export default interface PresetConfiguration { - config: Partial; + config: PartialStrykerOptions; handbookUrl: string; dependencies: string[]; + additionalConfigFiles?: File[]; } diff --git a/packages/core/src/initializer/presets/ReactPreset.ts b/packages/core/src/initializer/presets/ReactPreset.ts index f788331465..3659973091 100644 --- a/packages/core/src/initializer/presets/ReactPreset.ts +++ b/packages/core/src/initializer/presets/ReactPreset.ts @@ -1,4 +1,3 @@ -import inquirer = require('inquirer'); import { StrykerOptions } from '@stryker-mutator/api/core'; import Preset from './Preset'; @@ -12,9 +11,9 @@ const handbookUrl = 'https://github.com/stryker-mutator/stryker-handbook/blob/ma */ export class ReactPreset implements Preset { public readonly name = 'create-react-app'; - private readonly generalDependencies = ['@stryker-mutator/core', '@stryker-mutator/jest-runner']; + private readonly dependencies = ['@stryker-mutator/jest-runner']; - private readonly sharedConfig: Partial = { + private readonly config: Partial = { testRunner: 'jest', reporters: ['progress', 'clear-text', 'html'], coverageAnalysis: 'off', @@ -23,37 +22,7 @@ export class ReactPreset implements Preset { }, }; - private readonly tsxDependencies = ['@stryker-mutator/typescript', ...this.generalDependencies]; - private readonly tsxConf: Partial = { - mutate: ['src/**/*.ts?(x)', '!src/**/*@(.test|.spec|Spec).ts?(x)'], - mutator: 'typescript', - ...this.sharedConfig, - }; - - private readonly jsxDependencies = ['@stryker-mutator/javascript-mutator', ...this.generalDependencies]; - private readonly jsxConf: Partial = { - mutate: ['src/**/*.js?(x)', '!src/**/*@(.test|.spec|Spec).js?(x)'], - mutator: 'javascript', - ...this.sharedConfig, - }; - public async createConfig(): Promise { - const choices: Array> = ['JSX', 'TSX']; - const answers = await inquirer.prompt<{ choice: string }>({ - choices, - message: 'Is your project a JSX project or a TSX project?', - name: 'choice', - type: 'list', - }); - return this.load(answers.choice); - } - private load(choice: string): PresetConfiguration { - if (choice === 'JSX') { - return { config: this.jsxConf, handbookUrl, dependencies: this.jsxDependencies }; - } else if (choice === 'TSX') { - return { config: this.tsxConf, handbookUrl, dependencies: this.tsxDependencies }; - } else { - throw new Error(`Invalid project type ${choice}`); - } + return { config: this.config, handbookUrl, dependencies: this.dependencies }; } } diff --git a/packages/core/src/initializer/presets/VueJsPreset.ts b/packages/core/src/initializer/presets/VueJsPreset.ts index 3702d8e648..6bd4d49b54 100644 --- a/packages/core/src/initializer/presets/VueJsPreset.ts +++ b/packages/core/src/initializer/presets/VueJsPreset.ts @@ -1,5 +1,5 @@ import inquirer = require('inquirer'); -import { StrykerOptions } from '@stryker-mutator/api/core'; +import { File, PartialStrykerOptions } from '@stryker-mutator/api/core'; import Preset from './Preset'; import PresetConfiguration from './PresetConfiguration'; @@ -11,63 +11,53 @@ const handbookUrl = 'https://github.com/stryker-mutator/stryker-handbook/blob/ma * https://github.com/stryker-mutator/stryker-handbook/blob/master/stryker/guides/vuejs.md#vuejs */ export class VueJsPreset implements Preset { - public readonly name = 'vueJs'; - private readonly generalDependencies = ['@stryker-mutator/core', '@stryker-mutator/vue-mutator']; + public readonly name = 'vue-cli'; - private readonly jestDependency = '@stryker-mutator/jest-runner'; - private readonly jestConf: Partial = { - mutate: ['src/**/*.js', 'src/**/*.ts', 'src/**/*.vue'], - mutator: 'vue', + private readonly jestConf: PartialStrykerOptions = { testRunner: 'jest', + mutator: { + plugins: [], + }, jest: { // config: require('path/to/your/custom/jestConfig.js') }, reporters: ['progress', 'clear-text', 'html'], coverageAnalysis: 'off', }; - - private readonly karmaDependency = '@stryker-mutator/karma-runner'; - private readonly karmaConf: Partial = { - mutate: ['src/**/*.js', 'src/**/*.ts', 'src/**/*.vue'], - mutator: 'vue', - testRunner: 'karma', - karma: { - configFile: 'test/unit/karma.conf.js', - config: { - browsers: ['ChromeHeadless'], - }, + private readonly mochaConf: PartialStrykerOptions = { + testRunner: 'mocha', + mutator: { + plugins: [], }, + mochaOptions: { + require: ['@vue/cli-plugin-unit-mocha/setup.js'], + spec: ['dist/js/chunk-vendors.js', 'dist/js/tests.js'], + }, + buildCommand: 'webpack --config webpack.config.stryker.js', reporters: ['progress', 'clear-text', 'html'], - coverageAnalysis: 'off', + coverageAnalysis: 'perTest', }; public async createConfig(): Promise { - const testRunnerChoices: Array> = ['karma', 'jest']; + const testRunnerChoices = ['mocha', 'jest']; const testRunnerAnswers = await inquirer.prompt<{ testRunner: string }>({ choices: testRunnerChoices, message: 'Which test runner do you want to use?', name: 'testRunner', type: 'list', }); - const scriptChoices: Array> = ['typescript', 'javascript']; - const scriptAnswers = await inquirer.prompt<{ script: string }>({ - choices: scriptChoices, - message: 'Which language does your project use?', - name: 'script', - type: 'list', - }); const chosenTestRunner = testRunnerAnswers.testRunner; - const chosenScript = scriptAnswers.script; return { config: this.getConfig(chosenTestRunner), - dependencies: this.createDependencies(chosenTestRunner, chosenScript), + dependencies: this.createDependencies(chosenTestRunner), handbookUrl, + additionalConfigFiles: this.getAdditionalConfigFiles(chosenTestRunner), }; } private getConfig(testRunner: string) { - if (testRunner === 'karma') { - return this.karmaConf; + if (testRunner === 'mocha') { + return this.mochaConf; } else if (testRunner === 'jest') { return this.jestConf; } else { @@ -75,28 +65,49 @@ export class VueJsPreset implements Preset { } } - private createDependencies(testRunner: string, script: string): string[] { - const dependencies = this.generalDependencies; - dependencies.push(this.getTestRunnerDependency(testRunner)); - dependencies.push(this.getScriptDependency(script)); - return dependencies; - } + private getAdditionalConfigFiles(testRunner: string): File[] | undefined { + if (testRunner === 'mocha') { + return [ + new File( + 'webpack.config.stryker.js', + ` +const glob = require('glob'); + +// Set env +process.env.BABEL_ENV = 'test'; +process.env.NODE_ENV = 'test'; +process.env.VUE_CLI_BABEL_TARGET_NODE = 'true'; +process.env.VUE_CLI_TRANSPILE_BABEL_RUNTIME = 'true'; + +// Load webpack config +const conf = require('@vue/cli-service/webpack.config.js'); + +// Override the entry files +conf.entry = { + // Choose your test files here: + tests: glob.sync('{test,tests}/**/*+(spec).js').map((fileName) => \`./\${fileName}\`), +}; - private getScriptDependency(script: string): string { - if (script === 'typescript') { - return '@stryker-mutator/typescript'; - } else if (script === 'javascript') { - return '@stryker-mutator/javascript-mutator'; +module.exports = conf; +` + ), + ]; } else { - throw new Error(`Invalid script chosen: ${script}`); + return; } } - private getTestRunnerDependency(testRunner: string): string { - if (testRunner === 'karma') { - return this.karmaDependency; + private createDependencies(testRunner: string): string[] { + const dependencies = []; + dependencies.push(...this.getTestRunnerDependency(testRunner)); + return dependencies; + } + + private getTestRunnerDependency(testRunner: string): string[] { + if (testRunner === 'mocha') { + return ['@stryker-mutator/mocha-runner', 'glob', 'webpack-cli']; } else if (testRunner === 'jest') { - return this.jestDependency; + return ['@stryker-mutator/jest-runner']; } else { throw new Error(`Invalid test runner chosen: ${testRunner}`); } diff --git a/packages/core/src/input/InputFileCollection.ts b/packages/core/src/input/InputFileCollection.ts index b883e58d39..31ff28cb13 100644 --- a/packages/core/src/input/InputFileCollection.ts +++ b/packages/core/src/input/InputFileCollection.ts @@ -1,9 +1,9 @@ +import os = require('os'); + import { File } from '@stryker-mutator/api/core'; import { Logger } from '@stryker-mutator/api/logging'; import { normalizeWhitespaces } from '@stryker-mutator/util'; -import os = require('os'); - export default class InputFileCollection { public readonly files: readonly File[]; public readonly filesToMutate: readonly File[]; diff --git a/packages/core/src/input/InputFileResolver.ts b/packages/core/src/input/InputFileResolver.ts index f10ec185b9..17c7b74a43 100644 --- a/packages/core/src/input/InputFileResolver.ts +++ b/packages/core/src/input/InputFileResolver.ts @@ -1,7 +1,9 @@ -import * as path from 'path'; -import { promises as fs } from 'fs'; import { StringDecoder } from 'string_decoder'; +import * as path from 'path'; +import fs = require('fs'); +import { from } from 'rxjs'; +import { filter, map, mergeMap, toArray } from 'rxjs/operators'; import { File, StrykerOptions } from '@stryker-mutator/api/core'; import { Logger } from '@stryker-mutator/api/logging'; import { commonTokens, tokens } from '@stryker-mutator/api/plugin'; @@ -10,7 +12,7 @@ import { childProcessAsPromised, isErrnoException, normalizeWhitespaces, Stryker import { coreTokens } from '../di'; import StrictReporter from '../reporters/StrictReporter'; -import { glob } from '../utils/fileUtils'; +import { glob, MAX_CONCURRENT_FILE_IO } from '../utils/fileUtils'; import { defaultOptions } from '../config/OptionsValidator'; import InputFileCollection from './InputFileCollection'; @@ -55,7 +57,7 @@ export default class InputFileResolver { public static inject = tokens(commonTokens.logger, commonTokens.options, coreTokens.reporter); constructor(private readonly log: Logger, { mutate, files, tempDirName }: StrykerOptions, private readonly reporter: StrictReporter) { this.tempDirName = tempDirName; - this.mutatePatterns = mutate || []; + this.mutatePatterns = mutate; if (files) { this.filePatterns = files; } @@ -157,25 +159,31 @@ export default class InputFileResolver { } private async readFiles(fileNames: string[]): Promise { - const files = await Promise.all(fileNames.map((fileName) => this.readFile(fileName))); - return files.filter(notEmpty); + const files = from(fileNames) + .pipe( + mergeMap((fileName) => this.readFile(fileName), MAX_CONCURRENT_FILE_IO), + filter(notEmpty), + toArray(), + // Filter the files here, so we force a deterministic instrumentation process + map((files) => files.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0))) + ) + .toPromise(); + return files; } - private readFile(fileName: string): Promise { - return fs - .readFile(fileName) - .then((content: Buffer) => new File(fileName, content)) - .then((file: File) => { - this.reportSourceFilesRead(file); - return file; - }) - .catch((error) => { - if ((isErrnoException(error) && error.code === 'ENOENT') || error.code === 'EISDIR') { - return null; // file is deleted or a directory. This can be a valid result of the git command - } else { - // Rethrow - throw error; - } - }); + private async readFile(fileName: string): Promise { + try { + const content = await fs.promises.readFile(fileName); + const file = new File(fileName, content); + this.reportSourceFilesRead(file); + return file; + } catch (error) { + if ((isErrnoException(error) && error.code === 'ENOENT') || error.code === 'EISDIR') { + return null; // file is deleted or a directory. This can be a valid result of the git command + } else { + // Rethrow + throw error; + } + } } } diff --git a/packages/core/src/logging/LogConfigurator.ts b/packages/core/src/logging/LogConfigurator.ts index b670c93a61..ab79a6b2f7 100644 --- a/packages/core/src/logging/LogConfigurator.ts +++ b/packages/core/src/logging/LogConfigurator.ts @@ -3,7 +3,7 @@ import * as log4js from 'log4js'; import { getFreePort } from '../utils/netUtils'; -import LoggingClientContext from './LoggingClientContext'; +import { LoggingClientContext } from './LoggingClientContext'; import { minLevel } from './logUtils'; const enum AppenderName { @@ -32,7 +32,7 @@ interface AppendersConfiguration { } const LOG_FILE_NAME = 'stryker.log'; -export default class LogConfigurator { +export class LogConfigurator { private static createMainProcessAppenders(consoleLogLevel: LogLevel, fileLogLevel: LogLevel, allowConsoleColors: boolean): AppendersConfiguration { // Add the custom "multiAppender": https://log4js-node.github.io/log4js-node/appenders.html#other-appenders const multiAppender = { type: require.resolve('./MultiAppender'), appenders: [AppenderName.FilteredConsoleLevel] }; @@ -82,7 +82,7 @@ export default class LogConfigurator { public static configureMainProcess( consoleLogLevel: LogLevel = LogLevel.Information, fileLogLevel: LogLevel = LogLevel.Off, - allowConsoleColors: boolean = true + allowConsoleColors = true ) { const appenders = this.createMainProcessAppenders(consoleLogLevel, fileLogLevel, allowConsoleColors); log4js.configure(this.createLog4jsConfig(minLevel(consoleLogLevel, fileLogLevel), appenders)); diff --git a/packages/core/src/logging/LoggingClientContext.ts b/packages/core/src/logging/LoggingClientContext.ts index ead857441a..7902a25463 100644 --- a/packages/core/src/logging/LoggingClientContext.ts +++ b/packages/core/src/logging/LoggingClientContext.ts @@ -1,6 +1,6 @@ import { LogLevel } from '@stryker-mutator/api/core'; -export default interface LoggingClientContext { +export interface LoggingClientContext { /** * The port where the logging server listens for logging events on the localhost */ diff --git a/packages/core/src/logging/index.ts b/packages/core/src/logging/index.ts new file mode 100644 index 0000000000..8e9dfd0fdc --- /dev/null +++ b/packages/core/src/logging/index.ts @@ -0,0 +1,2 @@ +export * from './LogConfigurator'; +export * from './LoggingClientContext'; diff --git a/packages/core/src/mutants/MutantTestMatcher.ts b/packages/core/src/mutants/MutantTestMatcher.ts deleted file mode 100644 index 51aa904329..0000000000 --- a/packages/core/src/mutants/MutantTestMatcher.ts +++ /dev/null @@ -1,219 +0,0 @@ -import { StrykerOptions } from '@stryker-mutator/api/core'; -import { Logger } from '@stryker-mutator/api/logging'; -import { Mutant } from '@stryker-mutator/api/mutant'; -import { commonTokens, tokens } from '@stryker-mutator/api/plugin'; -import { MatchedMutant } from '@stryker-mutator/api/report'; -import { CoverageCollection, CoveragePerTestResult, CoverageResult, StatementMap } from '@stryker-mutator/api/test_runner'; -import { notEmpty } from '@stryker-mutator/util'; - -import { coreTokens } from '../di'; -import InputFileCollection from '../input/InputFileCollection'; -import { InitialTestRunResult } from '../process/InitialTestExecutor'; -import StrictReporter from '../reporters/StrictReporter'; -import SourceFile from '../SourceFile'; -import TestableMutant, { TestSelectionResult } from '../TestableMutant'; -import { CoverageMaps } from '../transpiler/CoverageInstrumenterTranspiler'; -import LocationHelper from '../utils/LocationHelper'; - -const enum StatementIndexKind { - Function, - Statement, -} - -/** - * Represents a statement index inside the coverage maps of a file - * Either the function map, or statement map - */ -interface StatementIndex { - kind: StatementIndexKind; - index: string; -} - -export class MutantTestMatcher { - public static inject = tokens(commonTokens.logger, commonTokens.options, coreTokens.reporter, coreTokens.inputFiles, coreTokens.initialRunResult); - constructor( - private readonly log: Logger, - private readonly options: StrykerOptions, - private readonly reporter: StrictReporter, - private readonly input: InputFileCollection, - private readonly initialRunResult: InitialTestRunResult - ) {} - - private get baseline(): CoverageCollection | null { - if (this.isCoveragePerTestResult(this.initialRunResult.runResult.coverage)) { - return this.initialRunResult.runResult.coverage.baseline; - } else { - return null; - } - } - - public async matchWithMutants(mutants: readonly Mutant[]): Promise { - const testableMutants = this.createTestableMutants(mutants); - - if (this.options.coverageAnalysis === 'off') { - testableMutants.forEach((mutant) => mutant.selectAllTests(this.initialRunResult.runResult, TestSelectionResult.Success)); - } else if (!this.initialRunResult.runResult.coverage) { - this.log.warn( - 'No coverage result found, even though coverageAnalysis is "%s". Assuming that all tests cover each mutant. This might have a big impact on the performance.', - this.options.coverageAnalysis - ); - testableMutants.forEach((mutant) => mutant.selectAllTests(this.initialRunResult.runResult, TestSelectionResult.FailedButAlreadyReported)); - } else { - await Promise.all(testableMutants.map((testableMutant) => this.enrichWithCoveredTests(testableMutant))); - } - this.reporter.onAllMutantsMatchedWithTests(Object.freeze(testableMutants.map(this.mapMutantOnMatchedMutant))); - return testableMutants; - } - - public async enrichWithCoveredTests(testableMutant: TestableMutant) { - const transpiledLocation = await this.initialRunResult.sourceMapper.transpiledLocationFor({ - fileName: testableMutant.mutant.fileName, - location: testableMutant.location, - }); - const fileCoverage = this.initialRunResult.coverageMaps[transpiledLocation.fileName]; - const statementIndex = this.findMatchingStatement(new LocationHelper(transpiledLocation.location), fileCoverage); - if (statementIndex) { - if (this.isCoveredByBaseline(transpiledLocation.fileName, statementIndex)) { - testableMutant.selectAllTests(this.initialRunResult.runResult, TestSelectionResult.Success); - } else { - this.initialRunResult.runResult.tests.forEach((testResult, id) => { - if (this.isCoveredByTest(id, transpiledLocation.fileName, statementIndex)) { - testableMutant.selectTest(testResult, id); - } - }); - } - } else { - // Could not find a statement corresponding to this mutant - // This can happen when for example mutating a TypeScript interface - // It should result in an early result during mutation testing - // Lets delay error reporting for now - testableMutant.selectAllTests(this.initialRunResult.runResult, TestSelectionResult.Failed); - } - } - - private isCoveredByBaseline(fileName: string, statementIndex: StatementIndex): boolean { - if (this.baseline) { - const coverageResult = this.baseline[fileName]; - return this.isCoveredByCoverageCollection(coverageResult, statementIndex); - } else { - return false; - } - } - - private isCoveredByTest(testId: number, fileName: string, statementIndex: StatementIndex): boolean { - const coverageCollection = this.findCoverageCollectionForTest(testId); - const coveredFile = coverageCollection && coverageCollection[fileName]; - return this.isCoveredByCoverageCollection(coveredFile, statementIndex); - } - - private isCoveredByCoverageCollection(coveredFile: CoverageResult | null, statementIndex: StatementIndex): boolean { - if (coveredFile) { - if (statementIndex.kind === StatementIndexKind.Statement) { - return coveredFile.s[statementIndex.index] > 0; - } else { - return coveredFile.f[statementIndex.index] > 0; - } - } else { - return false; - } - } - - private createTestableMutants(mutants: readonly Mutant[]): readonly TestableMutant[] { - const sourceFiles = this.input.filesToMutate.map((file) => new SourceFile(file)); - return mutants - .map((mutant, index) => { - const sourceFile = sourceFiles.find((file) => file.name === mutant.fileName); - if (sourceFile) { - return new TestableMutant(index.toString(), mutant, sourceFile); - } else { - this.log.error( - `Mutant "${mutant.mutatorName}${mutant.replacement}" is corrupt, because cannot find a text file with name ${ - mutant.fileName - }. List of source files: \n\t${sourceFiles.map((s) => s.name).join('\n\t')}` - ); - return null; - } - }) - .filter(notEmpty); - } - - /** - * Map the Mutant object on the MatchMutant Object. - * @param testableMutant The mutant. - * @returns The MatchedMutant - */ - private mapMutantOnMatchedMutant(testableMutant: TestableMutant): MatchedMutant { - const matchedMutant: MatchedMutant = { - fileName: testableMutant.mutant.fileName, - id: testableMutant.id, - mutatorName: testableMutant.mutant.mutatorName, - replacement: testableMutant.mutant.replacement, - runAllTests: testableMutant.runAllTests, - scopedTestIds: testableMutant.selectedTests.map((testSelection) => testSelection.id), - timeSpentScopedTests: testableMutant.timeSpentScopedTests, - }; - return Object.freeze(matchedMutant); - } - - private findMatchingStatement(location: LocationHelper, fileCoverage: CoverageMaps): StatementIndex | null { - const statementIndex = this.findMatchingStatementInMap(location, fileCoverage.statementMap); - if (statementIndex) { - return { - index: statementIndex, - kind: StatementIndexKind.Statement, - }; - } else { - const functionIndex = this.findMatchingStatementInMap(location, fileCoverage.fnMap); - if (functionIndex) { - return { - index: functionIndex, - kind: StatementIndexKind.Function, - }; - } else { - return null; - } - } - } - - /** - * Finds the smallest statement that covers a location - * @param needle The location to find. - * @param haystack the statement map or function map to search in. - * @returns The index of the smallest statement surrounding the location, or null if not found. - */ - private findMatchingStatementInMap(needle: LocationHelper, haystack: StatementMap): string | null { - let smallestStatement: { index: string | null; location: LocationHelper } = { - index: null, - location: LocationHelper.MAX_VALUE, - }; - if (haystack) { - Object.keys(haystack).forEach((statementId) => { - const statementLocation = haystack[statementId]; - - if (needle.isCoveredBy(statementLocation) && smallestStatement.location.isSmallerArea(statementLocation)) { - smallestStatement = { - index: statementId, - location: new LocationHelper(statementLocation), - }; - } - }); - } - return smallestStatement.index; - } - - private findCoverageCollectionForTest(testId: number): CoverageCollection | null { - if (this.initialRunResult.runResult.coverage) { - if (this.isCoveragePerTestResult(this.initialRunResult.runResult.coverage)) { - return this.initialRunResult.runResult.coverage.deviations[testId]; - } else { - return this.initialRunResult.runResult.coverage; - } - } else { - return null; - } - } - - private isCoveragePerTestResult(_coverage: CoverageCollection | CoveragePerTestResult | undefined): _coverage is CoveragePerTestResult { - return this.options.coverageAnalysis === 'perTest'; - } -} diff --git a/packages/core/src/mutants/MutatorFacade.ts b/packages/core/src/mutants/MutatorFacade.ts deleted file mode 100644 index bae0597229..0000000000 --- a/packages/core/src/mutants/MutatorFacade.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { File, MutatorDescriptor } from '@stryker-mutator/api/core'; -import { Logger } from '@stryker-mutator/api/logging'; -import { Mutant, Mutator } from '@stryker-mutator/api/mutant'; -import { commonTokens, PluginKind, tokens } from '@stryker-mutator/api/plugin'; - -import { coreTokens, PluginCreator } from '../di'; - -export class MutatorFacade implements Mutator { - public static inject = tokens(commonTokens.mutatorDescriptor, coreTokens.pluginCreatorMutator, commonTokens.logger); - constructor( - private readonly mutatorDescriptor: MutatorDescriptor, - private readonly pluginCreator: PluginCreator, - private readonly log: Logger - ) {} - - public mutate(inputFiles: readonly File[]): readonly Mutant[] { - const allMutants = this.pluginCreator.create(this.getMutatorName(this.mutatorDescriptor.name)).mutate(inputFiles); - const includedMutants = this.removeExcludedMutants(allMutants); - this.logMutantCount(includedMutants.length, allMutants.length); - return includedMutants; - } - - private removeExcludedMutants(mutants: readonly Mutant[]): readonly Mutant[] { - if (this.mutatorDescriptor.excludedMutations.length) { - return mutants.filter((mutant) => !this.mutatorDescriptor.excludedMutations.includes(mutant.mutatorName)); - } else { - return mutants; - } - } - - private getMutatorName(mutator: string | MutatorDescriptor) { - if (typeof mutator === 'string') { - return mutator; - } else { - return mutator.name; - } - } - - private logMutantCount(includedMutantCount: number, totalMutantCount: number) { - let mutantCountMessage; - if (includedMutantCount) { - mutantCountMessage = `${includedMutantCount} Mutant(s) generated`; - } else { - mutantCountMessage = "It's a mutant-free world, nothing to test."; - } - const numberExcluded = totalMutantCount - includedMutantCount; - if (numberExcluded) { - mutantCountMessage += ` (${numberExcluded} Mutant(s) excluded)`; - } - this.log.info(mutantCountMessage); - } -} diff --git a/packages/core/src/mutants/findMutantTestCoverage.ts b/packages/core/src/mutants/findMutantTestCoverage.ts new file mode 100644 index 0000000000..fe41d5314a --- /dev/null +++ b/packages/core/src/mutants/findMutantTestCoverage.ts @@ -0,0 +1,123 @@ +import { CompleteDryRunResult, TestResult } from '@stryker-mutator/api/test_runner'; +import { Mutant, CoveragePerTestId } from '@stryker-mutator/api/core'; +import { commonTokens, tokens } from '@stryker-mutator/api/plugin'; + +import { MatchedMutant } from '@stryker-mutator/api/report'; + +import { Logger } from '@stryker-mutator/api/logging'; + +import { coreTokens } from '../di'; +import StrictReporter from '../reporters/StrictReporter'; + +export interface MutantTestCoverage { + estimatedNetTime: number; + coveredByTests: boolean; + testFilter?: string[]; + mutant: Mutant; +} + +findMutantTestCoverage.inject = tokens(coreTokens.dryRunResult, coreTokens.mutants, coreTokens.reporter, commonTokens.logger); +export function findMutantTestCoverage( + dryRunResult: CompleteDryRunResult, + mutants: readonly Mutant[], + reporter: StrictReporter, + logger: Logger +): MutantTestCoverage[] { + const mutantTestCoverage = mapToMutantTestCoverage(dryRunResult, mutants, logger); + reporter.onAllMutantsMatchedWithTests(mutantTestCoverage.map(toMatchedMutant)); + return mutantTestCoverage; +} + +function toMatchedMutant({ mutant, testFilter, coveredByTests, estimatedNetTime }: MutantTestCoverage): MatchedMutant { + return { + fileName: mutant.fileName, + id: mutant.id.toString(), + mutatorName: mutant.mutatorName, + replacement: mutant.replacement, + runAllTests: !testFilter && coveredByTests, + testFilter: testFilter, + timeSpentScopedTests: estimatedNetTime, + }; +} + +function mapToMutantTestCoverage(dryRunResult: CompleteDryRunResult, mutants: readonly Mutant[], logger: Logger) { + const testsByMutantId = findTestsByMutant(dryRunResult.mutantCoverage?.perTest, dryRunResult.tests, logger); + const timeSpentAllTests = calculateTotalTime(dryRunResult.tests); + + const mutantCoverage = mutants.map((mutant) => { + if (mutant.ignoreReason !== undefined) { + return { + mutant, + estimatedNetTime: 0, + coveredByTests: false, + }; + } else if (!dryRunResult.mutantCoverage || dryRunResult.mutantCoverage.static[mutant.id] > 0) { + return { + mutant, + estimatedNetTime: timeSpentAllTests, + testFilter: undefined, + coveredByTests: true, + }; + } else { + const tests = testsByMutantId.get(mutant.id); + if (tests && tests.size > 0) { + return { + mutant, + estimatedNetTime: calculateTotalTime(tests), + testFilter: toTestIds(tests), + coveredByTests: true, + }; + } else { + return { + mutant, + estimatedNetTime: 0, + testFilter: undefined, + coveredByTests: false, + }; + } + } + }); + return mutantCoverage; +} + +function findTestsByMutant(coveragePerTest: CoveragePerTestId | undefined, allTests: TestResult[], logger: Logger) { + const testsByMutantId = new Map>(); + coveragePerTest && + Object.entries(coveragePerTest).forEach(([testId, mutantCoverage]) => { + const test = allTests.find((test) => test.id === testId); + if (!test) { + logger.debug( + `Found test with id "${testId}" in coverage data, but not in the test results of the dry run. Not taking coverage data for this test into account` + ); + return; + } + Object.entries(mutantCoverage).forEach(([mutantIdAsString, count]) => { + if (count) { + const mutantId = parseInt(mutantIdAsString, 10); + let tests = testsByMutantId.get(mutantId); + if (!tests) { + tests = new Set(); + testsByMutantId.set(mutantId, tests); + } + tests.add(test); + } + }); + }); + return testsByMutantId; +} + +function calculateTotalTime(testResults: Iterable): number { + let total = 0; + for (const test of testResults) { + total += test.timeSpentMs; + } + return total; +} + +function toTestIds(testResults: Iterable): string[] { + const result = []; + for (const test of testResults) { + result.push(test.id); + } + return result; +} diff --git a/packages/core/src/mutants/index.ts b/packages/core/src/mutants/index.ts new file mode 100644 index 0000000000..309c98c172 --- /dev/null +++ b/packages/core/src/mutants/index.ts @@ -0,0 +1 @@ +export * from './findMutantTestCoverage'; diff --git a/packages/core/src/process/1-PrepareExecutor.ts b/packages/core/src/process/1-PrepareExecutor.ts new file mode 100644 index 0000000000..a59ecc51ae --- /dev/null +++ b/packages/core/src/process/1-PrepareExecutor.ts @@ -0,0 +1,29 @@ +import { PartialStrykerOptions } from '@stryker-mutator/api/core'; +import { commonTokens, Injector, tokens } from '@stryker-mutator/api/plugin'; + +import { LogConfigurator } from '../logging'; +import { buildMainInjector, coreTokens, CliOptionsProvider } from '../di'; +import InputFileResolver from '../input/InputFileResolver'; +import { ConfigError } from '../errors'; + +import { MutantInstrumenterContext } from '.'; + +export class PrepareExecutor { + public static readonly inject = tokens(coreTokens.cliOptions, commonTokens.injector); + constructor(private readonly cliOptions: PartialStrykerOptions, private readonly injector: CliOptionsProvider) {} + + public async execute(): Promise> { + LogConfigurator.configureMainProcess(this.cliOptions.logLevel, this.cliOptions.fileLogLevel, this.cliOptions.allowConsoleColors); + const mainInjector = buildMainInjector(this.injector); + mainInjector.resolve(coreTokens.timer).reset(); + const options = mainInjector.resolve(commonTokens.options); + const loggingContext = await LogConfigurator.configureLoggingServer(options.logLevel, options.fileLogLevel, options.allowConsoleColors); + const inputFiles = await mainInjector.injectClass(InputFileResolver).resolve(); + if (inputFiles.files.length) { + mainInjector.resolve(coreTokens.temporaryDirectory).initialize(); + return mainInjector.provideValue(coreTokens.inputFiles, inputFiles).provideValue(coreTokens.loggingContext, loggingContext); + } else { + throw new ConfigError('No input files found.'); + } + } +} diff --git a/packages/core/src/process/2-MutantInstrumenterExecutor.ts b/packages/core/src/process/2-MutantInstrumenterExecutor.ts new file mode 100644 index 0000000000..7087a71ac8 --- /dev/null +++ b/packages/core/src/process/2-MutantInstrumenterExecutor.ts @@ -0,0 +1,66 @@ +import { Injector, tokens, commonTokens } from '@stryker-mutator/api/plugin'; +import { Instrumenter, InstrumentResult } from '@stryker-mutator/instrumenter'; +import { File, StrykerOptions } from '@stryker-mutator/api/core'; + +import { MainContext, coreTokens } from '../di'; +import InputFileCollection from '../input/InputFileCollection'; +import { Sandbox } from '../sandbox/sandbox'; +import { LoggingClientContext } from '../logging'; + +import { ConcurrencyTokenProvider, createCheckerPool } from '../concurrent'; +import { createCheckerFactory } from '../checker/CheckerFacade'; +import { createPreprocessor } from '../sandbox'; + +import { DryRunContext } from './3-DryRunExecutor'; + +export interface MutantInstrumenterContext extends MainContext { + [coreTokens.inputFiles]: InputFileCollection; + [coreTokens.loggingContext]: LoggingClientContext; +} + +export class MutantInstrumenterExecutor { + public static readonly inject = tokens(commonTokens.injector, coreTokens.inputFiles, commonTokens.options); + constructor( + private readonly injector: Injector, + private readonly inputFiles: InputFileCollection, + private readonly options: StrykerOptions + ) {} + + public async execute(): Promise> { + // Create the checker and instrumenter + const instrumenter = this.injector.injectClass(Instrumenter); + + // Instrument files in-memory + const instrumentResult = await instrumenter.instrument(this.inputFiles.filesToMutate, this.options.mutator); + + // Preprocess sandbox files + const preprocess = this.injector.injectFunction(createPreprocessor); + const files = await preprocess.preprocess(this.replaceInstrumentedFiles(instrumentResult)); + + // Initialize the checker pool + const concurrencyTokenProviderProvider = this.injector.provideClass(coreTokens.concurrencyTokenProvider, ConcurrencyTokenProvider); + const concurrencyTokenProvider = concurrencyTokenProviderProvider.resolve(coreTokens.concurrencyTokenProvider); + + const checkerPoolProvider = concurrencyTokenProviderProvider + .provideValue(coreTokens.checkerConcurrencyTokens, concurrencyTokenProvider.checkerToken$) + .provideFactory(coreTokens.checkerFactory, createCheckerFactory) + .provideFactory(coreTokens.checkerPool, createCheckerPool); + const checkerPool = checkerPoolProvider.resolve(coreTokens.checkerPool); + await checkerPool.init(); + + // Feed the sandbox + const sandbox = await this.injector.provideValue(coreTokens.files, files).injectFunction(Sandbox.create); + return checkerPoolProvider.provideValue(coreTokens.sandbox, sandbox).provideValue(coreTokens.mutants, instrumentResult.mutants); + } + + private replaceInstrumentedFiles(instrumentResult: InstrumentResult): File[] { + return this.inputFiles.files.map((inputFile) => { + const instrumentedFile = instrumentResult.files.find((instrumentedFile) => instrumentedFile.name === inputFile.name); + if (instrumentedFile) { + return instrumentedFile; + } else { + return inputFile; + } + }); + } +} diff --git a/packages/core/src/process/3-DryRunExecutor.ts b/packages/core/src/process/3-DryRunExecutor.ts new file mode 100644 index 0000000000..d22c56bfa1 --- /dev/null +++ b/packages/core/src/process/3-DryRunExecutor.ts @@ -0,0 +1,181 @@ +import { EOL } from 'os'; + +import { Injector } from 'typed-inject'; +import { I } from '@stryker-mutator/util'; +import { Logger } from '@stryker-mutator/api/logging'; +import { commonTokens, tokens } from '@stryker-mutator/api/plugin'; +import { StrykerOptions, Mutant } from '@stryker-mutator/api/core'; +import { + DryRunResult, + TestRunner, + DryRunStatus, + CompleteDryRunResult, + TestStatus, + TestResult, + FailedTestResult, + ErrorDryRunResult, +} from '@stryker-mutator/api/test_runner'; +import { first } from 'rxjs/operators'; + +import { Checker } from '@stryker-mutator/api/check'; + +import { coreTokens } from '../di'; +import { Sandbox } from '../sandbox/sandbox'; +import Timer from '../utils/Timer'; +import { createTestRunnerFactory } from '../test-runner'; +import { MutationTestReportHelper } from '../reporters/MutationTestReportHelper'; +import { ConfigError } from '../errors'; +import { findMutantTestCoverage } from '../mutants'; +import { Pool, createTestRunnerPool } from '../concurrent/pool'; +import { ConcurrencyTokenProvider } from '../concurrent'; + +import { MutationTestContext } from './4-MutationTestExecutor'; +import { MutantInstrumenterContext } from './2-MutantInstrumenterExecutor'; + +// The initial run might take a while. +// For example: angular-bootstrap takes up to 45 seconds. +// Lets take 5 minutes just to be sure +const INITIAL_RUN_TIMEOUT = 60 * 1000 * 5; +const INITIAL_TEST_RUN_MARKER = 'Initial test run'; + +export interface DryRunContext extends MutantInstrumenterContext { + [coreTokens.sandbox]: Sandbox; + [coreTokens.mutants]: readonly Mutant[]; + [coreTokens.checkerPool]: I>; + [coreTokens.concurrencyTokenProvider]: I; +} + +/** + * A small object that keeps the timing variables of a test run. + */ +interface Timing { + /** + * The time that the test runner was actually executing tests in milliseconds. + */ + net: number; + /** + * the time that was spend not executing tests in milliseconds. + * So the time it took to start the test runner and to report the result. + */ + overhead: number; + + /** + * The total time spent (net + overhead) in a human readable format + */ + humanReadableTimeElapsed: string; +} + +function isFailedTest(testResult: TestResult): testResult is FailedTestResult { + return testResult.status === TestStatus.Failed; +} + +export class DryRunExecutor { + public static readonly inject = tokens( + commonTokens.injector, + commonTokens.logger, + commonTokens.options, + coreTokens.timer, + coreTokens.concurrencyTokenProvider + ); + + constructor( + private readonly injector: Injector, + private readonly log: Logger, + private readonly options: StrykerOptions, + private readonly timer: I, + private readonly concurrencyTokenProvider: I + ) {} + + public async execute(): Promise> { + const testRunnerInjector = this.injector + .provideFactory(coreTokens.testRunnerFactory, createTestRunnerFactory) + .provideValue(coreTokens.testRunnerConcurrencyTokens, this.concurrencyTokenProvider.testRunnerToken$) + .provideFactory(coreTokens.testRunnerPool, createTestRunnerPool); + const testRunnerPool = testRunnerInjector.resolve(coreTokens.testRunnerPool); + const testRunner = await testRunnerPool.worker$.pipe(first()).toPromise(); + const { dryRunResult, timing } = await this.timeDryRun(testRunner); + this.logInitialTestRunSucceeded(dryRunResult.tests, timing); + if (!dryRunResult.tests.length) { + throw new ConfigError('No tests were executed. Stryker will exit prematurely. Please check your configuration.'); + } + return testRunnerInjector + .provideValue(coreTokens.timeOverheadMS, timing.overhead) + .provideValue(coreTokens.dryRunResult, dryRunResult) + .provideClass(coreTokens.mutationTestReportHelper, MutationTestReportHelper) + .provideFactory(coreTokens.mutantsWithTestCoverage, findMutantTestCoverage); + } + + private validateResultCompleted(runResult: DryRunResult): asserts runResult is CompleteDryRunResult { + switch (runResult.status) { + case DryRunStatus.Complete: + const failedTests = runResult.tests.filter(isFailedTest); + if (failedTests.length) { + this.logFailedTestsInInitialRun(failedTests); + throw new ConfigError('There were failed tests in the initial test run.'); + } + return; + case DryRunStatus.Error: + this.logErrorsInInitialRun(runResult); + break; + case DryRunStatus.Timeout: + this.logTimeoutInitialRun(); + break; + } + throw new Error('Something went wrong in the initial test run'); + } + + private async timeDryRun(testRunner: TestRunner): Promise<{ dryRunResult: CompleteDryRunResult; timing: Timing }> { + this.timer.mark(INITIAL_TEST_RUN_MARKER); + this.log.info('Starting initial test run. This may take a while.'); + const dryRunResult = await testRunner.dryRun({ timeout: INITIAL_RUN_TIMEOUT, coverageAnalysis: this.options.coverageAnalysis }); + const grossTimeMS = this.timer.elapsedMs(INITIAL_TEST_RUN_MARKER); + const humanReadableTimeElapsed = this.timer.humanReadableElapsed(INITIAL_TEST_RUN_MARKER); + this.validateResultCompleted(dryRunResult); + const timing = this.calculateTiming(grossTimeMS, humanReadableTimeElapsed, dryRunResult.tests); + return { dryRunResult, timing }; + } + + private logInitialTestRunSucceeded(tests: TestResult[], timing: Timing) { + this.log.info( + 'Initial test run succeeded. Ran %s tests in %s (net %s ms, overhead %s ms).', + tests.length, + timing.humanReadableTimeElapsed, + timing.net, + timing.overhead + ); + } + + /** + * Calculates the timing variables for the test run. + * grossTime = NetTime + overheadTime + * + * The overhead time is used to calculate exact timeout values during mutation testing. + * See timeoutMS setting in README for more information on this calculation + */ + private calculateTiming(grossTimeMS: number, humanReadableTimeElapsed: string, tests: readonly TestResult[]): Timing { + const netTimeMS = tests.reduce((total, test) => total + test.timeSpentMs, 0); + const overheadTimeMS = grossTimeMS - netTimeMS; + return { + net: netTimeMS, + overhead: overheadTimeMS < 0 ? 0 : overheadTimeMS, + humanReadableTimeElapsed, + }; + } + + private logFailedTestsInInitialRun(failedTests: FailedTestResult[]): void { + let message = 'One or more tests failed in the initial test run:'; + failedTests.forEach((test) => { + message += `${EOL}\t${test.name}`; + message += `${EOL}\t\t${test.failureMessage}`; + }); + this.log.error(message); + } + private logErrorsInInitialRun(runResult: ErrorDryRunResult) { + let message = `One or more tests resulted in an error:${EOL}\t${runResult.errorMessage}`; + this.log.error(message); + } + + private logTimeoutInitialRun() { + this.log.error('Initial test run timed out!'); + } +} diff --git a/packages/core/src/process/4-MutationTestExecutor.ts b/packages/core/src/process/4-MutationTestExecutor.ts new file mode 100644 index 0000000000..5ebc356da1 --- /dev/null +++ b/packages/core/src/process/4-MutationTestExecutor.ts @@ -0,0 +1,140 @@ +import { from, zip, partition, merge, Observable } from 'rxjs'; +import { flatMap, toArray, map, tap, shareReplay } from 'rxjs/operators'; +import { tokens, commonTokens } from '@stryker-mutator/api/plugin'; +import { StrykerOptions } from '@stryker-mutator/api/core'; +import { MutantResult } from '@stryker-mutator/api/report'; +import { MutantRunOptions, TestRunner } from '@stryker-mutator/api/test_runner'; +import { Logger } from '@stryker-mutator/api/logging'; +import { I } from '@stryker-mutator/util'; +import { CheckStatus, Checker, CheckResult, PassedCheckResult } from '@stryker-mutator/api/check'; + +import { coreTokens } from '../di'; +import StrictReporter from '../reporters/StrictReporter'; +import { MutantTestCoverage } from '../mutants/findMutantTestCoverage'; +import { MutationTestReportHelper } from '../reporters/MutationTestReportHelper'; +import Timer from '../utils/Timer'; +import { Pool, ConcurrencyTokenProvider } from '../concurrent'; +import { Sandbox } from '../sandbox'; + +import { DryRunContext } from './3-DryRunExecutor'; + +export interface MutationTestContext extends DryRunContext { + [coreTokens.testRunnerPool]: I>; + [coreTokens.timeOverheadMS]: number; + [coreTokens.mutationTestReportHelper]: MutationTestReportHelper; + [coreTokens.mutantsWithTestCoverage]: MutantTestCoverage[]; +} + +export class MutationTestExecutor { + public static inject = tokens( + commonTokens.options, + coreTokens.reporter, + coreTokens.checkerPool, + coreTokens.testRunnerPool, + coreTokens.timeOverheadMS, + coreTokens.mutantsWithTestCoverage, + coreTokens.mutationTestReportHelper, + coreTokens.sandbox, + commonTokens.logger, + coreTokens.timer, + coreTokens.concurrencyTokenProvider + ); + + constructor( + private readonly options: StrykerOptions, + private readonly reporter: StrictReporter, + private readonly checkerPool: I>, + private readonly testRunnerPool: I>, + private readonly timeOverheadMS: number, + private readonly matchedMutants: readonly MutantTestCoverage[], + private readonly mutationTestReportHelper: I, + private readonly sandbox: I, + private readonly log: Logger, + private readonly timer: I, + private readonly concurrencyTokenProvider: I + ) {} + + public async execute(): Promise { + const { ignoredResult$, notIgnoredMutant$ } = this.executeIgnore(from(this.matchedMutants)); + const { passedMutant$, checkResult$ } = this.executeCheck(from(notIgnoredMutant$)); + const { coveredMutant$, noCoverageResult$ } = this.executeNoCoverage(passedMutant$); + const testRunnerResult$ = this.executeRunInTestRunner(coveredMutant$); + const results = await merge(testRunnerResult$, checkResult$, noCoverageResult$, ignoredResult$).pipe(toArray()).toPromise(); + this.mutationTestReportHelper.reportAll(results); + await this.reporter.wrapUp(); + this.logDone(); + return results; + } + + private executeIgnore(input$: Observable) { + const [notIgnoredMutant$, ignoredMutant$] = partition(input$.pipe(shareReplay()), ({ mutant }) => mutant.ignoreReason === undefined); + const ignoredResult$ = ignoredMutant$.pipe(map(({ mutant }) => this.mutationTestReportHelper.reportMutantIgnored(mutant))); + return { ignoredResult$, notIgnoredMutant$ }; + } + + private executeNoCoverage(input$: Observable) { + const [coveredMutant$, noCoverageMatchedMutant$] = partition(input$.pipe(shareReplay()), (matchedMutant) => matchedMutant.coveredByTests); + const noCoverageResult$ = noCoverageMatchedMutant$.pipe(map(({ mutant }) => this.mutationTestReportHelper.reportNoCoverage(mutant))); + return { noCoverageResult$, coveredMutant$ }; + } + + private executeCheck(input$: Observable) { + const checkTask$ = zip(input$, this.checkerPool.worker$).pipe( + flatMap(async ([matchedMutant, checker]) => { + const checkResult = await checker.check(matchedMutant.mutant); + this.checkerPool.recycle(checker); + return { + checkResult, + matchedMutant, + }; + }), + // Dispose when all checks are completed. + // This will allow resources to be freed up and more test runners to be spined up. + tap({ + complete: () => { + this.checkerPool.dispose(); + this.concurrencyTokenProvider.freeCheckers(); + }, + }) + ); + const [passedCheckResult$, failedCheckResult$] = partition( + checkTask$.pipe(shareReplay()), + ({ checkResult }) => checkResult.status === CheckStatus.Passed + ); + const checkResult$ = failedCheckResult$.pipe( + map((failedMutant) => + this.mutationTestReportHelper.reportCheckFailed( + failedMutant.matchedMutant.mutant, + failedMutant.checkResult as Exclude + ) + ) + ); + const passedMutant$ = passedCheckResult$.pipe(map(({ matchedMutant }) => matchedMutant)); + return { checkResult$, passedMutant$ }; + } + + private executeRunInTestRunner(input$: Observable): Observable { + return zip(this.testRunnerPool.worker$, input$).pipe( + flatMap(async ([testRunner, matchedMutant]) => { + const mutantRunOptions = this.createMutantRunOptions(matchedMutant); + const result = await testRunner.mutantRun(mutantRunOptions); + this.testRunnerPool.recycle(testRunner); + return this.mutationTestReportHelper.reportMutantRunResult(matchedMutant, result); + }) + ); + } + + private createMutantRunOptions(mutant: MutantTestCoverage): MutantRunOptions { + const timeout = this.options.timeoutFactor * mutant.estimatedNetTime + this.options.timeoutMS + this.timeOverheadMS; + return { + activeMutant: mutant.mutant, + timeout: timeout, + testFilter: mutant.testFilter, + sandboxFileName: this.sandbox.sandboxFileFor(mutant.mutant.fileName), + }; + } + + private logDone() { + this.log.info('Done in %s.', this.timer.humanReadableElapsed()); + } +} diff --git a/packages/core/src/process/InitialTestExecutor.ts b/packages/core/src/process/InitialTestExecutor.ts deleted file mode 100644 index 5248b9dc42..0000000000 --- a/packages/core/src/process/InitialTestExecutor.ts +++ /dev/null @@ -1,222 +0,0 @@ -import { EOL } from 'os'; - -import { File, StrykerOptions } from '@stryker-mutator/api/core'; -import { Logger } from '@stryker-mutator/api/logging'; -import { commonTokens, tokens } from '@stryker-mutator/api/plugin'; -import { TestFramework } from '@stryker-mutator/api/test_framework'; -import { RunResult, RunStatus, TestResult, TestStatus } from '@stryker-mutator/api/test_runner'; -import { Transpiler } from '@stryker-mutator/api/transpile'; - -import { coreTokens } from '../di'; -import InputFileCollection from '../input/InputFileCollection'; -import LoggingClientContext from '../logging/LoggingClientContext'; -import Sandbox from '../Sandbox'; -import { coveragePerTestHooks } from '../transpiler/coverageHooks'; -import CoverageInstrumenterTranspiler, { CoverageMapsByFile } from '../transpiler/CoverageInstrumenterTranspiler'; -import SourceMapper from '../transpiler/SourceMapper'; -import { TemporaryDirectory } from '../utils/TemporaryDirectory'; -import Timer from '../utils/Timer'; - -// The initial run might take a while. -// For example: angular-bootstrap takes up to 45 seconds. -// Lets take 5 minutes just to be sure -const INITIAL_RUN_TIMEOUT = 60 * 1000 * 5; -const INITIAL_TEST_RUN_MARKER = 'Initial test run'; - -export interface InitialTestRunResult { - runResult: RunResult; - overheadTimeMS: number; - sourceMapper: SourceMapper; - coverageMaps: CoverageMapsByFile; -} - -/** - * A small object that keeps the timing variables of a test run. - */ -interface Timing { - /** - * The time that the test runner was actually executing tests in milliseconds. - */ - net: number; - /** - * the time that was spend not executing tests in milliseconds. - * So the time it took to start the test runner and to report the result. - */ - overhead: number; -} - -export default class InitialTestExecutor { - public static inject = tokens( - commonTokens.options, - commonTokens.logger, - coreTokens.inputFiles, - coreTokens.testFramework, - coreTokens.timer, - coreTokens.loggingContext, - coreTokens.transpiler, - coreTokens.temporaryDirectory - ); - - constructor( - private readonly options: StrykerOptions, - private readonly log: Logger, - private readonly inputFiles: InputFileCollection, - private readonly testFramework: TestFramework | null, - private readonly timer: Timer, - private readonly loggingContext: LoggingClientContext, - private readonly transpiler: Transpiler, - private readonly tempDir: TemporaryDirectory - ) {} - - public async run(): Promise { - this.log.info('Starting initial test run. This may take a while.'); - - // Before we can run the tests we transpile the input files. - // Files that are not transpiled should pass through without transpiling - const transpiledFiles = await this.transpiler.transpile(this.inputFiles.files); - - // Now that we have the transpiled files, we create a source mapper so - // we can figure out which files we need to annotate for code coverage - const sourceMapper = SourceMapper.create(transpiledFiles, this.options); - - // Annotate the transpiled files for code coverage. This allows the - // test runner to report code coverage (if `coverageAnalysis` is enabled) - const { coverageMaps, instrumentedFiles } = await this.annotateForCodeCoverage(transpiledFiles, sourceMapper); - this.logTranspileResult(instrumentedFiles); - - const { runResult, grossTimeMS } = await this.runInSandbox(instrumentedFiles); - const timing = this.calculateTiming(grossTimeMS, runResult.tests); - this.validateResult(runResult, timing); - return { - coverageMaps, - overheadTimeMS: timing.overhead, - runResult, - sourceMapper, - }; - } - - private async runInSandbox(files: readonly File[]): Promise<{ runResult: RunResult; grossTimeMS: number }> { - const sandbox = await Sandbox.create(this.options, 0, files, this.testFramework, 0, this.loggingContext, this.tempDir); - this.timer.mark(INITIAL_TEST_RUN_MARKER); - const runResult = await sandbox.run(INITIAL_RUN_TIMEOUT, this.getCollectCoverageHooksIfNeeded()); - const grossTimeMS = this.timer.elapsedMs(INITIAL_TEST_RUN_MARKER); - await sandbox.dispose(); - return { runResult, grossTimeMS }; - } - - private async annotateForCodeCoverage( - files: readonly File[], - sourceMapper: SourceMapper - ): Promise<{ instrumentedFiles: readonly File[]; coverageMaps: CoverageMapsByFile }> { - const filesToInstrument = this.inputFiles.filesToMutate.map((mutateFile) => sourceMapper.transpiledFileNameFor(mutateFile.name)); - const coverageInstrumenterTranspiler = new CoverageInstrumenterTranspiler(this.options, filesToInstrument); - const instrumentedFiles = await coverageInstrumenterTranspiler.transpile(files); - return { coverageMaps: coverageInstrumenterTranspiler.fileCoverageMaps, instrumentedFiles }; - } - - private validateResult(runResult: RunResult, timing: Timing): void { - switch (runResult.status) { - case RunStatus.Complete: - const failedTests = this.filterOutFailedTests(runResult); - if (failedTests.length) { - this.logFailedTestsInInitialRun(failedTests); - throw new Error('There were failed tests in the initial test run.'); - } - if (runResult.tests.length === 0) { - this.log.warn('No tests were executed. Stryker will exit prematurely. Please check your configuration.'); - return; - } else { - this.logInitialTestRunSucceeded(runResult.tests, timing); - return; - } - case RunStatus.Error: - this.logErrorsInInitialRun(runResult); - break; - case RunStatus.Timeout: - this.logTimeoutInitialRun(runResult); - break; - } - throw new Error('Something went wrong in the initial test run'); - } - - /** - * Calculates the timing variables for the test run. - * grossTime = NetTime + overheadTime - * - * The overhead time is used to calculate exact timeout values during mutation testing. - * See timeoutMS setting in README for more information on this calculation - */ - private calculateTiming(grossTimeMS: number, tests: readonly TestResult[]): Timing { - const netTimeMS = tests.reduce((total, test) => total + test.timeSpentMs, 0); - const overheadTimeMS = grossTimeMS - netTimeMS; - return { - net: netTimeMS, - overhead: overheadTimeMS < 0 ? 0 : overheadTimeMS, - }; - } - - private getCollectCoverageHooksIfNeeded(): string | undefined { - if (this.options.coverageAnalysis === 'perTest') { - if (this.testFramework) { - // Add piece of javascript to collect coverage per test results - this.log.debug('Adding test hooks for coverageAnalysis "perTest".'); - return coveragePerTestHooks(this.testFramework); - } else { - this.log.warn( - 'Cannot measure coverage results per test, there is no testFramework and thus no way of executing code right before and after each test.' - ); - } - } - return undefined; - } - - private logTranspileResult(transpiledFiles: readonly File[]) { - if (this.options.transpilers.length && this.log.isDebugEnabled()) { - this.log.debug( - `Transpiled files: ${JSON.stringify( - transpiledFiles.map((f) => `${f.name}`), - null, - 2 - )}` - ); - } - } - - private filterOutFailedTests(runResult: RunResult) { - return runResult.tests.filter((testResult) => testResult.status === TestStatus.Failed); - } - - private logInitialTestRunSucceeded(tests: TestResult[], timing: Timing) { - this.log.info( - 'Initial test run succeeded. Ran %s tests in %s (net %s ms, overhead %s ms).', - tests.length, - this.timer.humanReadableElapsed(), - timing.net, - timing.overhead - ); - } - - private logFailedTestsInInitialRun(failedTests: TestResult[]): void { - let message = 'One or more tests failed in the initial test run:'; - failedTests.forEach((test) => { - message += `${EOL}\t${test.name}`; - if (test.failureMessages && test.failureMessages.length) { - message += `${EOL}\t\t${test.failureMessages.join(`${EOL}\t\t`)}`; - } - }); - this.log.error(message); - } - private logErrorsInInitialRun(runResult: RunResult) { - let message = 'One or more tests resulted in an error:'; - if (runResult.errorMessages && runResult.errorMessages.length) { - runResult.errorMessages.forEach((error) => (message += `${EOL}\t${error}`)); - } - this.log.error(message); - } - - private logTimeoutInitialRun(runResult: RunResult) { - let message = 'Initial test run timed out! Ran following tests before timeout:'; - runResult.tests.forEach((test) => (message += `${EOL}\t${test.name} (${TestStatus[test.status]})`)); - this.log.error(message); - } -} diff --git a/packages/core/src/process/MutationTestExecutor.ts b/packages/core/src/process/MutationTestExecutor.ts deleted file mode 100644 index 8a730b1a6e..0000000000 --- a/packages/core/src/process/MutationTestExecutor.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { tokens } from '@stryker-mutator/api/plugin'; -import { MutantResult } from '@stryker-mutator/api/report'; -import { tap, toArray } from 'rxjs/operators'; - -import { coreTokens } from '../di'; -import StrictReporter from '../reporters/StrictReporter'; -import { SandboxPool } from '../SandboxPool'; -import TestableMutant from '../TestableMutant'; -import { MutantTranspileScheduler } from '../transpiler/MutantTranspileScheduler'; - -export class MutationTestExecutor { - public static inject = tokens(coreTokens.reporter, coreTokens.mutantTranspileScheduler, coreTokens.sandboxPool); - constructor( - private readonly reporter: StrictReporter, - private readonly mutantTranspileScheduler: MutantTranspileScheduler, - private readonly sandboxPool: SandboxPool - ) {} - - public async run(allMutants: readonly TestableMutant[]): Promise { - const results = await this.sandboxPool - .runMutants(this.mutantTranspileScheduler.scheduleTranspileMutants(allMutants)) - .pipe( - tap(this.reportResult), - // Signal the mutant transpiler that there is another slot open for transpiling - tap(this.mutantTranspileScheduler.scheduleNext), - toArray(), - tap(this.reportAll) - ) - .toPromise(); - - return results; - } - - private readonly reportResult = (mutantResult: MutantResult): void => { - this.reporter.onMutantTested(mutantResult); - }; - - private readonly reportAll = (mutantResults: MutantResult[]): void => { - this.reporter.onAllMutantsTested(mutantResults); - }; -} diff --git a/packages/core/src/process/index.ts b/packages/core/src/process/index.ts new file mode 100644 index 0000000000..2578387f72 --- /dev/null +++ b/packages/core/src/process/index.ts @@ -0,0 +1,4 @@ +export * from './1-PrepareExecutor'; +export * from './2-MutantInstrumenterExecutor'; +export * from './3-DryRunExecutor'; +export * from './4-MutationTestExecutor'; diff --git a/packages/core/src/reporters/BroadcastReporter.ts b/packages/core/src/reporters/BroadcastReporter.ts index 9ce51a947a..bfd9685367 100644 --- a/packages/core/src/reporters/BroadcastReporter.ts +++ b/packages/core/src/reporters/BroadcastReporter.ts @@ -44,7 +44,7 @@ export default class BroadcastReporter implements StrictReporter { } } - private broadcast(methodName: keyof Reporter, eventArgs: any): Promise { + private broadcast(methodName: keyof Reporter, eventArgs: any): Promise { return Promise.all( Object.keys(this.reporters).map(async (reporterName) => { const reporter = this.reporters[reporterName]; diff --git a/packages/core/src/reporters/ClearTextReporter.ts b/packages/core/src/reporters/ClearTextReporter.ts index c821bdd0ea..679f0d167e 100644 --- a/packages/core/src/reporters/ClearTextReporter.ts +++ b/packages/core/src/reporters/ClearTextReporter.ts @@ -1,14 +1,13 @@ import * as os from 'os'; +import chalk = require('chalk'); import { Position, StrykerOptions } from '@stryker-mutator/api/core'; import { Logger } from '@stryker-mutator/api/logging'; import { commonTokens } from '@stryker-mutator/api/plugin'; -import { MutantResult, MutantStatus, mutationTestReportSchema, Reporter } from '@stryker-mutator/api/report'; +import { MutantResult, MutantStatus, mutationTestReportSchema, Reporter, UndetectedMutantResult } from '@stryker-mutator/api/report'; import { calculateMetrics } from 'mutation-testing-metrics'; import { tokens } from 'typed-inject'; -import chalk = require('chalk'); - import ClearTextScoreTable from './ClearTextScoreTable'; export default class ClearTextReporter implements Reporter { @@ -33,45 +32,31 @@ export default class ClearTextReporter implements Reporter { this.writeLine(); let totalTests = 0; - // use these fn's in order to preserve the 'this` pointer + // use these functions in order to preserve the 'this` pointer const logDebugFn = (input: string) => this.log.debug(input); const writeLineFn = (input: string) => this.writeLine(input); - mutantResults.forEach((result, index) => { - if (result.testsRan) { - totalTests += result.testsRan.length; - } + mutantResults.forEach((result) => { + totalTests += result.nrOfTestsRan; switch (result.status) { case MutantStatus.Killed: - this.log.debug(chalk.bold.green('Mutant killed!')); - this.logMutantResult(result, index, logDebugFn); - break; case MutantStatus.TimedOut: - this.log.debug(chalk.bold.yellow('Mutant timed out!')); - this.logMutantResult(result, index, logDebugFn); - break; case MutantStatus.RuntimeError: - this.log.debug(chalk.bold.yellow('Mutant caused a runtime error!')); - this.logMutantResult(result, index, logDebugFn); - break; - case MutantStatus.TranspileError: - this.log.debug(chalk.bold.yellow('Mutant caused a transpile error!')); - this.logMutantResult(result, index, logDebugFn); + case MutantStatus.CompileError: + this.logMutantResult(result, logDebugFn); break; case MutantStatus.Survived: - this.logMutantResult(result, index, writeLineFn); - break; case MutantStatus.NoCoverage: - this.logMutantResult(result, index, writeLineFn); + this.logMutantResult(result, writeLineFn); break; } }); this.writeLine(`Ran ${(totalTests / mutantResults.length).toFixed(2)} tests per mutant on average.`); } - private logMutantResult(result: MutantResult, index: number, logImplementation: (input: string) => void): void { - logImplementation(`${index}. [${MutantStatus[result.status]}] ${result.mutatorName}`); - logImplementation(this.colorSourceFileAndLocation(result.sourceFilePath, result.location.start)); + private logMutantResult(result: MutantResult, logImplementation: (input: string) => void): void { + logImplementation(`#${result.id}. [${MutantStatus[result.status]}] ${result.mutatorName}`); + logImplementation(this.colorSourceFileAndLocation(result.fileName, result.location.start)); result.originalLines.split('\n').forEach((line) => { logImplementation(chalk.red('- ' + line)); @@ -80,42 +65,47 @@ export default class ClearTextReporter implements Reporter { logImplementation(chalk.green('+ ' + line)); }); logImplementation(''); - if (this.options.coverageAnalysis === 'perTest') { - this.logExecutedTests(result, logImplementation); - } else if (result.testsRan && result.testsRan.length > 0) { - logImplementation('Ran all tests for this mutant.'); + if (result.status === MutantStatus.Survived) { + if (this.options.coverageAnalysis === 'perTest' && result.testFilter) { + this.logExecutedTests(result, logImplementation); + } else { + logImplementation('Ran all tests for this mutant.'); + } + } else if (result.status === MutantStatus.Killed) { + logImplementation(`Killed by: ${result.killedBy}`); + } else if (result.status === MutantStatus.RuntimeError || result.status === MutantStatus.CompileError) { + logImplementation(`Error message: ${result.errorMessage}`); } } - private colorSourceFileAndLocation(sourceFilePath: string, position: Position): string { - const clearTextReporterConfig = this.options.clearTextReporter; - - if (clearTextReporterConfig && clearTextReporterConfig.allowColor !== false) { - return `${sourceFilePath}:${position.line}:${position.column}`; + private colorSourceFileAndLocation(fileName: string, position: Position): string { + if (!this.options.clearTextReporter.allowColor) { + return `${fileName}:${position.line}:${position.column}`; } - return [chalk.cyan(sourceFilePath), chalk.yellow(`${position.line}`), chalk.yellow(`${position.column}`)].join(':'); + return [chalk.cyan(fileName), chalk.yellow(`${position.line}`), chalk.yellow(`${position.column}`)].join(':'); } - private logExecutedTests(result: MutantResult, logImplementation: (input: string) => void) { + private logExecutedTests(result: UndetectedMutantResult, logImplementation: (input: string) => void) { if (!this.options.clearTextReporter.logTests) { return; } - if (result.testsRan && result.testsRan.length > 0) { - let testsToLog = this.options.clearTextReporter.maxTestsToLog; + if (result.nrOfTestsRan > 0) { + const { maxTestsToLog } = this.options.clearTextReporter; - if (testsToLog > 0) { - logImplementation('Tests ran: '); - for (let i = 0; i < testsToLog; i++) { - if (i > result.testsRan.length - 1) { + if (maxTestsToLog > 0) { + logImplementation('Tests ran:'); + for (let i = 0; i < maxTestsToLog; i++) { + if (i > result.testFilter!.length - 1) { break; } - - logImplementation(' ' + result.testsRan[i]); + logImplementation(` ${result.testFilter![i]}`); } - if (testsToLog < result.testsRan.length) { - logImplementation(` and ${result.testsRan.length - testsToLog} more tests!`); + const diff = result.testFilter!.length - maxTestsToLog; + if (diff > 0) { + const plural = diff === 1 ? '' : 's'; + logImplementation(` and ${diff} more test${plural}!`); } logImplementation(''); } diff --git a/packages/core/src/reporters/ClearTextScoreTable.ts b/packages/core/src/reporters/ClearTextScoreTable.ts index b22eb5e856..b7bcf94525 100644 --- a/packages/core/src/reporters/ClearTextScoreTable.ts +++ b/packages/core/src/reporters/ClearTextScoreTable.ts @@ -25,7 +25,7 @@ class Column { this.width = this.pad(dots(maxContentSize)).length; } - protected determineValueSize(row: MetricsResult = this.rows, ancestorCount: number = 0): number { + protected determineValueSize(row: MetricsResult = this.rows, ancestorCount = 0): number { const valueWidths = row.childResults.map((child) => this.determineValueSize(child, ancestorCount + 1)); valueWidths.push(this.header.length); valueWidths.push(this.valueFactory(row, ancestorCount).length); diff --git a/packages/core/src/reporters/EventRecorderReporter.ts b/packages/core/src/reporters/EventRecorderReporter.ts index 7199bb465f..b90d783787 100644 --- a/packages/core/src/reporters/EventRecorderReporter.ts +++ b/packages/core/src/reporters/EventRecorderReporter.ts @@ -14,7 +14,7 @@ export default class EventRecorderReporter implements StrictReporter { public static readonly inject = tokens(commonTokens.logger, commonTokens.options); private readonly allWork: Array> = []; - private readonly createBaseFolderTask: Promise; + private readonly createBaseFolderTask: Promise; private index = 0; constructor(private readonly log: Logger, private readonly options: StrykerOptions) { @@ -65,7 +65,7 @@ export default class EventRecorderReporter implements StrictReporter { this.work('onAllMutantsTested', results); } - public async wrapUp(): Promise { + public async wrapUp(): Promise { await this.createBaseFolderTask; return Promise.all(this.allWork); } diff --git a/packages/core/src/reporters/MutationTestReportCalculator.ts b/packages/core/src/reporters/MutationTestReportCalculator.ts deleted file mode 100644 index f9c8d96826..0000000000 --- a/packages/core/src/reporters/MutationTestReportCalculator.ts +++ /dev/null @@ -1,143 +0,0 @@ -import * as path from 'path'; - -import { Location, Position, StrykerOptions } from '@stryker-mutator/api/core'; -import { Logger } from '@stryker-mutator/api/logging'; -import { commonTokens, tokens } from '@stryker-mutator/api/plugin'; -import { MutantResult, MutantStatus, mutationTestReportSchema, Reporter } from '@stryker-mutator/api/report'; -import { normalizeWhitespaces } from '@stryker-mutator/util'; -import { calculateMetrics } from 'mutation-testing-metrics'; - -import { coreTokens } from '../di'; -import InputFileCollection from '../input/InputFileCollection'; -import { setExitCode } from '../utils/objectUtils'; - -export class MutationTestReportCalculator { - public static inject = tokens(coreTokens.reporter, commonTokens.options, coreTokens.inputFiles, commonTokens.logger); - - constructor( - private readonly reporter: Required, - private readonly options: StrykerOptions, - private readonly inputFiles: InputFileCollection, - private readonly log: Logger - ) {} - - public report(results: readonly MutantResult[]) { - const report = this.mutationTestReport(results); - this.reporter.onMutationTestReportReady(report); - this.determineExitCode(report); - } - - private determineExitCode(report: mutationTestReportSchema.MutationTestResult) { - const { metrics } = calculateMetrics(report.files); - const breaking = this.options.thresholds.break; - const formattedScore = metrics.mutationScore.toFixed(2); - if (typeof breaking === 'number') { - if (metrics.mutationScore < breaking) { - this.log.error(`Final mutation score ${formattedScore} under breaking threshold ${breaking}, setting exit code to 1 (failure).`); - this.log.info('(improve mutation score or set `thresholds.break = null` to prevent this error in the future)'); - setExitCode(1); - } else { - this.log.info(`Final mutation score of ${formattedScore} is greater than or equal to break threshold ${breaking}`); - } - } else { - this.log.debug( - "No breaking threshold configured. Won't fail the build no matter how low your mutation score is. Set `thresholds.break` to change this behavior." - ); - } - } - - private mutationTestReport(results: readonly MutantResult[]): mutationTestReportSchema.MutationTestResult { - return { - files: this.toFileResults(results), - schemaVersion: '1.0', - thresholds: this.options.thresholds, - }; - } - - private toFileResults(results: readonly MutantResult[]): mutationTestReportSchema.FileResultDictionary { - const resultDictionary: mutationTestReportSchema.FileResultDictionary = Object.create(null); - results.forEach((mutantResult) => { - const fileResult = resultDictionary[mutantResult.sourceFilePath]; - if (fileResult) { - fileResult.mutants.push(this.toMutantResult(mutantResult)); - } else { - const sourceFile = this.inputFiles.files.find((file) => file.name === mutantResult.sourceFilePath); - if (sourceFile) { - resultDictionary[mutantResult.sourceFilePath] = { - language: this.determineLanguage(sourceFile.name), - mutants: [this.toMutantResult(mutantResult)], - source: sourceFile.textContent, - }; - } else { - this.log.warn( - normalizeWhitespaces(`File "${mutantResult.sourceFilePath}" not found - in input files, but did receive mutant result for it. This shouldn't happen`) - ); - } - } - }); - return resultDictionary; - } - - public determineLanguage(name: string): string { - const ext = path.extname(name).toLowerCase(); - switch (ext) { - case '.ts': - case '.tsx': - return 'typescript'; - case '.html': - case '.vue': - return 'html'; - default: - return 'javascript'; - } - } - - private toMutantResult(mutantResult: MutantResult): mutationTestReportSchema.MutantResult { - return { - id: mutantResult.id, - location: this.toLocation(mutantResult.location), - mutatorName: mutantResult.mutatorName, - replacement: mutantResult.replacement, - status: this.toStatus(mutantResult.status), - }; - } - - private toLocation(location: Location): mutationTestReportSchema.Location { - return { - end: this.toPosition(location.end), - start: this.toPosition(location.start), - }; - } - - private toPosition(pos: Position): mutationTestReportSchema.Position { - return { - column: pos.column + 1, // convert from 0-based to 1-based - line: pos.line + 1, - }; - } - - private toStatus(status: MutantStatus): mutationTestReportSchema.MutantStatus { - switch (status) { - case MutantStatus.Killed: - return mutationTestReportSchema.MutantStatus.Killed; - case MutantStatus.NoCoverage: - return mutationTestReportSchema.MutantStatus.NoCoverage; - case MutantStatus.RuntimeError: - return mutationTestReportSchema.MutantStatus.RuntimeError; - case MutantStatus.Survived: - return mutationTestReportSchema.MutantStatus.Survived; - case MutantStatus.TimedOut: - return mutationTestReportSchema.MutantStatus.Timeout; - case MutantStatus.TranspileError: - return mutationTestReportSchema.MutantStatus.CompileError; - default: - this.logUnsupportedMutantStatus(status); - return mutationTestReportSchema.MutantStatus.RuntimeError; - } - } - - private logUnsupportedMutantStatus(status: never) { - this.log.warn('Unable to convert "%s" to a MutantStatus', status); - } -} diff --git a/packages/core/src/reporters/MutationTestReportHelper.ts b/packages/core/src/reporters/MutationTestReportHelper.ts new file mode 100644 index 0000000000..b655957fc0 --- /dev/null +++ b/packages/core/src/reporters/MutationTestReportHelper.ts @@ -0,0 +1,249 @@ +import * as path from 'path'; + +import { Location, Position, StrykerOptions, Mutant } from '@stryker-mutator/api/core'; +import { Logger } from '@stryker-mutator/api/logging'; +import { commonTokens, tokens } from '@stryker-mutator/api/plugin'; +import { + MutantResult, + MutantStatus, + mutationTestReportSchema, + Reporter, + TimeoutMutantResult, + InvalidMutantResult, + BaseMutantResult, + UndetectedMutantResult, + KilledMutantResult, + IgnoredMutantResult, +} from '@stryker-mutator/api/report'; +import { normalizeWhitespaces } from '@stryker-mutator/util'; +import { calculateMetrics } from 'mutation-testing-metrics'; +import { CompleteDryRunResult, MutantRunResult, MutantRunStatus } from '@stryker-mutator/api/test_runner'; +import { CheckStatus, PassedCheckResult, CheckResult } from '@stryker-mutator/api/check'; + +import { coreTokens } from '../di'; +import InputFileCollection from '../input/InputFileCollection'; +import { setExitCode } from '../utils/objectUtils'; +import { MutantTestCoverage } from '../mutants/findMutantTestCoverage'; +import { mutatedLines, originalLines } from '../utils/mutantUtils'; + +/** + * A helper class to convert and report mutants that survived or get killed + */ +export class MutationTestReportHelper { + private readonly testNamesById: Map; + + public static inject = tokens(coreTokens.reporter, commonTokens.options, coreTokens.inputFiles, commonTokens.logger, coreTokens.dryRunResult); + constructor( + private readonly reporter: Required, + private readonly options: StrykerOptions, + private readonly inputFiles: InputFileCollection, + private readonly log: Logger, + private readonly dryRunResult: CompleteDryRunResult + ) { + this.testNamesById = new Map(this.dryRunResult.tests.map((test) => [test.id, test.name])); + } + + public reportCheckFailed(mutant: Mutant, checkResult: Exclude): MutantResult { + return this.reportOne(mutant, { + status: this.checkStatusToResultStatus(checkResult.status), + errorMessage: checkResult.reason, + }); + } + + public reportNoCoverage(mutant: Mutant) { + return this.reportOne(mutant, { status: MutantStatus.NoCoverage, testFilter: [] }); + } + + public reportMutantIgnored(mutant: Mutant) { + return this.reportOne(mutant, { status: MutantStatus.Ignored, ignoreReason: mutant.ignoreReason! }); + } + + public reportMutantRunResult(mutantWithTestCoverage: MutantTestCoverage, result: MutantRunResult) { + const { mutant, testFilter } = mutantWithTestCoverage; + switch (result.status) { + case MutantRunStatus.Error: + return this.reportOne(mutant, { status: MutantStatus.RuntimeError, errorMessage: result.errorMessage }); + case MutantRunStatus.Killed: + return this.reportOne(mutant, { + status: MutantStatus.Killed, + nrOfTestsRan: result.nrOfTests, + killedBy: this.testNamesById.get(result.killedBy)!, + }); + case MutantRunStatus.Timeout: + return this.reportOne(mutant, { status: MutantStatus.TimedOut }); + case MutantRunStatus.Survived: + return this.reportOne(mutant, { + status: MutantStatus.Survived, + nrOfTestsRan: result.nrOfTests, + testFilter: testFilter ? this.dryRunResult.tests.filter((t) => testFilter.includes(t.id)).map((t) => t.name) : undefined, + }); + } + } + + private reportOne(mutant: Mutant, additionalFields: Omit & { nrOfTestsRan?: number }) { + const originalFileTextContent = this.inputFiles.filesToMutate.find((fileToMutate) => fileToMutate.name === mutant.fileName)!.textContent; + + const mutantResult = { + id: mutant.id.toString(), + location: mutant.location, + mutatedLines: mutatedLines(originalFileTextContent, mutant), + mutatorName: mutant.mutatorName, + originalLines: originalLines(originalFileTextContent, mutant), + range: mutant.range, + replacement: mutant.replacement, + fileName: mutant.fileName, + nrOfTestsRan: 0, + ...additionalFields, + } as MutantResult; + this.reporter.onMutantTested(mutantResult); + + return mutantResult; + } + + public reportMutantTimeout(mutantWithTestCoverage: MutantTestCoverage) {} + + private checkStatusToResultStatus(status: Exclude): MutantStatus.CompileError { + switch (status) { + case CheckStatus.CompileError: + return MutantStatus.CompileError; + } + } + + public reportAll(results: MutantResult[]) { + const report = this.mutationTestReport(results); + this.reporter.onAllMutantsTested(results); + this.reporter.onMutationTestReportReady(report); + this.determineExitCode(report); + } + + private determineExitCode(report: mutationTestReportSchema.MutationTestResult) { + const { metrics } = calculateMetrics(report.files); + const breaking = this.options.thresholds.break; + const formattedScore = metrics.mutationScore.toFixed(2); + if (typeof breaking === 'number') { + if (metrics.mutationScore < breaking) { + this.log.error(`Final mutation score ${formattedScore} under breaking threshold ${breaking}, setting exit code to 1 (failure).`); + this.log.info('(improve mutation score or set `thresholds.break = null` to prevent this error in the future)'); + setExitCode(1); + } else { + this.log.info(`Final mutation score of ${formattedScore} is greater than or equal to break threshold ${breaking}`); + } + } else { + this.log.debug( + "No breaking threshold configured. Won't fail the build no matter how low your mutation score is. Set `thresholds.break` to change this behavior." + ); + } + } + + private mutationTestReport(results: readonly MutantResult[]): mutationTestReportSchema.MutationTestResult { + return { + files: this.toFileResults(results), + schemaVersion: '1.0', + thresholds: this.options.thresholds, + }; + } + + private toFileResults(results: readonly MutantResult[]): mutationTestReportSchema.FileResultDictionary { + const resultDictionary: mutationTestReportSchema.FileResultDictionary = Object.create(null); + results.forEach((mutantResult) => { + const fileResult = resultDictionary[mutantResult.fileName]; + if (fileResult) { + fileResult.mutants.push(this.toMutantResult(mutantResult)); + } else { + const sourceFile = this.inputFiles.files.find((file) => file.name === mutantResult.fileName); + if (sourceFile) { + resultDictionary[mutantResult.fileName] = { + language: this.determineLanguage(sourceFile.name), + mutants: [this.toMutantResult(mutantResult)], + source: sourceFile.textContent, + }; + } else { + this.log.warn( + normalizeWhitespaces(`File "${mutantResult.fileName}" not found + in input files, but did receive mutant result for it. This shouldn't happen`) + ); + } + } + }); + return resultDictionary; + } + + public determineLanguage(name: string): string { + const ext = path.extname(name).toLowerCase(); + switch (ext) { + case '.ts': + case '.tsx': + return 'typescript'; + case '.html': + case '.vue': + return 'html'; + default: + return 'javascript'; + } + } + + private toMutantResult(mutantResult: MutantResult): mutationTestReportSchema.MutantResult { + return { + id: mutantResult.id, + location: this.toLocation(mutantResult.location), + mutatorName: mutantResult.mutatorName, + replacement: mutantResult.replacement, + status: this.toStatus(mutantResult.status), + description: this.describe(mutantResult), + }; + } + + private toLocation(location: Location): mutationTestReportSchema.Location { + return { + end: this.toPosition(location.end), + start: this.toPosition(location.start), + }; + } + + private toPosition(pos: Position): mutationTestReportSchema.Position { + return { + column: pos.column + 1, // convert from 0-based to 1-based + line: pos.line + 1, + }; + } + + private toStatus(status: MutantStatus): mutationTestReportSchema.MutantStatus { + switch (status) { + case MutantStatus.Killed: + return mutationTestReportSchema.MutantStatus.Killed; + case MutantStatus.NoCoverage: + return mutationTestReportSchema.MutantStatus.NoCoverage; + case MutantStatus.RuntimeError: + return mutationTestReportSchema.MutantStatus.RuntimeError; + case MutantStatus.Survived: + return mutationTestReportSchema.MutantStatus.Survived; + case MutantStatus.TimedOut: + return mutationTestReportSchema.MutantStatus.Timeout; + case MutantStatus.CompileError: + return mutationTestReportSchema.MutantStatus.CompileError; + case MutantStatus.Ignored: + return mutationTestReportSchema.MutantStatus.Ignored; + default: + this.logUnsupportedMutantStatus(status); + return mutationTestReportSchema.MutantStatus.RuntimeError; + } + } + + private describe(mutantResult: MutantResult): string | undefined { + switch (mutantResult.status) { + case MutantStatus.Ignored: + return `Ignore reason: ${mutantResult.ignoreReason}`; + case MutantStatus.Killed: + return `Killed by: ${mutantResult.killedBy}`; + case MutantStatus.CompileError: + case MutantStatus.RuntimeError: + return `Error message: ${mutantResult.errorMessage}`; + default: + return undefined; + } + } + + private logUnsupportedMutantStatus(status: never) { + this.log.warn('Unable to convert "%s" to a MutantStatus', status); + } +} diff --git a/packages/core/src/reporters/ProgressKeeper.ts b/packages/core/src/reporters/ProgressKeeper.ts index f128f70d3b..db95022827 100644 --- a/packages/core/src/reporters/ProgressKeeper.ts +++ b/packages/core/src/reporters/ProgressKeeper.ts @@ -16,7 +16,7 @@ abstract class ProgressKeeper implements Reporter { public onAllMutantsMatchedWithTests(matchedMutants: readonly MatchedMutant[]): void { this.timer = new Timer(); - this.mutantIdsWithoutCoverage = matchedMutants.filter((m) => !m.runAllTests && m.scopedTestIds.length === 0).map((m) => m.id); + this.mutantIdsWithoutCoverage = matchedMutants.filter((m) => !m.runAllTests && !m.testFilter?.length).map((m) => m.id); this.progress.total = matchedMutants.length - this.mutantIdsWithoutCoverage.length; } diff --git a/packages/core/src/reporters/ProgressReporter.ts b/packages/core/src/reporters/ProgressReporter.ts index 7ddc6786b9..bc3b893585 100644 --- a/packages/core/src/reporters/ProgressReporter.ts +++ b/packages/core/src/reporters/ProgressReporter.ts @@ -33,11 +33,11 @@ export default class ProgressBarReporter extends ProgressKeeper { } } - private tick(tickObj: object): void { + private tick(tickObj: Record): void { this.progressBar.tick(tickObj); } - private render(renderObj: object): void { + private render(renderObj: Record): void { this.progressBar.render(renderObj); } } diff --git a/packages/core/src/reporters/dashboard-reporter/index.ts b/packages/core/src/reporters/dashboard-reporter/index.ts index 5a850f9228..84b3dd86a0 100644 --- a/packages/core/src/reporters/dashboard-reporter/index.ts +++ b/packages/core/src/reporters/dashboard-reporter/index.ts @@ -1,4 +1,4 @@ -import { commonTokens, Injector, OptionsContext, tokens } from '@stryker-mutator/api/plugin'; +import { commonTokens, Injector, PluginContext, tokens } from '@stryker-mutator/api/plugin'; import { HttpClient } from 'typed-rest-client/HttpClient'; import { determineCIProvider } from '../ci/Provider'; @@ -7,7 +7,7 @@ import DashboardReporter from './DashboardReporter'; import DashboardReporterClient from './DashboardReporterClient'; import { dashboardReporterTokens } from './tokens'; -export function dashboardReporterFactory(injector: Injector): DashboardReporter { +export function dashboardReporterFactory(injector: Injector): DashboardReporter { return injector .provideValue(dashboardReporterTokens.httpClient, new HttpClient('stryker-dashboard-reporter')) .provideClass(dashboardReporterTokens.dashboardReporterClient, DashboardReporterClient) diff --git a/packages/core/src/sandbox/create-preprocessor.ts b/packages/core/src/sandbox/create-preprocessor.ts new file mode 100644 index 0000000000..dd553480c9 --- /dev/null +++ b/packages/core/src/sandbox/create-preprocessor.ts @@ -0,0 +1,18 @@ +import { tokens, Injector, commonTokens, PluginContext } from '@stryker-mutator/api/plugin'; + +import { disableTypeChecks } from '@stryker-mutator/instrumenter'; + +import { coreTokens } from '../di'; + +import { TSConfigPreprocessor } from './ts-config-preprocessor'; +import { FilePreprocessor } from './file-preprocessor'; +import { MultiPreprocessor } from './multi-preprocessor'; +import { DisableTypeChecksPreprocessor } from './disable-type-checks-preprocessor'; + +createPreprocessor.inject = tokens(commonTokens.injector); +export function createPreprocessor(injector: Injector): FilePreprocessor { + return new MultiPreprocessor([ + injector.provideValue(coreTokens.disableTypeChecksHelper, disableTypeChecks).injectClass(DisableTypeChecksPreprocessor), + injector.injectClass(TSConfigPreprocessor), + ]); +} diff --git a/packages/core/src/sandbox/disable-type-checks-preprocessor.ts b/packages/core/src/sandbox/disable-type-checks-preprocessor.ts new file mode 100644 index 0000000000..15438f20e1 --- /dev/null +++ b/packages/core/src/sandbox/disable-type-checks-preprocessor.ts @@ -0,0 +1,61 @@ +import path = require('path'); + +import minimatch = require('minimatch'); +import { commonTokens, tokens } from '@stryker-mutator/api/plugin'; +import { File, StrykerOptions } from '@stryker-mutator/api/core'; +import type { disableTypeChecks } from '@stryker-mutator/instrumenter'; +import { Logger } from '@stryker-mutator/api/logging'; +import { propertyPath, PropertyPathBuilder } from '@stryker-mutator/util'; + +import { coreTokens } from '../di'; +import { isWarningEnabled } from '../utils/objectUtils'; + +import { FilePreprocessor } from './file-preprocessor'; + +/** + * Disabled type checking by inserting `@ts-nocheck` atop TS/JS files and removing other @ts-xxx directives from comments: + * @see https://github.com/stryker-mutator/stryker/issues/2438 + */ +export class DisableTypeChecksPreprocessor implements FilePreprocessor { + public static readonly inject = tokens(commonTokens.logger, commonTokens.options, coreTokens.disableTypeChecksHelper); + constructor(private readonly log: Logger, private readonly options: StrykerOptions, private readonly impl: typeof disableTypeChecks) {} + + public async preprocess(files: File[]): Promise { + if (this.options.disableTypeChecks === false) { + return files; + } else { + const pattern = path.resolve(this.options.disableTypeChecks); + let warningLogged = false; + const outFiles = await Promise.all( + files.map(async (file) => { + if (minimatch(path.resolve(file.name), pattern)) { + try { + return await this.impl(file, { plugins: this.options.mutator.plugins }); + } catch (err) { + if (isWarningEnabled('preprocessorErrors', this.options.warnings)) { + warningLogged = true; + this.log.warn( + `Unable to disable type checking for file "${ + file.name + }". Shouldn't type checking be disabled for this file? Consider configuring a more restrictive "${propertyPath( + 'disableTypeChecks' + )}" settings (or turn it completely off with \`false\`)`, + err + ); + } + return file; + } + } else { + return file; + } + }) + ); + if (warningLogged) { + this.log.warn( + `(disable "${PropertyPathBuilder.create().prop('warnings').prop('preprocessorErrors')}" to ignore this warning` + ); + } + return outFiles; + } + } +} diff --git a/packages/core/src/sandbox/file-preprocessor.ts b/packages/core/src/sandbox/file-preprocessor.ts new file mode 100644 index 0000000000..68b0fc2745 --- /dev/null +++ b/packages/core/src/sandbox/file-preprocessor.ts @@ -0,0 +1,10 @@ +import { File } from '@stryker-mutator/api/core'; + +/** + * A preprocessor changes files before writing them to the sandbox. + * Stuff like rewriting references tsconfig.json files or adding // @ts-nocheck + * This is a private api that we might want to open up in the future. + */ +export interface FilePreprocessor { + preprocess(files: File[]): Promise; +} diff --git a/packages/core/src/sandbox/index.ts b/packages/core/src/sandbox/index.ts new file mode 100644 index 0000000000..2cc06ba112 --- /dev/null +++ b/packages/core/src/sandbox/index.ts @@ -0,0 +1,3 @@ +export type { FilePreprocessor } from './file-preprocessor'; +export * from './sandbox'; +export * from './create-preprocessor'; diff --git a/packages/core/src/sandbox/multi-preprocessor.ts b/packages/core/src/sandbox/multi-preprocessor.ts new file mode 100644 index 0000000000..07d2bbd8cf --- /dev/null +++ b/packages/core/src/sandbox/multi-preprocessor.ts @@ -0,0 +1,14 @@ +import { File } from '@stryker-mutator/api/core'; + +import { FilePreprocessor } from './file-preprocessor'; + +export class MultiPreprocessor implements FilePreprocessor { + constructor(private readonly preprocessors: FilePreprocessor[]) {} + + public async preprocess(files: File[]): Promise { + for await (const preprocessor of this.preprocessors) { + files = await preprocessor.preprocess(files); + } + return files; + } +} diff --git a/packages/core/src/sandbox/sandbox.ts b/packages/core/src/sandbox/sandbox.ts new file mode 100644 index 0000000000..7a44338c42 --- /dev/null +++ b/packages/core/src/sandbox/sandbox.ts @@ -0,0 +1,128 @@ +import path = require('path'); + +import execa = require('execa'); +import npmRunPath = require('npm-run-path'); +import { StrykerOptions } from '@stryker-mutator/api/core'; +import { File } from '@stryker-mutator/api/core'; +import { normalizeWhitespaces, I } from '@stryker-mutator/util'; +import * as mkdirp from 'mkdirp'; +import { Logger, LoggerFactoryMethod } from '@stryker-mutator/api/logging'; +import { tokens, commonTokens } from '@stryker-mutator/api/plugin'; +import { mergeMap, toArray } from 'rxjs/operators'; +import { from } from 'rxjs'; + +import { TemporaryDirectory } from '../utils/TemporaryDirectory'; +import { findNodeModules, MAX_CONCURRENT_FILE_IO, symlinkJunction, writeFile } from '../utils/fileUtils'; +import { coreTokens } from '../di'; + +interface SandboxFactory { + (options: StrykerOptions, getLogger: LoggerFactoryMethod, files: readonly File[], tempDir: I, exec: typeof execa): Promise< + Sandbox + >; + inject: [ + typeof commonTokens.options, + typeof commonTokens.getLogger, + typeof coreTokens.files, + typeof coreTokens.temporaryDirectory, + typeof coreTokens.execa + ]; +} + +export class Sandbox { + private readonly fileMap = new Map(); + public readonly workingDirectory: string; + + private constructor( + private readonly options: StrykerOptions, + private readonly log: Logger, + temporaryDirectory: I, + private readonly files: readonly File[], + private readonly exec: typeof execa + ) { + this.workingDirectory = temporaryDirectory.createRandomDirectory('sandbox'); + this.log.debug('Creating a sandbox for files in %s', this.workingDirectory); + } + + private async initialize(): Promise { + await this.fillSandbox(); + await this.runBuildCommand(); + await this.symlinkNodeModulesIfNeeded(); + } + + public static create: SandboxFactory = Object.assign( + async ( + options: StrykerOptions, + getLogger: LoggerFactoryMethod, + files: readonly File[], + tempDir: I, + exec: typeof execa + ): Promise => { + const sandbox = new Sandbox(options, getLogger(Sandbox.name), tempDir, files, exec); + await sandbox.initialize(); + return sandbox; + }, + { inject: tokens(commonTokens.options, commonTokens.getLogger, coreTokens.files, coreTokens.temporaryDirectory, coreTokens.execa) } + ); + + public get sandboxFileNames(): string[] { + return [...this.fileMap.entries()].map(([, to]) => to); + } + + public sandboxFileFor(fileName: string): string { + const sandboxFileName = this.fileMap.get(fileName); + if (sandboxFileName === undefined) { + throw new Error(`Cannot find sandbox file for ${fileName}`); + } + return sandboxFileName; + } + + private fillSandbox(): Promise { + return from(this.files) + .pipe( + mergeMap((file) => this.fillFile(file), MAX_CONCURRENT_FILE_IO), + toArray() + ) + .toPromise(); + } + + private async runBuildCommand() { + if (this.options.buildCommand) { + const env = npmRunPath.env(); + this.log.info('Running build command "%s" in the sandbox at "%s".', this.options.buildCommand, this.workingDirectory); + this.log.debug('(using PATH: %s)', env.PATH); + await this.exec.command(this.options.buildCommand, { cwd: this.workingDirectory, env }); + } + } + + private async symlinkNodeModulesIfNeeded(): Promise { + if (this.options.symlinkNodeModules) { + // TODO: Change with this.options.basePath when we have it + const basePath = process.cwd(); + const nodeModules = await findNodeModules(basePath); + if (nodeModules) { + await symlinkJunction(nodeModules, path.join(this.workingDirectory, 'node_modules')).catch((error: NodeJS.ErrnoException) => { + if (error.code === 'EEXIST') { + this.log.warn( + normalizeWhitespaces(`Could not symlink "${nodeModules}" in sandbox directory, + it is already created in the sandbox. Please remove the node_modules from your sandbox files. + Alternatively, set \`symlinkNodeModules\` to \`false\` to disable this warning.`) + ); + } else { + this.log.warn(`Unexpected error while trying to symlink "${nodeModules}" in sandbox directory.`, error); + } + }); + } else { + this.log.warn(`Could not find a node_modules folder to symlink into the sandbox directory. Search "${basePath}" and its parent directories`); + } + } + } + + private async fillFile(file: File): Promise { + const relativePath = path.relative(process.cwd(), file.name); + const folderName = path.join(this.workingDirectory, path.dirname(relativePath)); + mkdirp.sync(folderName); + const targetFileName = path.join(folderName, path.basename(relativePath)); + this.fileMap.set(file.name, targetFileName); + await writeFile(targetFileName, file.content); + } +} diff --git a/packages/core/src/sandbox/ts-config-preprocessor.ts b/packages/core/src/sandbox/ts-config-preprocessor.ts new file mode 100644 index 0000000000..d72e7e347d --- /dev/null +++ b/packages/core/src/sandbox/ts-config-preprocessor.ts @@ -0,0 +1,96 @@ +import path = require('path'); + +import { StrykerOptions, File } from '@stryker-mutator/api/core'; +import { tokens, commonTokens } from '@stryker-mutator/api/plugin'; +import { Logger } from '@stryker-mutator/api/logging'; + +import { FilePreprocessor } from './file-preprocessor'; + +/** + * A helper class that rewrites `references` and `extends` file paths if they end up falling outside of the sandbox. + * @example + * { + * "extends": "../../tsconfig.settings.json", + * "references": { + * "path": "../model" + * } + * } + * becomes: + * { + * "extends": "../../../../tsconfig.settings.json", + * "references": { + * "path": "../../../model" + * } + * } + */ +export class TSConfigPreprocessor implements FilePreprocessor { + private readonly touched: string[] = []; + private readonly fs = new Map(); + public static readonly inject = tokens(commonTokens.logger, commonTokens.options); + constructor(private readonly log: Logger, private readonly options: StrykerOptions) {} + + public async preprocess(input: File[]): Promise { + const tsconfigFile = path.resolve(this.options.tsconfigFile); + if (input.find((file) => file.name === tsconfigFile)) { + this.fs.clear(); + input.forEach((file) => { + this.fs.set(file.name, file); + }); + await this.rewriteTSConfigFile(tsconfigFile); + return [...this.fs.values()]; + } else { + return input; + } + } + + private async rewriteTSConfigFile(tsconfigFileName: string): Promise { + if (!this.touched.includes(tsconfigFileName)) { + this.touched.push(tsconfigFileName); + const tsconfigFile = this.fs.get(tsconfigFileName); + if (tsconfigFile) { + this.log.debug('Rewriting file %s', tsconfigFile); + const ts = await import('typescript'); + const { config } = ts.parseConfigFileTextToJson(tsconfigFile.name, tsconfigFile.textContent); + if (config) { + await this.rewriteExtends(config, tsconfigFileName); + await this.rewriteProjectReferences(config, tsconfigFileName); + this.fs.set(tsconfigFileName, new File(tsconfigFileName, JSON.stringify(config, null, 2))); + } + } + } + } + + private async rewriteExtends(config: any, tsconfigFileName: string): Promise { + if (typeof config.extends === 'string') { + const extendsFileName = path.resolve(path.dirname(tsconfigFileName), config.extends); + const relativeToSandbox = path.relative(process.cwd(), extendsFileName); + if (relativeToSandbox.startsWith('..')) { + config.extends = this.join('..', '..', config.extends); + return true; + } else { + await this.rewriteTSConfigFile(extendsFileName); + } + } + return false; + } + + private async rewriteProjectReferences(config: { references?: Array<{ path: string }> }, originTSConfigFileName: string): Promise { + const ts = await import('typescript'); + if (Array.isArray(config.references)) { + for (const reference of config.references) { + const referencePath = ts.resolveProjectReferencePath(reference); + const referencedProjectFileName = path.resolve(path.dirname(originTSConfigFileName), referencePath); + const relativeToProject = path.relative(process.cwd(), referencedProjectFileName); + if (relativeToProject.startsWith('..')) { + reference.path = this.join('..', '..', referencePath); + } else { + await this.rewriteTSConfigFile(referencedProjectFileName); + } + } + } + } + + private join(...pathSegments: string[]) { + return pathSegments.map((segment) => segment.replace(/\\/g, '/')).join('/'); + } +} diff --git a/packages/core/src/test-runner/ChildProcessTestRunnerDecorator.ts b/packages/core/src/test-runner/ChildProcessTestRunnerDecorator.ts index b8e60306d2..96276061c0 100644 --- a/packages/core/src/test-runner/ChildProcessTestRunnerDecorator.ts +++ b/packages/core/src/test-runner/ChildProcessTestRunnerDecorator.ts @@ -1,10 +1,10 @@ import { StrykerOptions } from '@stryker-mutator/api/core'; -import { RunOptions, RunResult, TestRunner } from '@stryker-mutator/api/test_runner'; +import { TestRunner, DryRunOptions, MutantRunOptions, MutantRunResult, DryRunResult } from '@stryker-mutator/api/test_runner'; +import { ExpirableTask } from '@stryker-mutator/util'; import ChildProcessCrashedError from '../child-proxy/ChildProcessCrashedError'; import ChildProcessProxy from '../child-proxy/ChildProcessProxy'; -import LoggingClientContext from '../logging/LoggingClientContext'; -import { timeout } from '../utils/objectUtils'; +import { LoggingClientContext } from '../logging'; import { ChildProcessTestRunnerWorker } from './ChildProcessTestRunnerWorker'; @@ -16,12 +16,12 @@ const MAX_WAIT_FOR_DISPOSE = 2000; export default class ChildProcessTestRunnerDecorator implements TestRunner { private readonly worker: ChildProcessProxy; - constructor(options: StrykerOptions, sandboxFileNames: readonly string[], sandboxWorkingDirectory: string, loggingContext: LoggingClientContext) { + constructor(options: StrykerOptions, sandboxWorkingDirectory: string, loggingContext: LoggingClientContext) { this.worker = ChildProcessProxy.create( require.resolve(`./${ChildProcessTestRunnerWorker.name}`), loggingContext, options, - { sandboxFileNames }, + {}, sandboxWorkingDirectory, ChildProcessTestRunnerWorker ); @@ -31,12 +31,15 @@ export default class ChildProcessTestRunnerDecorator implements TestRunner { return this.worker.proxy.init(); } - public run(options: RunOptions): Promise { - return this.worker.proxy.run(options); + public dryRun(options: DryRunOptions): Promise { + return this.worker.proxy.dryRun(options); + } + public mutantRun(options: MutantRunOptions): Promise { + return this.worker.proxy.mutantRun(options); } public async dispose(): Promise { - await timeout( + await ExpirableTask.timeout( // First let the inner test runner dispose this.worker.proxy.dispose().catch((error) => { // It's OK if the child process is already down. diff --git a/packages/core/src/test-runner/ChildProcessTestRunnerWorker.ts b/packages/core/src/test-runner/ChildProcessTestRunnerWorker.ts index 8cad8100c8..5a349576d9 100644 --- a/packages/core/src/test-runner/ChildProcessTestRunnerWorker.ts +++ b/packages/core/src/test-runner/ChildProcessTestRunnerWorker.ts @@ -1,6 +1,15 @@ import { StrykerOptions } from '@stryker-mutator/api/core'; -import { commonTokens, Injector, OptionsContext, PluginKind, tokens } from '@stryker-mutator/api/plugin'; -import { RunOptions, TestRunner } from '@stryker-mutator/api/test_runner'; +import { commonTokens, Injector, PluginContext, PluginKind, tokens } from '@stryker-mutator/api/plugin'; +import { + TestRunner, + DryRunOptions, + MutantRunOptions, + MutantRunResult, + DryRunResult, + DryRunStatus, + MutantRunStatus, +} from '@stryker-mutator/api/test_runner'; + import { errorToString } from '@stryker-mutator/util'; import { PluginCreator } from '../di'; @@ -8,12 +17,9 @@ import { PluginCreator } from '../di'; export class ChildProcessTestRunnerWorker implements TestRunner { private readonly underlyingTestRunner: TestRunner; - public static inject = tokens(commonTokens.sandboxFileNames, commonTokens.options, commonTokens.injector); - constructor(sandboxFileNames: readonly string[], { testRunner }: StrykerOptions, injector: Injector) { - this.underlyingTestRunner = injector - .provideValue(commonTokens.sandboxFileNames, sandboxFileNames) - .injectFunction(PluginCreator.createFactory(PluginKind.TestRunner)) - .create(testRunner); + public static inject = tokens(commonTokens.options, commonTokens.injector); + constructor({ testRunner }: StrykerOptions, injector: Injector) { + this.underlyingTestRunner = injector.injectFunction(PluginCreator.createFactory(PluginKind.TestRunner)).create(testRunner); } public async init(): Promise { @@ -28,17 +34,21 @@ export class ChildProcessTestRunnerWorker implements TestRunner { } } - public async run(options: RunOptions) { - const result = await this.underlyingTestRunner.run(options); - // If the test runner didn't report on coverage, let's try to do it ourselves. - if (!result.coverage) { - result.coverage = (global as any).__coverage__; + public async dryRun(options: DryRunOptions): Promise { + const dryRunResult = await this.underlyingTestRunner.dryRun(options); + if (dryRunResult.status === DryRunStatus.Complete && !dryRunResult.mutantCoverage && options.coverageAnalysis !== 'off') { + // @ts-expect-error + dryRunResult.mutantCoverage = global.__mutantCoverage__; + } + if (dryRunResult.status === DryRunStatus.Error) { + dryRunResult.errorMessage = errorToString(dryRunResult.errorMessage); } - if (result.errorMessages) { - // errorMessages should be a string[] - // Just in case the test runner implementer forgot to convert `Error`s to string, we will do it here - // https://github.com/stryker-mutator/stryker/issues/141 - result.errorMessages = result.errorMessages.map(errorToString); + return dryRunResult; + } + public async mutantRun(options: MutantRunOptions): Promise { + const result = await this.underlyingTestRunner.mutantRun(options); + if (result.status === MutantRunStatus.Error) { + result.errorMessage = errorToString(result.errorMessage); } return result; } diff --git a/packages/core/src/test-runner/CommandTestRunner.ts b/packages/core/src/test-runner/CommandTestRunner.ts index 5d591658c9..04dcf69e2d 100644 --- a/packages/core/src/test-runner/CommandTestRunner.ts +++ b/packages/core/src/test-runner/CommandTestRunner.ts @@ -1,9 +1,20 @@ import { exec } from 'child_process'; import * as os from 'os'; -import { StrykerOptions, CommandRunnerOptions } from '@stryker-mutator/api/core'; -import { RunResult, RunStatus, TestRunner, TestStatus } from '@stryker-mutator/api/test_runner'; -import { errorToString } from '@stryker-mutator/util'; +import { StrykerOptions, CommandRunnerOptions, INSTRUMENTER_CONSTANTS } from '@stryker-mutator/api/core'; +import { + TestRunner, + TestStatus, + DryRunOptions, + MutantRunOptions, + DryRunResult, + MutantRunResult, + DryRunStatus, + ErrorDryRunResult, + CompleteDryRunResult, + toMutantRunResult, +} from '@stryker-mutator/api/test_runner'; +import { errorToString, StrykerError } from '@stryker-mutator/util'; import { kill } from '../utils/objectUtils'; import Timer from '../utils/Timer'; @@ -24,7 +35,7 @@ export default class CommandTestRunner implements TestRunner { * Determines whether a given name is "command" (ignore case) * @param name Maybe "command", maybe not */ - public static is(name: string): boolean { + public static is(name: string): name is 'command' { return this.runnerName === name.toLowerCase(); } @@ -36,11 +47,29 @@ export default class CommandTestRunner implements TestRunner { this.settings = options.commandRunner; } - public run(): Promise { + public async dryRun({ coverageAnalysis }: Pick): Promise { + if (coverageAnalysis !== 'off') { + throw new StrykerError( + `The "${CommandTestRunner.runnerName}" test runner does not support coverageAnalysis "${coverageAnalysis}". Please set "coverageAnalysis": "off".` + ); + } + return this.run({}); + } + + public async mutantRun({ activeMutant }: Pick): Promise { + const result = await this.run({ activeMutantId: activeMutant.id }); + return toMutantRunResult(result); + } + + private run({ activeMutantId }: { activeMutantId?: number }): Promise { return new Promise((res, rej) => { const timer = new Timer(); const output: Array = []; - const childProcess = exec(this.settings.command, { cwd: this.workingDir }); + const env = + activeMutantId === undefined + ? process.env + : { ...process.env, [INSTRUMENTER_CONSTANTS.ACTIVE_MUTANT_ENV_VARIABLE]: activeMutantId.toString() }; + const childProcess = exec(this.settings.command, { cwd: this.workingDir, env }); childProcess.on('error', (error) => { kill(childProcess.pid) .then(() => handleResolve(errorResult(error))) @@ -58,11 +87,11 @@ export default class CommandTestRunner implements TestRunner { }); this.timeoutHandler = async () => { - handleResolve({ status: RunStatus.Timeout, tests: [] }); + handleResolve({ status: DryRunStatus.Timeout }); await kill(childProcess.pid); }; - const handleResolve = (runResult: RunResult) => { + const handleResolve = (runResult: DryRunResult) => { removeAllListeners(); this.timeoutHandler = undefined; res(runResult); @@ -74,21 +103,21 @@ export default class CommandTestRunner implements TestRunner { childProcess.removeAllListeners(); } - function errorResult(error: Error): RunResult { + function errorResult(error: Error): ErrorDryRunResult { return { - errorMessages: [errorToString(error)], - status: RunStatus.Error, - tests: [], + errorMessage: errorToString(error), + status: DryRunStatus.Error, }; } - function completeResult(exitCode: number | null, timer: Timer): RunResult { + function completeResult(exitCode: number | null, timer: Timer): CompleteDryRunResult { const duration = timer.elapsedMs(); if (exitCode === 0) { return { - status: RunStatus.Complete, + status: DryRunStatus.Complete, tests: [ { + id: 'all', name: 'All tests', status: TestStatus.Success, timeSpentMs: duration, @@ -97,10 +126,11 @@ export default class CommandTestRunner implements TestRunner { }; } else { return { - status: RunStatus.Complete, + status: DryRunStatus.Complete, tests: [ { - failureMessages: [output.map((buf) => buf.toString()).join(os.EOL)], + id: 'all', + failureMessage: output.map((buf) => buf.toString()).join(os.EOL), name: 'All tests', status: TestStatus.Failed, timeSpentMs: duration, diff --git a/packages/core/src/test-runner/MaxTestRunnerReuseDecorator.ts b/packages/core/src/test-runner/MaxTestRunnerReuseDecorator.ts new file mode 100644 index 0000000000..60d1e11573 --- /dev/null +++ b/packages/core/src/test-runner/MaxTestRunnerReuseDecorator.ts @@ -0,0 +1,40 @@ +import { MutantRunOptions, MutantRunResult, TestRunner } from '@stryker-mutator/api/test_runner'; + +import { StrykerOptions } from '@stryker-mutator/api/core'; + +import TestRunnerDecorator from './TestRunnerDecorator'; + +/** + * Wraps a test runner and implements the retry functionality. + */ +export default class MaxTestRunnerReuseDecorator extends TestRunnerDecorator { + public runs = 0; + private readonly restartAfter; + + constructor(testRunnerProducer: () => TestRunner, options: Pick) { + super(testRunnerProducer); + + this.restartAfter = options.maxTestRunnerReuse || 0; + } + + public async mutantRun(options: MutantRunOptions): Promise { + this.runs++; + if (this.restartAfter > 0 && this.runs > this.restartAfter) { + await this.recover(); + this.runs = 1; + } + + return super.mutantRun(options); + } + + private async recover(): Promise { + await this.dispose(); + this.createInnerRunner(); + return this.init(); + } + + public dispose(): Promise { + this.runs = 0; + return super.dispose(); + } +} diff --git a/packages/core/src/test-runner/ResilientTestRunnerFactory.ts b/packages/core/src/test-runner/ResilientTestRunnerFactory.ts deleted file mode 100644 index 467b0d6934..0000000000 --- a/packages/core/src/test-runner/ResilientTestRunnerFactory.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { StrykerOptions } from '@stryker-mutator/api/core'; -import { TestRunner } from '@stryker-mutator/api/test_runner'; - -import LoggingClientContext from '../logging/LoggingClientContext'; -import CommandTestRunner from '../test-runner/CommandTestRunner'; - -import ChildProcessTestRunnerDecorator from './ChildProcessTestRunnerDecorator'; -import RetryDecorator from './RetryDecorator'; -import TimeoutDecorator from './TimeoutDecorator'; - -export default { - create( - options: StrykerOptions, - sandboxFileNames: readonly string[], - sandboxWorkingDirectory: string, - loggingContext: LoggingClientContext - ): Required { - if (CommandTestRunner.is(options.testRunner)) { - return new RetryDecorator(() => new TimeoutDecorator(() => new CommandTestRunner(sandboxWorkingDirectory, options))); - } else { - return new RetryDecorator( - () => new TimeoutDecorator(() => new ChildProcessTestRunnerDecorator(options, sandboxFileNames, sandboxWorkingDirectory, loggingContext)) - ); - } - }, -}; diff --git a/packages/core/src/test-runner/RetryDecorator.ts b/packages/core/src/test-runner/RetryDecorator.ts index 65ccf1683b..6e9bea2905 100644 --- a/packages/core/src/test-runner/RetryDecorator.ts +++ b/packages/core/src/test-runner/RetryDecorator.ts @@ -1,4 +1,4 @@ -import { RunOptions, RunResult, RunStatus } from '@stryker-mutator/api/test_runner'; +import { DryRunStatus, DryRunResult, DryRunOptions, MutantRunResult, MutantRunOptions, MutantRunStatus } from '@stryker-mutator/api/test_runner'; import { errorToString } from '@stryker-mutator/util'; import { getLogger } from 'log4js'; @@ -14,10 +14,34 @@ const ERROR_MESSAGE = 'Test runner crashed. Tried twice to restart it without an export default class RetryDecorator extends TestRunnerDecorator { private readonly log = getLogger(RetryDecorator.name); - public async run(options: RunOptions, attemptsLeft = 2, lastError?: Error): Promise { + public async dryRun(options: DryRunOptions): Promise { + const result = await this.run(() => super.dryRun(options)); + if (typeof result === 'string') { + return { + status: DryRunStatus.Error, + errorMessage: result, + }; + } else { + return result; + } + } + + public async mutantRun(options: MutantRunOptions): Promise { + const result = await this.run(() => super.mutantRun(options)); + if (typeof result === 'string') { + return { + status: MutantRunStatus.Error, + errorMessage: result, + }; + } else { + return result; + } + } + + private async run(actRun: () => Promise, attemptsLeft = 2, lastError?: Error): Promise { if (attemptsLeft > 0) { try { - return await this.innerRunner.run(options); + return await actRun(); } catch (error) { if (error instanceof OutOfMemoryError) { this.log.info( @@ -26,11 +50,11 @@ export default class RetryDecorator extends TestRunnerDecorator { ); } await this.recover(); - return this.run(options, attemptsLeft - 1, error); + return this.run(actRun, attemptsLeft - 1, error); } } else { await this.recover(); - return { status: RunStatus.Error, errorMessages: [`${ERROR_MESSAGE}${errorToString(lastError)}`], tests: [] }; + return `${ERROR_MESSAGE}${errorToString(lastError)}`; } } diff --git a/packages/core/src/test-runner/TestRunnerDecorator.ts b/packages/core/src/test-runner/TestRunnerDecorator.ts index ea3e51b5b5..2cafbc3001 100644 --- a/packages/core/src/test-runner/TestRunnerDecorator.ts +++ b/packages/core/src/test-runner/TestRunnerDecorator.ts @@ -1,6 +1,7 @@ -import { RunOptions, RunResult, TestRunner } from '@stryker-mutator/api/test_runner'; +import { TestRunner, DryRunOptions, MutantRunOptions, MutantRunResult, DryRunResult } from '@stryker-mutator/api/test_runner'; +import { Disposable } from 'typed-inject'; -export default class TestRunnerDecorator implements Required { +export default class TestRunnerDecorator implements Required, Disposable { protected innerRunner: TestRunner; constructor(private readonly testRunnerProducer: () => TestRunner) { @@ -9,23 +10,25 @@ export default class TestRunnerDecorator implements Required { public init(): Promise { if (this.innerRunner.init) { - return this.innerRunner.init() || Promise.resolve(); + return this.innerRunner.init(); } else { return Promise.resolve(); } } - protected createInnerRunner() { this.innerRunner = this.testRunnerProducer(); } - public run(options: RunOptions): Promise { - return this.innerRunner.run(options); + public dryRun(options: DryRunOptions): Promise { + return this.innerRunner.dryRun(options); + } + public mutantRun(options: MutantRunOptions): Promise { + return this.innerRunner.mutantRun(options); } public dispose(): Promise { if (this.innerRunner.dispose) { - return this.innerRunner.dispose() || Promise.resolve(); + return this.innerRunner.dispose(); } else { return Promise.resolve(); } diff --git a/packages/core/src/test-runner/TimeoutDecorator.ts b/packages/core/src/test-runner/TimeoutDecorator.ts index f6c38e49ca..43427b9b43 100644 --- a/packages/core/src/test-runner/TimeoutDecorator.ts +++ b/packages/core/src/test-runner/TimeoutDecorator.ts @@ -1,7 +1,6 @@ -import { RunOptions, RunResult, RunStatus } from '@stryker-mutator/api/test_runner'; +import { DryRunStatus, DryRunResult, DryRunOptions, MutantRunOptions, MutantRunResult, MutantRunStatus } from '@stryker-mutator/api/test_runner'; import { getLogger } from 'log4js'; - -import { timeout, TimeoutExpired } from '../utils/objectUtils'; +import { ExpirableTask } from '@stryker-mutator/util'; import TestRunnerDecorator from './TestRunnerDecorator'; @@ -11,21 +10,46 @@ import TestRunnerDecorator from './TestRunnerDecorator'; export default class TimeoutDecorator extends TestRunnerDecorator { private readonly log = getLogger(TimeoutDecorator.name); - public async run(options: RunOptions): Promise { + public async dryRun(options: DryRunOptions): Promise { + const result = await this.run(options, () => super.dryRun(options)); + if (result === ExpirableTask.TimeoutExpired) { + return { + status: DryRunStatus.Timeout, + }; + } else { + return result; + } + } + + public async mutantRun(options: MutantRunOptions): Promise { + const result = await this.run(options, () => super.mutantRun(options)); + if (result === ExpirableTask.TimeoutExpired) { + return { + status: MutantRunStatus.Timeout, + }; + } else { + return result; + } + } + + private async run( + options: TOptions, + actRun: () => Promise + ): Promise { this.log.debug('Starting timeout timer (%s ms) for a test run', options.timeout); - const result = await timeout(super.run(options), options.timeout); - if (result === TimeoutExpired) { - return this.handleTimeout(); + const result = await ExpirableTask.timeout(actRun(), options.timeout); + if (result === ExpirableTask.TimeoutExpired) { + await this.handleTimeout(); + return result; } else { return result; } } - private handleTimeout(): Promise { + private async handleTimeout(): Promise { this.log.debug('Timeout expired, restarting the process and reporting timeout'); - return this.dispose() - .then(() => this.createInnerRunner()) - .then(() => this.init()) - .then(() => ({ status: RunStatus.Timeout, tests: [] })); + await this.dispose(); + this.createInnerRunner(); + await this.init(); } } diff --git a/packages/core/src/test-runner/index.ts b/packages/core/src/test-runner/index.ts new file mode 100644 index 0000000000..712a202039 --- /dev/null +++ b/packages/core/src/test-runner/index.ts @@ -0,0 +1,33 @@ +import { TestRunner } from '@stryker-mutator/api/test_runner'; +import { StrykerOptions } from '@stryker-mutator/api/core'; +import { tokens, commonTokens } from '@stryker-mutator/api/plugin'; + +import { LoggingClientContext } from '../logging'; +import { coreTokens } from '../di'; +import { Sandbox } from '../sandbox/sandbox'; + +import RetryDecorator from './RetryDecorator'; +import TimeoutDecorator from './TimeoutDecorator'; +import ChildProcessTestRunnerDecorator from './ChildProcessTestRunnerDecorator'; +import CommandTestRunner from './CommandTestRunner'; +import MaxTestRunnerReuseDecorator from './MaxTestRunnerReuseDecorator'; + +createTestRunnerFactory.inject = tokens(commonTokens.options, coreTokens.sandbox, coreTokens.loggingContext); +export function createTestRunnerFactory( + options: StrykerOptions, + sandbox: Pick, + loggingContext: LoggingClientContext +): () => Required { + if (CommandTestRunner.is(options.testRunner)) { + return () => new RetryDecorator(() => new TimeoutDecorator(() => new CommandTestRunner(sandbox.workingDirectory, options))); + } else { + return () => + new RetryDecorator( + () => + new MaxTestRunnerReuseDecorator( + () => new TimeoutDecorator(() => new ChildProcessTestRunnerDecorator(options, sandbox.workingDirectory, loggingContext)), + options + ) + ); + } +} diff --git a/packages/core/src/transpiler/ChildProcessTranspiler.ts b/packages/core/src/transpiler/ChildProcessTranspiler.ts deleted file mode 100644 index a207d24c06..0000000000 --- a/packages/core/src/transpiler/ChildProcessTranspiler.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { File, StrykerOptions } from '@stryker-mutator/api/core'; -import { commonTokens, tokens } from '@stryker-mutator/api/plugin'; -import { Transpiler } from '@stryker-mutator/api/transpile'; -import { Disposable } from 'typed-inject'; - -import ChildProcessProxy from '../child-proxy/ChildProcessProxy'; -import { coreTokens } from '../di'; -import LoggingClientContext from '../logging/LoggingClientContext'; - -import { ChildProcessTranspilerWorker } from './ChildProcessTranspilerWorker'; - -export class ChildProcessTranspiler implements Transpiler, Disposable { - private readonly childProcess: ChildProcessProxy; - - public static inject = tokens(commonTokens.options, coreTokens.loggingContext, commonTokens.produceSourceMaps); - - constructor(options: StrykerOptions, loggingContext: LoggingClientContext, produceSourceMaps: boolean) { - this.childProcess = ChildProcessProxy.create( - require.resolve(`./${ChildProcessTranspilerWorker.name}`), - loggingContext, - options, - { [commonTokens.produceSourceMaps]: produceSourceMaps }, - process.cwd(), - ChildProcessTranspilerWorker - ); - } - - public transpile(files: readonly File[]): Promise { - return this.childProcess.proxy.transpile(files); - } - - public dispose() { - this.childProcess.dispose(); - } -} diff --git a/packages/core/src/transpiler/ChildProcessTranspilerWorker.ts b/packages/core/src/transpiler/ChildProcessTranspilerWorker.ts deleted file mode 100644 index b2bacc1c31..0000000000 --- a/packages/core/src/transpiler/ChildProcessTranspilerWorker.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { File } from '@stryker-mutator/api/core'; -import { commonTokens, PluginKind, TranspilerPluginContext } from '@stryker-mutator/api/plugin'; -import { Transpiler } from '@stryker-mutator/api/transpile'; -import { Injector } from 'typed-inject'; - -import { coreTokens } from '../di'; -import { PluginCreator } from '../di/PluginCreator'; - -import { TranspilerFacade } from './TranspilerFacade'; - -export class ChildProcessTranspilerWorker implements Transpiler { - private readonly innerTranspiler: Transpiler; - - public static inject = [commonTokens.injector]; - constructor(injector: Injector) { - this.innerTranspiler = injector - .provideFactory(coreTokens.pluginCreatorTranspiler, PluginCreator.createFactory(PluginKind.Transpiler)) - .injectClass(TranspilerFacade); - } - - public transpile(files: readonly File[]): Promise { - return this.innerTranspiler.transpile(files); - } -} diff --git a/packages/core/src/transpiler/CoverageInstrumenterTranspiler.ts b/packages/core/src/transpiler/CoverageInstrumenterTranspiler.ts deleted file mode 100644 index c380e798a5..0000000000 --- a/packages/core/src/transpiler/CoverageInstrumenterTranspiler.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { File, StrykerOptions } from '@stryker-mutator/api/core'; -import { Transpiler } from '@stryker-mutator/api/transpile'; -import { StrykerError } from '@stryker-mutator/util'; -import { FileCoverageData, Range } from 'istanbul-lib-coverage'; -import { createInstrumenter, Instrumenter } from 'istanbul-lib-instrument'; - -import { COVERAGE_CURRENT_TEST_VARIABLE_NAME } from './coverageHooks'; - -export interface CoverageMaps { - statementMap: { [key: string]: Range }; - fnMap: { [key: string]: Range }; -} - -export interface CoverageMapsByFile { - [file: string]: CoverageMaps; -} - -export default class CoverageInstrumenterTranspiler implements Transpiler { - private readonly instrumenter: Instrumenter; - public fileCoverageMaps: CoverageMapsByFile = Object.create(null); - - constructor(private readonly settings: StrykerOptions, private readonly filesToInstrument: readonly string[]) { - this.instrumenter = createInstrumenter({ coverageVariable: this.coverageVariable, preserveComments: true }); - } - - public async transpile(files: readonly File[]): Promise { - return files.map((file) => this.instrumentFileIfNeeded(file)); - } - - /** - * Coverage variable *must* have the name '__coverage__'. Only that variable - * is reported back to the TestRunner process when using one of the karma - * test framework adapters (karma-jasmine, karma-mocha, ...). - * - * However, when coverageAnalysis is 'perTest' we don't choose that variable name right away, - * because we need that variable to hold all coverage results per test. Instead, we use __strykerCoverageCurrentTest__ - * and after each test copy over the value of that current test to the global coverage object __coverage__ - */ - private get coverageVariable() { - switch (this.settings.coverageAnalysis) { - case 'perTest': - return COVERAGE_CURRENT_TEST_VARIABLE_NAME; - default: - return '__coverage__'; - } - } - - private patchRanges(fileCoverage: FileCoverageData) { - function patchRange(range: Range) { - // Lines from istanbul are one-based, lines in Stryker are 0-based - range.end.line--; - range.start.line--; - } - - Object.keys(fileCoverage.statementMap).forEach((key) => patchRange(fileCoverage.statementMap[key])); - Object.keys(fileCoverage.branchMap).forEach((key) => { - patchRange(fileCoverage.branchMap[key].loc); - fileCoverage.branchMap[key].locations.forEach(patchRange); - fileCoverage.branchMap[key].line--; - }); - Object.keys(fileCoverage.fnMap).forEach((key) => { - patchRange(fileCoverage.fnMap[key].loc); - patchRange(fileCoverage.fnMap[key].decl); - fileCoverage.fnMap[key].line--; - }); - - return fileCoverage; - } - - private instrumentFileIfNeeded(file: File) { - if (this.settings.coverageAnalysis !== 'off' && this.filesToInstrument.some((fileName) => fileName === file.name)) { - return this.instrumentFile(file); - } else { - return file; - } - } - - private instrumentFile(sourceFile: File): File { - try { - const content = this.instrumenter.instrumentSync(sourceFile.textContent, sourceFile.name); - const fileCoverage = this.patchRanges(this.instrumenter.lastFileCoverage()); - this.fileCoverageMaps[sourceFile.name] = this.retrieveCoverageMaps(fileCoverage); - return new File(sourceFile.name, Buffer.from(content)); - } catch (error) { - throw new StrykerError(`Could not instrument "${sourceFile.name}" for code coverage`, error); - } - } - - private retrieveCoverageMaps(input: FileCoverageData): CoverageMaps { - const output: CoverageMaps = { - fnMap: {}, - statementMap: input.statementMap, - }; - Object.keys(input.fnMap).forEach((key) => (output.fnMap[key] = input.fnMap[key].loc)); - return output; - } -} diff --git a/packages/core/src/transpiler/MutantTranspileScheduler.ts b/packages/core/src/transpiler/MutantTranspileScheduler.ts deleted file mode 100644 index 975c39f894..0000000000 --- a/packages/core/src/transpiler/MutantTranspileScheduler.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { File } from '@stryker-mutator/api/core'; -import { Disposable } from '@stryker-mutator/api/plugin'; -import { tokens } from '@stryker-mutator/api/plugin'; -import { Transpiler } from '@stryker-mutator/api/transpile'; -import { errorToString } from '@stryker-mutator/util'; -import { Observable, range } from 'rxjs'; -import { BehaviorSubject } from 'rxjs'; -import { from } from 'rxjs'; -import { flatMap, zip } from 'rxjs/operators'; - -import { coreTokens } from '../di'; -import SourceFile from '../SourceFile'; -import TestableMutant from '../TestableMutant'; -import TranspiledMutant from '../TranspiledMutant'; - -import TranspileResult from './TranspileResult'; - -const INITIAL_CONCURRENCY = 100; - -export class MutantTranspileScheduler implements Disposable { - private currentMutatedFile: SourceFile; - private readonly concurrencyTicket$ = new BehaviorSubject(INITIAL_CONCURRENCY); - - public static inject = tokens(coreTokens.transpiler, coreTokens.transpiledFiles); - - /** - * Creates a mutant transpiler - */ - constructor(private readonly transpiler: Transpiler, private readonly unMutatedFiles: readonly File[]) {} - - public scheduleTranspileMutants(allMutants: readonly TestableMutant[]): Observable { - return from(allMutants).pipe( - zip(this.concurrencyTicket$.pipe(flatMap((n) => range(0, n)))), - flatMap(([mutant]) => this.transpileMutant(mutant), 1 /* IMPORTANT! Never transpile multiple mutants at once! */) - ); - } - - /** - * Schedule next mutant to be transpiled - */ - public readonly scheduleNext = () => { - this.concurrencyTicket$.next(1); - }; - - /** - * Dispose - */ - public dispose() { - this.concurrencyTicket$.complete(); - } - - private createTranspiledMutant(mutant: TestableMutant, transpileResult: TranspileResult) { - return new TranspiledMutant(mutant, transpileResult, someFilesChanged(this.unMutatedFiles)); - - function someFilesChanged(unMutatedFiles: readonly File[]): boolean { - return transpileResult.outputFiles.some((file) => fileChanged(file, unMutatedFiles)); - } - - function fileChanged(file: File, unMutatedFiles: readonly File[]) { - if (unMutatedFiles) { - const unMutatedFile = unMutatedFiles.find((f) => f.name === file.name); - return !unMutatedFile || unMutatedFile.textContent !== file.textContent; - } else { - return true; - } - } - } - - private async transpileMutant(mutant: TestableMutant): Promise { - const filesToTranspile: File[] = []; - if (this.currentMutatedFile && this.currentMutatedFile.name !== mutant.fileName) { - filesToTranspile.push(this.currentMutatedFile.file); - } - this.currentMutatedFile = mutant.sourceFile; - const mutatedFile = new File(mutant.fileName, Buffer.from(mutant.mutatedCode)); - filesToTranspile.push(mutatedFile); - try { - const transpiledFiles = await this.transpiler.transpile(filesToTranspile); - return this.createTranspiledMutant(mutant, { outputFiles: transpiledFiles, error: null }); - } catch (error) { - return this.createTranspiledMutant(mutant, { outputFiles: [], error: errorToString(error) }); - } - } -} diff --git a/packages/core/src/transpiler/SourceMapper.ts b/packages/core/src/transpiler/SourceMapper.ts deleted file mode 100644 index 3a4e233a28..0000000000 --- a/packages/core/src/transpiler/SourceMapper.ts +++ /dev/null @@ -1,254 +0,0 @@ -import * as path from 'path'; - -import { File, Location, Position, StrykerOptions } from '@stryker-mutator/api/core'; -import { StrykerError } from '@stryker-mutator/util'; -import { getLogger } from 'log4js'; -import { RawSourceMap, SourceMapConsumer } from 'source-map'; - -import { base64Decode } from '../utils/objectUtils'; - -const SOURCE_MAP_URL_REGEX = /\/\/\s*#\s*sourceMappingURL=(.*)/g; - -// This file contains source mapping logic. -// It reads transpiled output files (*.js) and scans it for comments like these: sourceMappingURL=*.js.map -// If it finds it, it will use mozilla's source-map to implement the `transpiledLocationFor` method. - -export interface MappedLocation { - fileName: string; - location: Location; -} - -export class SourceMapError extends StrykerError { - constructor(message: string, innerError?: Error) { - super( - `${message}. Cannot analyse code coverage. Setting \`coverageAnalysis: "off"\` in your config will prevent this error, but forces Stryker to run each test for each mutant.`, - innerError - ); - Error.captureStackTrace(this, SourceMapError); - // TS recommendation: https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work - Object.setPrototypeOf(this, SourceMapError.prototype); - } -} - -/** - * Represents an object that can calculated a transpiled location for a given original location - * It is implemented with the [composite pattern](https://en.wikipedia.org/wiki/Composite_pattern) - * Use the `create` method to retrieve a specific `SourceMapper` implementation - */ -export default abstract class SourceMapper { - /** - * Calculated a transpiled location for a given original location - * @param originalLocation The original location to be converted to a transpiled location - */ - public abstract async transpiledLocationFor(originalLocation: MappedLocation): Promise; - - public abstract transpiledFileNameFor(originalFileName: string): string; - - public static create(transpiledFiles: readonly File[], options: StrykerOptions): SourceMapper { - if (options.transpilers.length && options.coverageAnalysis !== 'off') { - return new TranspiledSourceMapper(transpiledFiles); - } else { - return new PassThroughSourceMapper(); - } - } -} - -export class TranspiledSourceMapper extends SourceMapper { - private sourceMaps: SourceMapBySource; - private readonly log = getLogger(SourceMapper.name); - - constructor(private readonly transpiledFiles: readonly File[]) { - super(); - } - - /** - * @inheritDoc - */ - public transpiledFileNameFor(originalFileName: string) { - const sourceMap = this.getSourceMap(originalFileName); - return sourceMap.transpiledFile.name; - } - - /** - * @inheritdoc - */ - public async transpiledLocationFor(originalLocation: MappedLocation): Promise { - const sourceMap = this.getSourceMap(originalLocation.fileName); - const relativeSource = this.getRelativeSource(sourceMap, originalLocation); - const start = await sourceMap.generatedPositionFor(originalLocation.location.start, relativeSource); - const end = await sourceMap.generatedPositionFor(originalLocation.location.end, relativeSource); - return { - fileName: sourceMap.transpiledFile.name, - location: { - end, - start, - }, - }; - } - - private getRelativeSource(from: SourceMap, to: MappedLocation) { - return path.relative(path.dirname(from.sourceMapFileName), to.fileName).replace(/\\/g, '/'); - } - - /** - * Gets the source map for given file - */ - private getSourceMap(sourceFileName: string): SourceMap { - if (!this.sourceMaps) { - this.sourceMaps = this.createSourceMaps(); - } - const sourceMap: SourceMap | undefined = this.sourceMaps[path.resolve(sourceFileName)]; - if (sourceMap) { - return sourceMap; - } else { - throw new SourceMapError(`Source map not found for "${sourceFileName}"`); - } - } - - /** - * Creates all source maps for lazy loading purposes - */ - private createSourceMaps(): SourceMapBySource { - const sourceMaps: SourceMapBySource = Object.create(null); - this.transpiledFiles.forEach((transpiledFile) => { - const sourceMapFile = this.getSourceMapForFile(transpiledFile); - if (sourceMapFile) { - const rawSourceMap = this.getRawSourceMap(sourceMapFile); - const sourceMap = new SourceMap(transpiledFile, sourceMapFile.name, rawSourceMap); - rawSourceMap.sources.forEach((source) => { - const sourceFileName = path.resolve(path.dirname(sourceMapFile.name), source); - sourceMaps[sourceFileName] = sourceMap; - }); - } - }); - return sourceMaps; - } - - private getRawSourceMap(sourceMapFile: File): RawSourceMap { - try { - return JSON.parse(sourceMapFile.textContent); - } catch (error) { - throw new SourceMapError(`Source map file "${sourceMapFile.name}" could not be parsed as json`, error); - } - } - - private getSourceMapForFile(transpiledFile: File): File | null { - const sourceMappingUrl = this.getSourceMapUrl(transpiledFile); - if (sourceMappingUrl) { - return this.getSourceMapFileFromUrl(sourceMappingUrl, transpiledFile); - } else { - return null; - } - } - - /** - * Gets the source map file from a url. - * @param sourceMapUrl The source map url. Can be a data url (data:application/json;base64,ABC...), or an actual file url - * @param transpiledFile The transpiled file for which the data url is - */ - private getSourceMapFileFromUrl(sourceMapUrl: string, transpiledFile: File): File { - const sourceMapFile = this.isInlineUrl(sourceMapUrl) - ? this.getInlineSourceMap(sourceMapUrl, transpiledFile) - : this.getExternalSourceMap(sourceMapUrl, transpiledFile); - return sourceMapFile; - } - - private isInlineUrl(sourceMapUrl: string) { - return sourceMapUrl.startsWith('data:'); - } - - /** - * Gets the source map from a data url - */ - private getInlineSourceMap(sourceMapUrl: string, transpiledFile: File): File { - const supportedDataPrefix = 'data:application/json;base64,'; - if (sourceMapUrl.startsWith(supportedDataPrefix)) { - const content = base64Decode(sourceMapUrl.substr(supportedDataPrefix.length)); - return new File(transpiledFile.name, content); - } else { - throw new SourceMapError( - `Source map file for "${transpiledFile.name}" cannot be read. Data url "${sourceMapUrl.substr( - 0, - sourceMapUrl.lastIndexOf(',') - )}" found, where "${supportedDataPrefix.substr(0, supportedDataPrefix.length - 1)}" was expected` - ); - } - } - - /** - * Gets the source map from a file - */ - private getExternalSourceMap(sourceMapUrl: string, transpiledFile: File) { - const sourceMapFileName = path.resolve(path.dirname(transpiledFile.name), sourceMapUrl); - const sourceMapFile = this.transpiledFiles.find((file) => path.resolve(file.name) === sourceMapFileName); - if (sourceMapFile) { - return sourceMapFile; - } else { - throw new SourceMapError( - `Source map file "${sourceMapUrl}" (referenced by "${transpiledFile.name}") cannot be found in list of transpiled files` - ); - } - } - - /** - * Gets the source map url from a transpiled file (the last comment with sourceMappingURL= ...) - */ - private getSourceMapUrl(transpiledFile: File): string | null { - SOURCE_MAP_URL_REGEX.lastIndex = 0; - let currentMatch: RegExpExecArray | null; - let lastMatch: RegExpExecArray | null = null; - // Retrieve the final sourceMappingURL comment in the file - while ((currentMatch = SOURCE_MAP_URL_REGEX.exec(transpiledFile.textContent))) { - lastMatch = currentMatch; - } - if (lastMatch) { - this.log.debug('Source map url found in transpiled file "%s"', transpiledFile.name); - return lastMatch[1]; - } else { - this.log.debug('No source map url found in transpiled file "%s"', transpiledFile.name); - return null; - } - } -} - -export class PassThroughSourceMapper extends SourceMapper { - /** - * @inheritdoc - */ - public transpiledFileNameFor(originalFileName: string): string { - return originalFileName; - } - - /** - * @inheritdoc - */ - public async transpiledLocationFor(originalLocation: MappedLocation): Promise { - return Promise.resolve(originalLocation); - } -} - -class SourceMap { - private sourceMap: SourceMapConsumer | undefined; - constructor(public transpiledFile: File, public sourceMapFileName: string, private readonly rawSourceMap: RawSourceMap) {} - public async generatedPositionFor(originalPosition: Position, relativeSource: string): Promise { - if (!this.sourceMap) { - this.sourceMap = await new SourceMapConsumer(this.rawSourceMap); - } - - const transpiledPosition = await this.sourceMap.generatedPositionFor({ - bias: SourceMapConsumer.LEAST_UPPER_BOUND, - column: originalPosition.column, - line: originalPosition.line + 1, // SourceMapConsumer works 1-based - source: relativeSource, - }); - - return Promise.resolve({ - column: transpiledPosition.column || 0, - line: (transpiledPosition.line || 1) - 1, // Stryker works 0-based - }); - } -} - -interface SourceMapBySource { - [sourceFileName: string]: SourceMap; -} diff --git a/packages/core/src/transpiler/TranspileResult.ts b/packages/core/src/transpiler/TranspileResult.ts deleted file mode 100644 index 85b5ff8adf..0000000000 --- a/packages/core/src/transpiler/TranspileResult.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { File } from '@stryker-mutator/api/core'; - -export default interface TranspileResult { - outputFiles: readonly File[]; - error: string | null; -} diff --git a/packages/core/src/transpiler/TranspilerFacade.ts b/packages/core/src/transpiler/TranspilerFacade.ts deleted file mode 100644 index 799739366b..0000000000 --- a/packages/core/src/transpiler/TranspilerFacade.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { File, StrykerOptions } from '@stryker-mutator/api/core'; -import { commonTokens, PluginKind, tokens } from '@stryker-mutator/api/plugin'; -import { Transpiler } from '@stryker-mutator/api/transpile'; -import { StrykerError } from '@stryker-mutator/util'; - -import { coreTokens } from '../di'; -import { PluginCreator } from '../di/PluginCreator'; - -class NamedTranspiler { - constructor(public name: string, public transpiler: Transpiler) {} -} - -export class TranspilerFacade implements Transpiler { - private readonly innerTranspilers: NamedTranspiler[]; - - public static inject = tokens(commonTokens.options, coreTokens.pluginCreatorTranspiler); - - constructor(options: StrykerOptions, pluginCreator: PluginCreator) { - this.innerTranspilers = options.transpilers.map((transpilerName) => new NamedTranspiler(transpilerName, pluginCreator.create(transpilerName))); - } - - public transpile(files: readonly File[]): Promise { - return this.performTranspileChain(files); - } - - private async performTranspileChain( - input: readonly File[], - remainingChain: NamedTranspiler[] = this.innerTranspilers.slice() - ): Promise { - const current = remainingChain.shift(); - if (current) { - const output = await current.transpiler.transpile(input).catch((error) => { - throw new StrykerError(`An error occurred in transpiler "${current.name}"`, error); - }); - return this.performTranspileChain(output, remainingChain); - } else { - return input; - } - } -} diff --git a/packages/core/src/transpiler/coverageHooks.ts b/packages/core/src/transpiler/coverageHooks.ts deleted file mode 100644 index 3561ae98c5..0000000000 --- a/packages/core/src/transpiler/coverageHooks.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { TestFramework } from '@stryker-mutator/api/test_framework'; - -import { wrapInClosure } from '../utils/objectUtils'; - -export const COVERAGE_CURRENT_TEST_VARIABLE_NAME = '__strykerCoverageCurrentTest__'; - -const cloneFunctionFragment = ` -function clone(source) { - var result = source; - if (Array.isArray(source)) { - result = []; - source.forEach(function (child, index) { - result[index] = clone(child); - }); - } else if (typeof source == "object") { - result = {}; - for (var i in source) { - result[i] = clone(source[i]); - } - } - return result; -}`; - -const BEFORE_EACH_FRAGMENT_PER_TEST = ` -if (!globalCoverage.baseline && window.${COVERAGE_CURRENT_TEST_VARIABLE_NAME}) { -globalCoverage.baseline = clone(window.${COVERAGE_CURRENT_TEST_VARIABLE_NAME}); -}`; - -const AFTER_EACH_FRAGMENT_PER_TEST = ` -globalCoverage.deviations[id] = coverageResult = {}; -id++; -var coveragePerFile = window.${COVERAGE_CURRENT_TEST_VARIABLE_NAME}; -if(coveragePerFile) { -Object.keys(coveragePerFile).forEach(function (file) { - var coverage = coveragePerFile[file]; - var baseline = globalCoverage.baseline[file]; - var fileResult = { s: {}, f: {} }; - var touchedFile = false; - for(var i in coverage.s){ - if(!baseline || coverage.s[i] !== baseline.s[i]){ - fileResult.s[i] = coverage.s[i]; - touchedFile = true; - } - } - for(var i in coverage.f){ - if(!baseline || coverage.f[i] !== baseline.f[i]){ - fileResult.f[i] = coverage.f[i]; - touchedFile = true; - } - } - if(touchedFile){ - coverageResult[file] = fileResult; - } -}); -}`; - -export function coveragePerTestHooks(testFramework: TestFramework): string { - return wrapInClosure(` - var id = 0, globalCoverage, coverageResult; - window.__coverage__ = globalCoverage = { deviations: {} }; - ${testFramework.beforeEach(BEFORE_EACH_FRAGMENT_PER_TEST)} - ${testFramework.afterEach(AFTER_EACH_FRAGMENT_PER_TEST)} - ${cloneFunctionFragment}; - `); -} diff --git a/packages/core/src/transpiler/index.ts b/packages/core/src/transpiler/index.ts deleted file mode 100644 index 7a026c029c..0000000000 --- a/packages/core/src/transpiler/index.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { File, StrykerOptions } from '@stryker-mutator/api/core'; -import { commonTokens, Disposable, Injector, tokens, TranspilerPluginContext } from '@stryker-mutator/api/plugin'; -import { Transpiler } from '@stryker-mutator/api/transpile'; - -import { coreTokens } from '../di'; -import LoggingClientContext from '../logging/LoggingClientContext'; - -import { ChildProcessTranspiler } from './ChildProcessTranspiler'; - -/** - * Creates a transpiler. If one is configured, spawns that in a child process - */ -export function transpilerFactory( - options: StrykerOptions, - injector: Injector -): Transpiler & Disposable { - if (options.transpilers.length) { - return injector.injectClass(ChildProcessTranspiler); - } else { - return { - transpile(files: readonly File[]) { - return Promise.resolve(files); - }, - dispose() { - // noop - }, - }; - } -} -transpilerFactory.inject = tokens(commonTokens.options, commonTokens.injector); diff --git a/packages/core/src/utils/LocationHelper.ts b/packages/core/src/utils/LocationHelper.ts deleted file mode 100644 index 9b5f7b66f2..0000000000 --- a/packages/core/src/utils/LocationHelper.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { Location } from '@stryker-mutator/api/core'; - -export default class LocationHelper { - public static MAX_VALUE = new LocationHelper( - Object.freeze({ - end: Object.freeze({ column: Number.POSITIVE_INFINITY, line: Number.POSITIVE_INFINITY }), - start: Object.freeze({ column: 0, line: -1 }), - }) - ); - - constructor(private readonly loc: Location) {} - - /** - * Indicates whether the current location is covered by an other location. - * @param maybeWrapper The location that is questioned to be wrapping this location. - * @returns true if this location is covered by given location, otherwise false - */ - public isCoveredBy(maybeWrapper: Location): boolean { - const isAfterStart = - this.loc.start.line > maybeWrapper.start.line || - (this.loc.start.line === maybeWrapper.start.line && this.loc.start.column >= maybeWrapper.start.column); - const isBeforeEnd = - this.loc.end.line < maybeWrapper.end.line || (this.loc.end.line === maybeWrapper.end.line && this.loc.end.column <= maybeWrapper.end.column); - return isAfterStart && isBeforeEnd; - } - - /** - * Indicates whether the given location is smaller than this location. - * @param maybeSmaller The area which is questioned to cover a smaller area than this location. - * @returns true if the given location covers a smaller area than this one. - */ - public isSmallerArea(maybeSmaller: Location) { - let firstLocationHasSmallerArea = false; - const lineDifference = this.loc.end.line - this.loc.start.line - (maybeSmaller.end.line - maybeSmaller.start.line); - const coversLessLines = lineDifference > 0; - const coversLessColumns = - lineDifference === 0 && maybeSmaller.start.column - this.loc.start.column + (this.loc.end.column - maybeSmaller.end.column) > 0; - if (coversLessLines || coversLessColumns) { - firstLocationHasSmallerArea = true; - } - return firstLocationHasSmallerArea; - } -} diff --git a/packages/core/src/utils/StringBuilder.ts b/packages/core/src/utils/StringBuilder.ts index 52047bcf31..d0fcafceae 100644 --- a/packages/core/src/utils/StringBuilder.ts +++ b/packages/core/src/utils/StringBuilder.ts @@ -11,8 +11,8 @@ export default class StringBuilder { this.strings.push(str); this.currentLength += str.length; while (this.currentLength > this.maxSize && this.strings.length > 1) { - const popped = this.strings.shift() as string; - this.currentLength -= popped.length; + const shifted = this.strings.shift() as string; + this.currentLength -= shifted.length; } } diff --git a/packages/core/src/utils/Task.ts b/packages/core/src/utils/Task.ts deleted file mode 100644 index 69cfd7c268..0000000000 --- a/packages/core/src/utils/Task.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { timeout, TimeoutExpired } from './objectUtils'; - -/** - * Wraps a promise in a Task api for convenience. - */ -export class Task { - protected _promise: Promise; - private resolveFn: (value?: T | PromiseLike) => void; - private rejectFn: (reason: any) => void; - private _isCompleted = false; - - constructor() { - this._promise = new Promise((resolve, reject) => { - this.resolveFn = resolve; - this.rejectFn = reject; - }); - } - - public get promise() { - return this._promise; - } - - public get isCompleted() { - return this._isCompleted; - } - - public resolve = (result: T | PromiseLike): void => { - this._isCompleted = true; - this.resolveFn(result); - }; - - public reject = (reason: any): void => { - this._isCompleted = true; - this.rejectFn(reason); - }; -} - -/** - * A task that can expire after the given time. - */ -export class ExpirableTask extends Task { - constructor(timeoutMS: number) { - super(); - this._promise = timeout(this._promise, timeoutMS); - } -} diff --git a/packages/core/src/utils/TemporaryDirectory.ts b/packages/core/src/utils/TemporaryDirectory.ts index edc3d2fd64..c0f559637a 100644 --- a/packages/core/src/utils/TemporaryDirectory.ts +++ b/packages/core/src/utils/TemporaryDirectory.ts @@ -12,10 +12,12 @@ import { deleteDir } from './fileUtils'; export class TemporaryDirectory implements Disposable { private readonly temporaryDirectory: string; private isInitialized = false; + public removeDuringDisposal: boolean; public static readonly inject = tokens(commonTokens.logger, commonTokens.options); constructor(private readonly log: Logger, options: StrykerOptions) { this.temporaryDirectory = path.resolve(options.tempDirName); + this.removeDuringDisposal = options.cleanTempDir; } public initialize() { @@ -66,11 +68,13 @@ export class TemporaryDirectory implements Disposable { if (!this.isInitialized) { throw new Error('initialize() was not called!'); } - this.log.debug('Deleting stryker temp directory %s', this.temporaryDirectory); - try { - await deleteDir(this.temporaryDirectory); - } catch (e) { - return this.log.info(`Failed to delete stryker temp directory ${this.temporaryDirectory}`); + if (this.removeDuringDisposal) { + this.log.debug('Deleting stryker temp directory %s', this.temporaryDirectory); + try { + await deleteDir(this.temporaryDirectory); + } catch (e) { + this.log.info(`Failed to delete stryker temp directory ${this.temporaryDirectory}`); + } } } diff --git a/packages/core/src/utils/Timer.ts b/packages/core/src/utils/Timer.ts index 5cf6ad9320..c8be84c8e1 100644 --- a/packages/core/src/utils/Timer.ts +++ b/packages/core/src/utils/Timer.ts @@ -2,7 +2,7 @@ export default class Timer { private readonly now: () => Date; private start: Date; private markers: { - [name: string]: Date; + [name: string]: Date | undefined; }; constructor(now = () => new Date()) { @@ -15,19 +15,20 @@ export default class Timer { this.start = this.now(); } - public humanReadableElapsed() { - const elapsedSeconds = this.elapsedSeconds(); + public humanReadableElapsed(sinceMarker?: string) { + const elapsedSeconds = this.elapsedSeconds(sinceMarker); return Timer.humanReadableElapsedMinutes(elapsedSeconds) + Timer.humanReadableElapsedSeconds(elapsedSeconds); } - public elapsedSeconds() { - const elapsedMs = this.elapsedMs(); + public elapsedSeconds(sinceMarker?: string) { + const elapsedMs = this.elapsedMs(sinceMarker); return Math.floor(elapsedMs / 1000); } public elapsedMs(sinceMarker?: string) { - if (sinceMarker && this.markers[sinceMarker]) { - return this.now().getTime() - this.markers[sinceMarker].getTime(); + const marker = sinceMarker && this.markers[sinceMarker]; + if (marker) { + return this.now().getTime() - marker.getTime(); } else { return this.now().getTime() - this.start.getTime(); } @@ -39,21 +40,21 @@ export default class Timer { private static humanReadableElapsedSeconds(elapsedSeconds: number) { const restSeconds = elapsedSeconds % 60; - if (restSeconds === 1) { - return `${restSeconds} second`; - } else { - return `${restSeconds} seconds`; - } + return this.formatTime('second', restSeconds); } private static humanReadableElapsedMinutes(elapsedSeconds: number) { const elapsedMinutes = Math.floor(elapsedSeconds / 60); - if (elapsedMinutes > 1) { - return `${elapsedMinutes} minutes `; - } else if (elapsedMinutes > 0) { - return `${elapsedMinutes} minute `; - } else { + if (elapsedMinutes === 0) { return ''; + } else { + return this.formatTime('minute', elapsedMinutes); } } + + private static formatTime(word: 'minute' | 'second', elapsed: number) { + const s = elapsed === 1 ? '' : 's'; + const blank = word === 'minute' ? ' ' : ''; + return `${elapsed} ${word}${s}${blank}`; + } } diff --git a/packages/core/src/utils/fileUtils.ts b/packages/core/src/utils/fileUtils.ts index e5303617a6..c25416b479 100644 --- a/packages/core/src/utils/fileUtils.ts +++ b/packages/core/src/utils/fileUtils.ts @@ -1,10 +1,14 @@ import * as path from 'path'; import { promises as fs } from 'fs'; +import { promisify } from 'util'; + import * as nodeGlob from 'glob'; import * as mkdirp from 'mkdirp'; import * as rimraf from 'rimraf'; +export const MAX_CONCURRENT_FILE_IO = 256; + export function glob(expression: string): Promise { return new Promise((resolve, reject) => { nodeGlob(expression, { nodir: true }, (error, matches) => { @@ -13,13 +17,7 @@ export function glob(expression: string): Promise { }); } -export function deleteDir(dirToDelete: string): Promise { - return new Promise((resolve, reject) => { - rimraf(dirToDelete, (error) => { - error ? reject(error) : resolve(); - }); - }); -} +export const deleteDir = promisify(rimraf); export async function cleanFolder(folderName: string) { try { diff --git a/packages/core/src/utils/mutantUtils.ts b/packages/core/src/utils/mutantUtils.ts new file mode 100644 index 0000000000..188c823cf4 --- /dev/null +++ b/packages/core/src/utils/mutantUtils.ts @@ -0,0 +1,51 @@ +import { Mutant } from '@stryker-mutator/api/core'; + +const enum CharacterCodes { + MaxAsciiCharacter = 0x7f, + LineFeed = 0x0a, // \n + CarriageReturn = 0x0d, // \r + LineSeparator = 0x2028, + ParagraphSeparator = 0x2029, +} + +export function isLineBreak(ch: number): boolean { + // ES5 7.3: + // The ECMAScript line terminator characters are listed in Table 3. + // Table 3: Line Terminator Characters + // Code Unit Value Name Formal Name + // \u000A Line Feed + // \u000D Carriage Return + // \u2028 Line separator + // \u2029 Paragraph separator + // Only the characters in Table 3 are treated as line terminators. Other new line or line + // breaking characters are treated as white space but not as line terminators. + + return ( + ch === CharacterCodes.LineFeed || + ch === CharacterCodes.CarriageReturn || + ch === CharacterCodes.LineSeparator || + ch === CharacterCodes.ParagraphSeparator + ); +} + +export function originalLines(originalText: string, mutant: Mutant): string { + const [startIndex, endIndex] = getMutationLineIndexes(originalText, mutant); + return originalText.substring(startIndex, endIndex); +} + +function getMutationLineIndexes(originalText: string, mutant: Mutant): [number, number] { + let startIndexLines = mutant.range[0]; + let endIndexLines = mutant.range[1]; + while (startIndexLines > 0 && !isLineBreak(originalText.charCodeAt(startIndexLines - 1))) { + startIndexLines--; + } + while (endIndexLines < originalText.length && !isLineBreak(originalText.charCodeAt(endIndexLines))) { + endIndexLines++; + } + return [startIndexLines, endIndexLines]; +} + +export function mutatedLines(originalText: string, mutant: Mutant): string { + const [startIndex, endIndex] = getMutationLineIndexes(originalText, mutant); + return `${originalText.substring(startIndex, mutant.range[0])}${mutant.replacement}${originalText.substring(mutant.range[1], endIndex)}`; +} diff --git a/packages/core/src/utils/objectUtils.ts b/packages/core/src/utils/objectUtils.ts index 3d98cc8caf..c7155ab266 100644 --- a/packages/core/src/utils/objectUtils.ts +++ b/packages/core/src/utils/objectUtils.ts @@ -64,23 +64,6 @@ export function kill(pid: number): Promise { }); } -export const TimeoutExpired: unique symbol = Symbol('TimeoutExpired'); -export function timeout(promise: Promise, ms: number): Promise { - const sleep = new Promise((res, rej) => { - const timer = setTimeout(() => res(TimeoutExpired), ms); - promise - .then((result) => { - clearTimeout(timer); - res(result); - }) - .catch((error) => { - clearTimeout(timer); - rej(error); - }); - }); - return sleep; -} - export function padLeft(input: string): string { return input .split('\n') diff --git a/packages/core/stryker.conf.js b/packages/core/stryker.conf.js index fa5a53f3c4..305c428237 100644 --- a/packages/core/stryker.conf.js +++ b/packages/core/stryker.conf.js @@ -1,5 +1,6 @@ const path = require('path'); const settings = require('../../stryker.parent.conf'); const moduleName = __dirname.split(path.sep).pop(); +settings.plugins = settings.plugins.map(p => path.resolve(p)); settings.dashboard.module = moduleName; module.exports = settings; diff --git a/packages/core/test/helpers/initChai.ts b/packages/core/test/helpers/initChai.ts deleted file mode 100644 index 514154da42..0000000000 --- a/packages/core/test/helpers/initChai.ts +++ /dev/null @@ -1,6 +0,0 @@ -import * as chai from 'chai'; -import * as chaiAsPromised from 'chai-as-promised'; -import * as sinonChai from 'sinon-chai'; - -chai.use(sinonChai); -chai.use(chaiAsPromised); diff --git a/packages/core/test/helpers/initSinon.ts b/packages/core/test/helpers/initSinon.ts deleted file mode 100644 index 96cb3f7e59..0000000000 --- a/packages/core/test/helpers/initSinon.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { testInjector } from '@stryker-mutator/test-helpers'; -import * as sinon from 'sinon'; - -afterEach(() => { - sinon.restore(); - testInjector.reset(); -}); diff --git a/packages/core/test/helpers/producers.ts b/packages/core/test/helpers/producers.ts index fed9a5dda0..40c039565f 100644 --- a/packages/core/test/helpers/producers.ts +++ b/packages/core/test/helpers/producers.ts @@ -1,15 +1,13 @@ -import { File, ClearTextReporterOptions } from '@stryker-mutator/api/core'; +import { ClearTextReporterOptions } from '@stryker-mutator/api/core'; import { factory } from '@stryker-mutator/test-helpers'; -import { FileCoverageData } from 'istanbul-lib-coverage'; import { Logger } from 'log4js'; import * as sinon from 'sinon'; +import { ReplaySubject } from 'rxjs'; +import { TestRunner } from '@stryker-mutator/api/test_runner'; +import { Checker } from '@stryker-mutator/api/check'; -import SourceFile from '../../src/SourceFile'; -import TestableMutant from '../../src/TestableMutant'; -import TranspiledMutant from '../../src/TranspiledMutant'; -import { CoverageMaps } from '../../src/transpiler/CoverageInstrumenterTranspiler'; -import { MappedLocation } from '../../src/transpiler/SourceMapper'; -import TranspileResult from '../../src/transpiler/TranspileResult'; +import { MutantTestCoverage } from '../../src/mutants/findMutantTestCoverage'; +import { Worker, Pool, ConcurrencyTokenProvider } from '../../src/concurrent'; export type Mutable = { -readonly [K in keyof T]: T[K]; @@ -35,6 +33,51 @@ export const createClearTextReporterOptions = factoryMethod = sinon.SinonStubbedInstance> & { + worker$: ReplaySubject>; +}; + +export type ConcurrencyTokenProviderMock = sinon.SinonStubbedInstance & { + testRunnerToken$: ReplaySubject; + checkerToken$: ReplaySubject; +}; + +export function createConcurrencyTokenProviderMock(): ConcurrencyTokenProviderMock { + return { + checkerToken$: new ReplaySubject(), + testRunnerToken$: new ReplaySubject(), + dispose: sinon.stub(), + freeCheckers: sinon.stub(), + }; +} + +export function createTestRunnerPoolMock(): PoolMock { + return { + dispose: sinon.stub(), + recycle: sinon.stub(), + init: sinon.stub(), + worker$: new ReplaySubject>(), + }; +} + +export function createCheckerPoolMock(): PoolMock { + return { + dispose: sinon.stub(), + recycle: sinon.stub(), + init: sinon.stub(), + worker$: new ReplaySubject>(), + }; +} + +export function createMutantTestCoverage(overrides?: Partial): MutantTestCoverage { + return { + coveredByTests: true, + mutant: factory.mutant(), + estimatedNetTime: 10, + ...overrides, + }; +} + export const logger = (): Mock => { return { _log: sinon.stub(), @@ -61,44 +104,3 @@ export const logger = (): Mock => { warn: sinon.stub(), }; }; - -export const mappedLocation = factoryMethod(() => ({ - fileName: 'file.js', - location: factory.location(), -})); - -export const coverageMaps = factoryMethod(() => ({ - fnMap: {}, - statementMap: {}, -})); - -export const fileCoverageData = factoryMethod(() => ({ - b: {}, - branchMap: {}, - f: {}, - fnMap: {}, - path: '', - s: {}, - statementMap: {}, -})); - -export const transpileResult = factoryMethod(() => ({ - error: null, - outputFiles: [factory.file(), factory.file()], -})); - -export const sourceFile = () => new SourceFile(factory.file()); - -export const testableMutant = (fileName = 'file', mutatorName = 'foobarMutator') => - new TestableMutant( - '1337', - factory.mutant({ - fileName, - mutatorName, - range: [12, 13], - replacement: '-', - }), - new SourceFile(new File(fileName, Buffer.from('const a = 4 + 5'))) - ); - -export const transpiledMutant = (fileName = 'file') => new TranspiledMutant(testableMutant(fileName), transpileResult(), true); diff --git a/packages/core/test/integration/child-proxy/ChildProcessProxy.it.spec.ts b/packages/core/test/integration/child-proxy/ChildProcessProxy.it.spec.ts index 9c5b0241c3..821cb3fa70 100644 --- a/packages/core/test/integration/child-proxy/ChildProcessProxy.it.spec.ts +++ b/packages/core/test/integration/child-proxy/ChildProcessProxy.it.spec.ts @@ -7,11 +7,11 @@ import { testInjector, LoggingServer } from '@stryker-mutator/test-helpers'; import { expect } from 'chai'; import * as log4js from 'log4js'; import { filter } from 'rxjs/operators'; +import { Task } from '@stryker-mutator/util'; import ChildProcessCrashedError from '../../../src/child-proxy/ChildProcessCrashedError'; import ChildProcessProxy from '../../../src/child-proxy/ChildProcessProxy'; import OutOfMemoryError from '../../../src/child-proxy/OutOfMemoryError'; -import { Task } from '../../../src/utils/Task'; import currentLogMock from '../../helpers/logMock'; import { Mock } from '../../helpers/producers'; import { sleep } from '../../helpers/testUtils'; diff --git a/packages/core/test/integration/child-proxy/Echo.ts b/packages/core/test/integration/child-proxy/Echo.ts index 4741249a47..9a9fa5e418 100644 --- a/packages/core/test/integration/child-proxy/Echo.ts +++ b/packages/core/test/integration/child-proxy/Echo.ts @@ -27,7 +27,7 @@ export class Echo { public exit(code: number) { process.exit(code); return new Promise(() => { - /*never resolve*/ + /* Never resolve */ }); } diff --git a/packages/core/test/integration/command-test-runner/CommandTestRunner.it.spec.ts b/packages/core/test/integration/command-test-runner/CommandTestRunner.it.spec.ts index 528a28e85a..9c10927a28 100644 --- a/packages/core/test/integration/command-test-runner/CommandTestRunner.it.spec.ts +++ b/packages/core/test/integration/command-test-runner/CommandTestRunner.it.spec.ts @@ -1,52 +1,71 @@ import * as path from 'path'; -import { RunStatus, TestStatus } from '@stryker-mutator/api/test_runner'; +import { TestStatus, DryRunStatus } from '@stryker-mutator/api/test_runner'; import { factory } from '@stryker-mutator/test-helpers'; import { expect } from 'chai'; import * as sinon from 'sinon'; import { CommandRunnerOptions } from '@stryker-mutator/api/core'; +import { assertions } from '@stryker-mutator/test-helpers'; + import CommandTestRunner from '../../../src/test-runner/CommandTestRunner'; import * as objectUtils from '../../../src/utils/objectUtils'; describe(`${CommandTestRunner.name} integration`, () => { const workingDir = path.resolve(__dirname, '..', '..', '..', 'testResources', 'command-runner'); - it('should report test as successful', async () => { - const sut = createSut(); - const result = await sut.run(); - expect(RunStatus[result.status]).eq(RunStatus[RunStatus.Complete]); - expect(result.tests).lengthOf(1); - expect(TestStatus[result.tests[0].status]).eq(TestStatus[TestStatus.Success]); - expect(result.tests[0].name).eq('All tests'); - expect(result.tests[0].timeSpentMs).greaterThan(1); - }); + describe(CommandTestRunner.prototype.dryRun.name, () => { + it('should report test as successful', async () => { + const sut = createSut(); + const result = await sut.dryRun({ coverageAnalysis: 'off' }); + assertions.expectCompleted(result); + expect(result.tests).lengthOf(1); + expect(result.tests[0].status).eq(TestStatus.Success); + expect(result.tests[0].id).eq('all'); + expect(result.tests[0].name).eq('All tests'); + expect(result.tests[0].timeSpentMs).greaterThan(1); + }); - it('should report test as failed if exit code != 0', async () => { - const sut = createSut({ command: 'npm run fail' }); - const result = await sut.run(); - expect(RunStatus[result.status]).eq(RunStatus[RunStatus.Complete]); - expect(result.tests).lengthOf(1); - expect(TestStatus[result.tests[0].status]).eq(TestStatus[TestStatus.Failed]); - expect(result.tests[0].name).eq('All tests'); - expect(result.tests[0].failureMessages).lengthOf(1); - expect((result.tests[0].failureMessages as string[])[0]).includes('Test 2 - NOK'); - expect(result.tests[0].timeSpentMs).greaterThan(1); - }); + it('should report test as failed if exit code != 0', async () => { + const sut = createSut({ command: 'npm run fail' }); + const result = await sut.dryRun({ coverageAnalysis: 'off' }); + assertions.expectCompleted(result); + expect(result.tests).lengthOf(1); + expect(TestStatus[result.tests[0].status]).eq(TestStatus[TestStatus.Failed]); + expect(result.tests[0].name).eq('All tests'); + assertions.expectFailed(result.tests[0]); + expect(result.tests[0].failureMessage).includes('Test 2 - NOK'); + expect(result.tests[0].timeSpentMs).greaterThan(1); + }); - it('should kill the child process and timeout the run result if dispose is called', async () => { - // Arrange - const killSpy = sinon.spy(objectUtils, 'kill'); - const sut = createSut({ command: 'npm run wait' }); - const runPromise = sut.run(); + it('should kill the child process and timeout the run result if dispose is called', async () => { + // Arrange + const killSpy = sinon.spy(objectUtils, 'kill'); + const sut = createSut({ command: 'npm run wait' }); + const runPromise = sut.dryRun({ coverageAnalysis: 'off' }); - // Act - await sut.dispose(); - const result = await runPromise; + // Act + await sut.dispose(); + const result = await runPromise; + + // Assert + expect(result.status).eq(DryRunStatus.Timeout); + expect(killSpy).called; + }); + }); - // Assert - expect(RunStatus[result.status]).eq(RunStatus[RunStatus.Timeout]); - expect(killSpy).called; + describe(CommandTestRunner.prototype.mutantRun.name, () => { + it('should report mutant as survived if the process exits with 0', async () => { + const sut = createSut({ command: 'npm run mutant' }); + const result = await sut.mutantRun({ activeMutant: factory.mutant({ id: 41 }) }); + assertions.expectSurvived(result); + }); + it('should report mutant as killed if the process exits with 1', async () => { + const sut = createSut({ command: 'npm run mutant' }); + const result = await sut.mutantRun({ activeMutant: factory.mutant({ id: 42 /* 42 should fail */ }) }); + assertions.expectKilled(result); + expect(result.killedBy).eq('all'); + }); }); function createSut(settings?: CommandRunnerOptions) { diff --git a/packages/core/test/integration/config-reader/ConfigReader.it.spec.ts b/packages/core/test/integration/config-reader/ConfigReader.it.spec.ts index 1fbb60dd69..65fd15b592 100644 --- a/packages/core/test/integration/config-reader/ConfigReader.it.spec.ts +++ b/packages/core/test/integration/config-reader/ConfigReader.it.spec.ts @@ -20,73 +20,74 @@ describe(ConfigReader.name, () => { .injectClass(ConfigReader); } + function resolveTestResource(...segments: string[]) { + return path.resolve(__dirname, '..', '..', '..', 'testResources', 'config-reader', ...segments); + } + + let originalCwd: string; + + beforeEach(() => { + originalCwd = process.cwd(); + }); + + afterEach(() => { + process.chdir(originalCwd); + }); + describe('readConfig()', () => { - let result: StrykerOptions; - describe('without config file', () => { - beforeEach(() => { - sut = createSut({ some: 'option', someOther: 2 }); - result = sut.readConfig(); - }); + it('should use cli options', () => { + process.chdir(resolveTestResource('empty-json')); + sut = createSut({ some: 'option', someOther: 2 }); + const result = sut.readConfig(); + expect(result.some).to.be.eq('option'); + expect(result.someOther).to.be.eq(2); + }); - it('should only use supplied config', () => { - expect(result.some).to.be.eq('option'); - expect(result.someOther).to.be.eq(2); - expect(testInjector.logger.warn).not.called; - }); + it('should throw an error with a non-existing config file', () => { + sut = createSut({ configFile: 'no-file.js' }); + + expect(() => sut.readConfig()).throws(`File ${path.resolve('no-file.js')} does not exist!`); }); describe('without config file or CLI options', () => { - describe('with a stryker.conf.js in the CWD', () => { - it('should parse the config', () => { - const mockCwd = path.resolve(__dirname, '..', '..', '..', 'testResources', 'config-reader', 'js'); - sinon.stub(process, 'cwd').returns(mockCwd); - sut = createSut({}); + it('should parse the stryker.conf.js config in cwd', () => { + process.chdir(resolveTestResource('js')); + sut = createSut({}); - result = sut.readConfig(); + const result = sut.readConfig(); - expect(result.type).to.be.eq('js'); - expect(testInjector.logger.warn).not.called; - }); + expect(result.type).to.be.eq('js'); + expect(testInjector.logger.warn).not.called; }); - describe('with a stryker.conf.json in the CWD', () => { - it('should parse the config', () => { - const mockCwd = path.resolve(__dirname, '..', '..', '..', 'testResources', 'config-reader', 'json'); - sinon.stub(process, 'cwd').returns(mockCwd); - sut = createSut({}); + it('should use the stryker.conf.json file in cwd', () => { + process.chdir(resolveTestResource('json')); + sut = createSut({}); - result = sut.readConfig(); + const result = sut.readConfig(); - expect(result.type).to.be.eq('json'); - expect(testInjector.logger.warn).not.called; - }); + expect(result.type).to.be.eq('json'); + expect(testInjector.logger.warn).not.called; }); - describe('with a stryker.conf.js and stryker.conf.json in the CWD', () => { - it('should parse the js config', () => { - const mockCwd = path.resolve(__dirname, '..', '..', '..', 'testResources', 'config-reader', 'json-and-js'); - sinon.stub(process, 'cwd').returns(mockCwd); - sut = createSut({}); + it('should use the stryker.conf.js file if both stryker.conf.js and stryker.conf.json are available', () => { + process.chdir(resolveTestResource('json-and-js')); + sut = createSut({}); - result = sut.readConfig(); + const result = sut.readConfig(); - expect(result.type).to.be.eq('js'); - expect(testInjector.logger.warn).not.called; - }); + expect(result.type).to.be.eq('js'); + expect(testInjector.logger.warn).not.called; }); - describe('without a stryker.conf.js in the CWD', () => { - it('should return default config', () => { - const mockCwd = path.resolve(__dirname, '..', '..', '..', 'testResources', 'config-reader', 'no-config'); - sinon.stub(process, 'cwd').returns(mockCwd); - - sut = createSut({}); + it('should use the default config if no stryker.conf file was found', () => { + process.chdir(resolveTestResource('no-config')); - result = sut.readConfig(); + sut = createSut({}); + const result = sut.readConfig(); - expect(result).to.deep.equal(factory.strykerOptions()); - expect(testInjector.logger.warn).not.called; - }); + expect(result).to.deep.equal(factory.strykerOptions()); + expect(testInjector.logger.warn).not.called; }); }); @@ -94,7 +95,7 @@ describe(ConfigReader.name, () => { it('should read config file', () => { sut = createSut({ configFile: 'testResources/config-reader/valid.conf.js' }); - result = sut.readConfig(); + const result = sut.readConfig(); expect(result.valid).to.be.eq('config'); expect(result.should).to.be.eq('be'); @@ -102,34 +103,29 @@ describe(ConfigReader.name, () => { expect(testInjector.logger.warn).not.called; }); - describe('with CLI options', () => { - it('should give precedence to CLI options', () => { - sut = createSut({ configFile: 'testResources/config-reader/valid.conf.js', read: false }); + it('should give precedence to CLI options', () => { + sut = createSut({ configFile: 'testResources/config-reader/valid.conf.js', read: false }); - result = sut.readConfig(); + const result = sut.readConfig(); - expect(result.read).to.be.eq(false); - expect(testInjector.logger.warn).not.called; - }); + expect(result.read).to.be.eq(false); + expect(testInjector.logger.warn).not.called; }); - }); - describe('with non-existing config file', () => { - beforeEach(() => { - sut = createSut({ configFile: 'no-file.js' }); - }); + it('should read a json config file', () => { + sut = createSut({ configFile: 'testResources/config-reader/valid.json' }); - it('should throw an error', () => { - expect(() => sut.readConfig()).throws(`File ${path.resolve('no-file.js')} does not exist!`); - }); - }); + const result = sut.readConfig(); - describe('with an existing file, but not a function or object', () => { - beforeEach(() => { - sut = createSut({ configFile: 'testResources/config-reader/invalid.conf.js' }); + expect(result.valid).to.be.eq('config'); + expect(result.should).to.be.eq('be'); + expect(result.read).to.be.eq(true); + expect(testInjector.logger.warn).not.called; }); - + }); + describe('when the config is not a function or object', () => { it('should report a fatal error', () => { + sut = createSut({ configFile: 'testResources/config-reader/invalid.conf.js' }); expect(() => sut.readConfig()).throws(); expect(testInjector.logger.fatal).calledWithMatch( sinon @@ -139,6 +135,7 @@ describe(ConfigReader.name, () => { }); it('should throw an error', () => { + sut = createSut({ configFile: 'testResources/config-reader/invalid.conf.js' }); expect(() => sut.readConfig()).throws('Config file must export an object'); }); }); @@ -153,16 +150,14 @@ describe(ConfigReader.name, () => { }); }); - describe('with json config file', () => { - it('should read config file', () => { - sut = createSut({ configFile: 'testResources/config-reader/valid.json' }); - - result = sut.readConfig(); + describe('deprecation informations', () => { + it('should report deprecation on module.export = function(config) {}', () => { + sut = createSut({ configFile: 'testResources/config-reader/deprecatedFunction.conf.js' }); + sut.readConfig(); - expect(result.valid).to.be.eq('config'); - expect(result.should).to.be.eq('be'); - expect(result.read).to.be.eq(true); - expect(testInjector.logger.warn).not.called; + expect(testInjector.logger.warn).calledWithMatch( + 'Usage of `module.export = function(config) {}` is deprecated. Please use `module.export = {}` or a "stryker.conf.json" file. For more details, see https://stryker-mutator.io/blog/2020-03-11/stryker-version-3#new-config-format' + ); }); }); }); diff --git a/packages/core/test/integration/input/InputFileResolver.it.spec.ts b/packages/core/test/integration/input/InputFileResolver.it.spec.ts new file mode 100644 index 0000000000..0f464608c7 --- /dev/null +++ b/packages/core/test/integration/input/InputFileResolver.it.spec.ts @@ -0,0 +1,47 @@ +import path = require('path'); + +import { factory, testInjector } from '@stryker-mutator/test-helpers'; +import { expect } from 'chai'; + +import { coreTokens } from '../../../src/di'; +import InputFileResolver from '../../../src/input/InputFileResolver'; + +const resolveTestResource: typeof path.resolve = path.resolve.bind( + path, + __dirname, + '..' /* input */, + '..' /* integration */, + '..' /* test */, + 'testResources', + 'input-files' +); + +describe(`${InputFileResolver.name} integration`, () => { + let sut: InputFileResolver; + let originalCwd: string; + + beforeEach(() => { + originalCwd = process.cwd(); + sut = testInjector.injector.provideValue(coreTokens.reporter, factory.reporter()).injectClass(InputFileResolver); + }); + + afterEach(() => { + process.chdir(originalCwd); + }); + + it('should by default resolve reasonable project source files to be mutated', async () => { + process.chdir(resolveTestResource()); + const inputFiles = await sut.resolve(); + expect(inputFiles.filesToMutate.map((file) => file.name)).deep.eq([ + resolveTestResource('lib', 'string-utils.js'), + resolveTestResource('src', 'app.ts'), + resolveTestResource('src', 'components', 'calculator', 'calculator.component.tsx'), + resolveTestResource('src', 'components', 'heading', 'heading.component.vue'), + resolveTestResource('src', 'index.html'), + resolveTestResource('src', 'services', 'storage.ts'), + resolveTestResource('src', 'services', 'test.ts'), + resolveTestResource('src', 'utils', 'commonjs.cjs'), + resolveTestResource('src', 'utils', 'esm.mjs'), + ]); + }); +}); diff --git a/packages/core/test/integration/options-validation/options-validation.it.spec.ts b/packages/core/test/integration/options-validation/options-validation.it.spec.ts index f480540c2c..b254470e60 100644 --- a/packages/core/test/integration/options-validation/options-validation.it.spec.ts +++ b/packages/core/test/integration/options-validation/options-validation.it.spec.ts @@ -2,18 +2,18 @@ import { expect } from 'chai'; import { testInjector } from '@stryker-mutator/test-helpers'; import { commonTokens } from '@stryker-mutator/api/plugin'; -import { createPluginResolverInjector } from '../../../src/di'; -import { resolveFromRoot } from '../../helpers/testUtils'; - import sinon = require('sinon'); +import { createPluginResolverProvider, coreTokens } from '../../../src/di'; + +import { resolveFromRoot } from '../../helpers/testUtils'; + describe('Options validation integration', () => { it('should log about unknown properties in log file', () => { - const optionsProvider = createPluginResolverInjector( - { + const optionsProvider = createPluginResolverProvider( + testInjector.injector.provideValue(coreTokens.cliOptions, { configFile: resolveFromRoot('testResources', 'options-validation', 'unknown-options.conf.json'), - }, - testInjector.injector + }) ); optionsProvider.resolve(commonTokens.options); expect(testInjector.logger.warn).calledWithMatch(sinon.match('Unknown stryker config option "this is an unknown property"')); diff --git a/packages/core/test/integration/source-mapper/SourceMapper.it.spec.ts b/packages/core/test/integration/source-mapper/SourceMapper.it.spec.ts deleted file mode 100644 index f321840a1c..0000000000 --- a/packages/core/test/integration/source-mapper/SourceMapper.it.spec.ts +++ /dev/null @@ -1,68 +0,0 @@ -import * as path from 'path'; -import { promises as fs } from 'fs'; - -import { File } from '@stryker-mutator/api/core'; -import { expect } from 'chai'; - -import { TranspiledSourceMapper } from '../../../src/transpiler/SourceMapper'; - -function resolve(...filePart: string[]) { - return path.resolve(__dirname, '..', '..', '..', 'testResources', 'source-mapper', ...filePart); -} - -function readFiles(...files: string[]): Promise { - return Promise.all( - files.map((relative) => resolve(relative)).map((fileName) => fs.readFile(fileName).then((content) => new File(fileName, content))) - ); -} - -describe('Source mapper integration', () => { - let sut: TranspiledSourceMapper; - - describe('with external source maps', () => { - beforeEach(async () => { - const files = await readFiles(path.join('external-source-maps', 'js', 'math.js'), path.join('external-source-maps', 'js', 'math.js.map')); - sut = new TranspiledSourceMapper(files); - }); - - it('it should be able to map to transpiled location', async () => { - const actual = await sut.transpiledLocationFor({ - fileName: resolve('external-source-maps', 'ts', 'src', 'math.ts'), - location: { - end: { line: 7, column: 42 }, - start: { line: 7, column: 8 }, - }, - }); - expect(actual).deep.eq({ - fileName: resolve('external-source-maps', 'js', 'math.js'), - location: { - end: { line: 16, column: 0 }, - start: { line: 15, column: 10 }, - }, - }); - }); - }); - - describe('with inline source maps', () => { - beforeEach(async () => { - const files = await readFiles(path.join('inline-source-maps', 'js', 'math.js')); - sut = new TranspiledSourceMapper(files); - }); - it('it should be able to map to transpiled location', async () => { - const actual = await sut.transpiledLocationFor({ - fileName: resolve('inline-source-maps', 'ts', 'src', 'math.ts'), - location: { - end: { line: 7, column: 42 }, - start: { line: 7, column: 8 }, - }, - }); - expect(actual).deep.eq({ - fileName: resolve('inline-source-maps', 'js', 'math.js'), - location: { - end: { line: 16, column: 0 }, - start: { line: 15, column: 10 }, - }, - }); - }); - }); -}); diff --git a/packages/core/test/integration/test-runner/AdditionalTestRunners.ts b/packages/core/test/integration/test-runner/AdditionalTestRunners.ts index 2ea28052c1..8e64103c75 100644 --- a/packages/core/test/integration/test-runner/AdditionalTestRunners.ts +++ b/packages/core/test/integration/test-runner/AdditionalTestRunners.ts @@ -1,13 +1,20 @@ +import * as os from 'os'; import { isRegExp } from 'util'; import { StrykerOptions } from '@stryker-mutator/api/core'; import { commonTokens, declareClassPlugin, PluginKind, tokens } from '@stryker-mutator/api/plugin'; -import { RunResult, RunStatus, TestRunner } from '@stryker-mutator/api/test_runner'; +import { TestRunner, DryRunResult, DryRunStatus, MutantRunResult } from '@stryker-mutator/api/test_runner'; +import { factory } from '@stryker-mutator/test-helpers'; + +const fs = require('fs'); class CoverageReportingTestRunner implements TestRunner { - public run() { - (global as any).__coverage__ = 'overridden'; - return Promise.resolve({ status: RunStatus.Complete, tests: [], coverage: 'realCoverage' as any }); + public async dryRun(): Promise { + (global as any).__mutantCoverage__ = 'overridden'; + return { status: DryRunStatus.Complete, tests: [], mutantCoverage: factory.mutantCoverage({ static: { 1: 42 } }) }; + } + public async mutantRun(): Promise { + throw new Error('Method not implemented.'); } } @@ -16,22 +23,45 @@ class TimeBombTestRunner implements TestRunner { // Setting a time bomb after 100 ms setTimeout(() => process.exit(), 500); } - public run() { - return Promise.resolve({ status: RunStatus.Complete, tests: [] }); + public async dryRun(): Promise { + return factory.completeDryRunResult(); + } + public async mutantRun(): Promise { + throw new Error('Method not implemented.'); } } class ProximityMineTestRunner implements TestRunner { - public run() { + public async dryRun(): Promise { process.exit(42); - return Promise.resolve({ status: RunStatus.Complete, tests: [] }); + } + public async mutantRun(): Promise { + throw new Error('Method not implemented.'); + } +} + +export class CounterTestRunner implements TestRunner { + private count = 0; + public static COUNTER_FILE = `${os.tmpdir()}/counter-file`; + + public async dryRun(): Promise { + return factory.completeDryRunResult(); + } + + public async mutantRun(): Promise { + this.count++; + fs.writeFileSync(CounterTestRunner.COUNTER_FILE, `${this.count}`); + return factory.survivedMutantRunResult(); } } class DirectResolvedTestRunner implements TestRunner { - public run() { - (global as any).__coverage__ = 'coverageObject'; - return Promise.resolve({ status: RunStatus.Complete, tests: [] }); + public async dryRun(): Promise { + (global as any).__mutantCoverage__ = 'coverageObject'; + return factory.completeDryRunResult(); + } + public async mutantRun(): Promise { + throw new Error('Method not implemented.'); } } @@ -39,24 +69,30 @@ class DiscoverRegexTestRunner implements TestRunner { public static inject = tokens(commonTokens.options); constructor(private readonly options: StrykerOptions) {} - public run(): Promise { + public async dryRun(): Promise { if (isRegExp(this.options.someRegex)) { - return Promise.resolve({ status: RunStatus.Complete, tests: [] }); + return factory.completeDryRunResult(); } else { - return Promise.resolve({ status: RunStatus.Error, tests: [], errorMessages: ['No regex found in runnerOptions.strykerOptions.someRegex'] }); + return factory.errorDryRunResult({ errorMessage: 'No regex found in runnerOptions.strykerOptions.someRegex' }); } } + public async mutantRun(): Promise { + throw new Error('Method not implemented.'); + } } class ErroredTestRunner implements TestRunner { - public run() { + public async dryRun(): Promise { let expectedError: any = null; try { throw new SyntaxError('This is invalid syntax!'); } catch (error) { expectedError = error; } - return Promise.resolve({ status: RunStatus.Error, errorMessages: [expectedError], tests: [] }); + return factory.errorDryRunResult({ errorMessage: expectedError }); + } + public async mutantRun(): Promise { + throw new Error('Method not implemented.'); } } @@ -65,14 +101,20 @@ class RejectInitRunner implements TestRunner { return Promise.reject(new Error('Init was rejected')); } - public run(): Promise { + public async dryRun(): Promise { throw new Error(); } + public async mutantRun(): Promise { + throw new Error('Method not implemented.'); + } } class NeverResolvedTestRunner implements TestRunner { - public run() { - return new Promise(() => {}); + public dryRun(): Promise { + return new Promise(() => {}); + } + public async mutantRun(): Promise { + throw new Error('Method not implemented.'); } } @@ -89,11 +131,15 @@ class SlowInitAndDisposeTestRunner implements TestRunner { }); } - public run() { + public async dryRun() { if (this.inInit) { throw new Error('Test should fail! Not yet initialized!'); } - return Promise.resolve({ status: RunStatus.Complete, tests: [] }); + return factory.completeDryRunResult(); + } + + public async mutantRun(): Promise { + throw new Error('Method not implemented.'); } public dispose() { @@ -101,27 +147,30 @@ class SlowInitAndDisposeTestRunner implements TestRunner { } } class VerifyWorkingFolderTestRunner implements TestRunner { - public runResult: RunResult = { status: RunStatus.Complete, tests: [] }; - - public run() { + public async dryRun(): Promise { if (process.cwd().toLowerCase() === __dirname.toLowerCase()) { - return Promise.resolve(this.runResult); + return factory.completeDryRunResult(); } else { - return Promise.reject(new Error(`Expected ${process.cwd()} to be ${__dirname}`)); + throw new Error(`Expected ${process.cwd()} to be ${__dirname}`); } } + public async mutantRun(): Promise { + throw new Error('Method not implemented.'); + } } class AsyncronousPromiseRejectionHandlerTestRunner implements TestRunner { public promise: Promise; - public init() { + public async init() { this.promise = Promise.reject('Reject for now, but will be caught asynchronously'); } - - public run() { + public async dryRun(): Promise { this.promise.catch(() => {}); - return Promise.resolve({ status: RunStatus.Complete, tests: [] }); + return factory.completeDryRunResult(); + } + public async mutantRun(): Promise { + throw new Error('Method not implemented.'); } } @@ -135,6 +184,7 @@ export const strykerPlugins = [ declareClassPlugin(PluginKind.TestRunner, 'coverage-reporting', CoverageReportingTestRunner), declareClassPlugin(PluginKind.TestRunner, 'time-bomb', TimeBombTestRunner), declareClassPlugin(PluginKind.TestRunner, 'proximity-mine', ProximityMineTestRunner), + declareClassPlugin(PluginKind.TestRunner, 'counter', CounterTestRunner), declareClassPlugin(PluginKind.TestRunner, 'async-promise-rejection-handler', AsyncronousPromiseRejectionHandlerTestRunner), declareClassPlugin(PluginKind.TestRunner, 'reject-init', RejectInitRunner), ]; diff --git a/packages/core/test/integration/test-runner/ResilientTestRunnerFactory.it.spec.ts b/packages/core/test/integration/test-runner/ResilientTestRunnerFactory.it.spec.ts deleted file mode 100644 index e6132d4679..0000000000 --- a/packages/core/test/integration/test-runner/ResilientTestRunnerFactory.it.spec.ts +++ /dev/null @@ -1,161 +0,0 @@ -import * as path from 'path'; - -import { LogLevel, StrykerOptions } from '@stryker-mutator/api/core'; -import { RunStatus, TestRunner } from '@stryker-mutator/api/test_runner'; -import { strykerOptions } from '@stryker-mutator/test-helpers/src/factory'; -import { expect } from 'chai'; -import * as log4js from 'log4js'; -import { toArray } from 'rxjs/operators'; -import { LoggingServer } from '@stryker-mutator/test-helpers'; - -import LoggingClientContext from '../../../src/logging/LoggingClientContext'; -import ResilientTestRunnerFactory from '../../../src/test-runner/ResilientTestRunnerFactory'; -import { sleep } from '../../helpers/testUtils'; - -describe('ResilientTestRunnerFactory integration', () => { - let sut: Required; - let options: StrykerOptions; - const sandboxWorkingDirectory = path.resolve('./test/integration/test-runner'); - let loggingContext: LoggingClientContext; - - let loggingServer: LoggingServer; - let alreadyDisposed: boolean; - - beforeEach(async () => { - // Make sure there is a logging server listening - loggingServer = new LoggingServer(); - const port = await loggingServer.listen(); - loggingContext = { port, level: LogLevel.Trace }; - options = strykerOptions({ - plugins: [require.resolve('./AdditionalTestRunners')], - someRegex: /someRegex/, - testFramework: 'jasmine', - testRunner: 'karma', - }); - alreadyDisposed = false; - }); - - afterEach(async () => { - if (!alreadyDisposed) { - await sut.dispose(); - } - await loggingServer.dispose(); - }); - - function createSut(name: string) { - options.testRunner = name; - sut = ResilientTestRunnerFactory.create(options, [], sandboxWorkingDirectory, loggingContext); - } - - async function arrangeSut(name: string): Promise { - createSut(name); - await sut.init(); - } - - function actRun(timeout = 4000) { - return sut.run({ timeout }); - } - - it('should be able to receive a regex', async () => { - await arrangeSut('discover-regex'); - const result = await actRun(); - expect(result.status).eq(RunStatus.Complete); - }); - - it('should pass along the coverage result from the test runner behind', async () => { - await arrangeSut('coverage-reporting'); - const result = await actRun(); - expect(result.coverage).eq('realCoverage'); - }); - - it('should pass along the run result', async () => { - await arrangeSut('direct-resolved'); - const result = await actRun(); - expect(result.status).eq(RunStatus.Complete); - }); - - it('should try to report coverage from the global scope, even when the test runner behind does not', async () => { - await arrangeSut('direct-resolved'); - const result = await actRun(); - expect(result.coverage).eq('coverageObject'); - }); - - it('should resolve in a timeout if the test runner never resolves', async () => { - await arrangeSut('never-resolved'); - const result = await actRun(1000); - expect(RunStatus[result.status]).eq(RunStatus[RunStatus.Timeout]); - }); - - it('should be able to recover from a timeout by creating a new child process', async () => { - await arrangeSut('never-resolved'); - await actRun(1000); // first timeout - const result = await actRun(1000); - expect(RunStatus[result.status]).eq(RunStatus[RunStatus.Timeout]); - }); - - it('should convert any `Error` objects to string', async () => { - await arrangeSut('errored'); - const result = await actRun(1000); - expect(RunStatus[result.status]).to.be.eq(RunStatus[RunStatus.Error]); - expect(result.errorMessages).to.have.length(1); - expect((result.errorMessages as any)[0]) - .includes('SyntaxError: This is invalid syntax!') - .and.includes('at ErroredTestRunner.run'); - }); - - it('should run only after initialization, even when it is slow', async () => { - await arrangeSut('slow-init-dispose'); - const result = await actRun(1000); - expect(RunStatus[result.status]).eq(RunStatus[RunStatus.Complete]); - }); - - it('should be able to run twice in quick succession', async () => { - await arrangeSut('direct-resolved'); - const result = await actRun(); - expect(RunStatus[result.status]).eq(RunStatus[RunStatus.Complete]); - }); - - it('should reject when `init` of test runner behind rejects', async () => { - createSut('reject-init'); - await expect(sut.init()).rejectedWith('Init was rejected'); - }); - - it('should change the current working directory to the sandbox directory', async () => { - await arrangeSut('verify-working-folder'); - const result = await actRun(); - expect(result.errorMessages).undefined; - }); - - it('should be able to recover from an async crash', async () => { - // time-bomb will crash after 500 ms - await arrangeSut('time-bomb'); - await sleep(550); - const result = await actRun(); - expect(RunStatus[result.status]).eq(RunStatus[RunStatus.Complete]); - expect(result.errorMessages).undefined; - }); - - it('should report if a crash happens twice', async () => { - await arrangeSut('proximity-mine'); - const result = await actRun(); - expect(RunStatus[result.status]).eq(RunStatus[RunStatus.Error]); - expect(result.errorMessages).property('0').contains('Test runner crashed'); - }); - - it('should handle asynchronously handled promise rejections from the underlying test runner', async () => { - const logEvents = loggingServer.event$.pipe(toArray()).toPromise(); - await arrangeSut('async-promise-rejection-handler'); - await actRun(); - await sut.dispose(); - alreadyDisposed = true; - await loggingServer.dispose(); - const actualLogEvents = await logEvents; - expect( - actualLogEvents.find( - (logEvent) => - log4js.levels.DEBUG.isEqualTo(logEvent.level) && - logEvent.data.toString().includes('UnhandledPromiseRejectionWarning: Unhandled promise rejection') - ) - ).ok; - }); -}); diff --git a/packages/core/test/integration/test-runner/createTestRunnerFactory.it.spec.ts b/packages/core/test/integration/test-runner/createTestRunnerFactory.it.spec.ts new file mode 100644 index 0000000000..a38b35eb15 --- /dev/null +++ b/packages/core/test/integration/test-runner/createTestRunnerFactory.it.spec.ts @@ -0,0 +1,189 @@ +import { LogLevel } from '@stryker-mutator/api/core'; +import { expect } from 'chai'; +import * as log4js from 'log4js'; +import { toArray } from 'rxjs/operators'; +import { LoggingServer, testInjector, factory } from '@stryker-mutator/test-helpers'; + +import { TestRunner, DryRunStatus } from '@stryker-mutator/api/test_runner'; + +import { expectCompleted, expectErrored } from '@stryker-mutator/test-helpers/src/assertions'; + +import { LoggingClientContext } from '../../../src/logging'; +import { createTestRunnerFactory } from '../../../src/test-runner'; +import { sleep } from '../../helpers/testUtils'; +import { coreTokens } from '../../../src/di'; + +import { CounterTestRunner } from './AdditionalTestRunners'; + +const fs = require('fs'); + +describe(`${createTestRunnerFactory.name} integration`, () => { + let createSut: () => Required; + let sut: Required; + let loggingContext: LoggingClientContext; + + let loggingServer: LoggingServer; + let alreadyDisposed: boolean; + + beforeEach(async () => { + // Make sure there is a logging server listening + loggingServer = new LoggingServer(); + const port = await loggingServer.listen(); + loggingContext = { port, level: LogLevel.Trace }; + testInjector.options.plugins = [require.resolve('./AdditionalTestRunners')]; + testInjector.options.someRegex = /someRegex/; + testInjector.options.testRunner = 'karma'; + testInjector.options.maxTestRunnerReuse = 0; + alreadyDisposed = false; + createSut = testInjector.injector + .provideValue(coreTokens.sandbox, { sandboxFileNames: ['foo.js'], workingDirectory: __dirname }) + .provideValue(coreTokens.loggingContext, loggingContext) + .injectFunction(createTestRunnerFactory); + + if (fs.existsSync(CounterTestRunner.COUNTER_FILE)) { + await fs.unlinkSync(CounterTestRunner.COUNTER_FILE); + } + }); + + afterEach(async () => { + if (!alreadyDisposed) { + await sut.dispose(); + } + await loggingServer.dispose(); + + if (fs.existsSync(CounterTestRunner.COUNTER_FILE)) { + await fs.unlinkSync(CounterTestRunner.COUNTER_FILE); + } + }); + + async function arrangeSut(name: string): Promise { + testInjector.options.testRunner = name; + sut = createSut(); + await sut.init(); + } + + function actDryRun(timeout = 4000) { + return sut.dryRun({ timeout, coverageAnalysis: 'all' }); + } + + function actMutantRun() { + return sut.mutantRun(factory.mutantRunOptions()); + } + + it('should be able to receive a regex', async () => { + await arrangeSut('discover-regex'); + const result = await actDryRun(); + expect(result.status).eq(DryRunStatus.Complete); + }); + + it('should pass along the coverage result from the test runner behind', async () => { + await arrangeSut('coverage-reporting'); + const result = await actDryRun(); + expectCompleted(result); + expect(result.mutantCoverage).deep.eq(factory.mutantCoverage({ static: { 1: 42 } })); + }); + + it('should pass along the run result', async () => { + await arrangeSut('direct-resolved'); + const result = await actDryRun(); + expect(result.status).eq(DryRunStatus.Complete); + }); + + it('should try to report coverage from the global scope, even when the test runner behind does not', async () => { + await arrangeSut('direct-resolved'); + const result = await actDryRun(); + expectCompleted(result); + expect(result.mutantCoverage).eq('coverageObject'); + }); + + it('should resolve in a timeout if the test runner never resolves', async () => { + await arrangeSut('never-resolved'); + const result = await actDryRun(1000); + expect(result.status).eq(DryRunStatus.Timeout); + }); + + it('should be able to recover from a timeout by creating a new child process', async () => { + await arrangeSut('never-resolved'); + await actDryRun(1000); // first timeout + const result = await actDryRun(1000); + expect(result.status).eq(DryRunStatus.Timeout); + }); + + it('should convert any `Error` objects to string', async () => { + await arrangeSut('errored'); + const result = await actDryRun(1000); + expectErrored(result); + expect(result.errorMessage).includes('SyntaxError: This is invalid syntax!').and.includes('at ErroredTestRunner.dryRun'); + }); + + it('should run only after initialization, even when it is slow', async () => { + await arrangeSut('slow-init-dispose'); + const result = await actDryRun(1000); + expectCompleted(result); + }); + + it('should be able to run twice in quick succession', async () => { + await arrangeSut('direct-resolved'); + const result = await actDryRun(); + expectCompleted(result); + }); + + it('should reject when `init` of test runner behind rejects', async () => { + await expect(arrangeSut('reject-init')).rejectedWith('Init was rejected'); + }); + + it('should change the current working directory to the sandbox directory', async () => { + await arrangeSut('verify-working-folder'); + const result = await actDryRun(); + expectCompleted(result); + }); + + it('should be able to recover from an async crash', async () => { + // time-bomb will crash after 500 ms + await arrangeSut('time-bomb'); + await sleep(550); + const result = await actDryRun(); + expectCompleted(result); + }); + + it('should report if a crash happens twice', async () => { + await arrangeSut('proximity-mine'); + const result = await actDryRun(); + expectErrored(result); + expect(result.errorMessage).contains('Test runner crashed'); + }); + + it('should handle asynchronously handled promise rejections from the underlying test runner', async () => { + const logEvents = loggingServer.event$.pipe(toArray()).toPromise(); + await arrangeSut('async-promise-rejection-handler'); + await actDryRun(); + await sut.dispose(); + alreadyDisposed = true; + await loggingServer.dispose(); + const actualLogEvents = await logEvents; + expect( + actualLogEvents.find( + (logEvent) => + log4js.levels.DEBUG.isEqualTo(logEvent.level) && + logEvent.data.toString().includes('UnhandledPromiseRejectionWarning: Unhandled promise rejection') + ) + ).ok; + }); + + it('should restart the worker after it has exceeded the maxTestRunnerReuse', async () => { + testInjector.options.maxTestRunnerReuse = 3; + await arrangeSut('counter'); + + await actMutantRun(); + expect(fs.readFileSync(CounterTestRunner.COUNTER_FILE, 'utf8')).to.equal('1'); + + await actMutantRun(); + expect(fs.readFileSync(CounterTestRunner.COUNTER_FILE, 'utf8')).to.equal('2'); + + await actMutantRun(); + expect(fs.readFileSync(CounterTestRunner.COUNTER_FILE, 'utf8')).to.equal('3'); + + await actMutantRun(); + expect(fs.readFileSync(CounterTestRunner.COUNTER_FILE, 'utf8')).to.equal('1'); + }); +}); diff --git a/packages/core/test/setup.ts b/packages/core/test/setup.ts new file mode 100644 index 0000000000..f166d2814a --- /dev/null +++ b/packages/core/test/setup.ts @@ -0,0 +1,16 @@ +import 'source-map-support/register'; +import * as chai from 'chai'; +import * as chaiAsPromised from 'chai-as-promised'; +import * as sinonChai from 'sinon-chai'; +import { testInjector } from '@stryker-mutator/test-helpers'; +import * as sinon from 'sinon'; + +chai.use(sinonChai); +chai.use(chaiAsPromised); + +export const mochaHooks = { + afterEach() { + sinon.restore(); + testInjector.reset(); + }, +}; diff --git a/packages/core/test/unit/Sandbox.spec.ts b/packages/core/test/unit/Sandbox.spec.ts deleted file mode 100644 index 473d1db808..0000000000 --- a/packages/core/test/unit/Sandbox.spec.ts +++ /dev/null @@ -1,320 +0,0 @@ -import * as path from 'path'; - -import { File, LogLevel, StrykerOptions } from '@stryker-mutator/api/core'; -import { Logger } from '@stryker-mutator/api/logging'; -import { Mutant } from '@stryker-mutator/api/mutant'; -import { MutantStatus } from '@stryker-mutator/api/report'; -import { TestFramework } from '@stryker-mutator/api/test_framework'; -import { RunResult, RunStatus } from '@stryker-mutator/api/test_runner'; -import { mutant as createMutant, fileAlreadyExistsError, testResult } from '@stryker-mutator/test-helpers/src/factory'; -import { normalizeWhitespaces } from '@stryker-mutator/util'; -import { expect } from 'chai'; -import * as mkdirp from 'mkdirp'; -import * as sinon from 'sinon'; - -import LoggingClientContext from '../../src/logging/LoggingClientContext'; -import Sandbox from '../../src/Sandbox'; -import SourceFile from '../../src/SourceFile'; -import ResilientTestRunnerFactory from '../../src/test-runner/ResilientTestRunnerFactory'; -import TestRunnerDecorator from '../../src/test-runner/TestRunnerDecorator'; -import TestableMutant, { TestSelectionResult } from '../../src/TestableMutant'; -import TranspiledMutant from '../../src/TranspiledMutant'; -import * as fileUtils from '../../src/utils/fileUtils'; -import { wrapInClosure } from '../../src/utils/objectUtils'; -import { TemporaryDirectory } from '../../src/utils/TemporaryDirectory'; -import currentLogMock from '../helpers/logMock'; -import { Mock } from '../helpers/producers'; - -const OVERHEAD_TIME_MS = 0; -const LOGGING_CONTEXT: LoggingClientContext = Object.freeze({ - level: LogLevel.Fatal, - port: 4200, -}); -const SANDBOX_INDEX = 3; - -describe(Sandbox.name, () => { - let options: StrykerOptions; - let inputFiles: File[]; - let testRunner: Mock; - let testFrameworkStub: sinon.SinonStubbedInstance; - let expectedFileToMutate: File; - let notMutatedFile: File; - let sandboxDirectory: string; - let expectedTargetFileToMutate: string; - let writeFileStub: sinon.SinonStub; - let symlinkJunctionStub: sinon.SinonStub; - let findNodeModulesStub: sinon.SinonStub; - let log: Mock; - let runResult: RunResult; - let temporaryDirectoryMock: sinon.SinonStubbedInstance; - - beforeEach(() => { - runResult = { tests: [], status: RunStatus.Complete }; - options = { timeoutFactor: 23, timeoutMS: 1000, testRunner: 'sandboxUnitTestRunner', symlinkNodeModules: true } as any; - testRunner = { init: sinon.stub(), run: sinon.stub().resolves(runResult), dispose: sinon.stub() }; - testFrameworkStub = { - filter: sinon.stub(), - afterEach: sinon.stub(), - beforeEach: sinon.stub(), - }; - expectedFileToMutate = new File(path.resolve('file1'), 'original code'); - notMutatedFile = new File(path.resolve('file2'), 'to be mutated'); - sandboxDirectory = path.resolve('random-folder-3'); - expectedTargetFileToMutate = path.join(sandboxDirectory, 'file1'); - inputFiles = [expectedFileToMutate, notMutatedFile]; - temporaryDirectoryMock = sinon.createStubInstance(TemporaryDirectory); - temporaryDirectoryMock.createRandomDirectory.returns(sandboxDirectory); - - writeFileStub = sinon.stub(fileUtils, 'writeFile'); - symlinkJunctionStub = sinon.stub(fileUtils, 'symlinkJunction'); - findNodeModulesStub = sinon.stub(fileUtils, 'findNodeModules'); - symlinkJunctionStub.resolves(); - findNodeModulesStub.resolves('node_modules'); - writeFileStub.resolves(); - sinon.stub(mkdirp, 'sync').returns(''); - sinon.stub(ResilientTestRunnerFactory, 'create').returns(testRunner); - log = currentLogMock(); - log.isDebugEnabled.returns(true); - }); - - interface CreateArgs { - testFramework: TestFramework | null; - overheadTimeMS: number; - files: readonly File[]; - } - function createSut(overrides?: Partial) { - const { files, testFramework, overheadTimeMS }: CreateArgs = { - files: inputFiles, - overheadTimeMS: OVERHEAD_TIME_MS, - testFramework: null, - ...overrides, - }; - return Sandbox.create(options, SANDBOX_INDEX, files, testFramework, overheadTimeMS, LOGGING_CONTEXT, temporaryDirectoryMock as any); - } - - describe('create()', () => { - it('should copy input files when created', async () => { - await createSut(); - expect(fileUtils.writeFile).calledWith(expectedTargetFileToMutate, inputFiles[0].content); - expect(fileUtils.writeFile).calledWith(path.join(sandboxDirectory, 'file2'), inputFiles[1].content); - }); - - it('should copy a local file when created', async () => { - await createSut({ files: [new File('localFile.js', 'foobar')] }); - expect(fileUtils.writeFile).calledWith(path.join(sandboxDirectory, 'localFile.js'), Buffer.from('foobar')); - }); - - it('should have created the isolated test runner', async () => { - await createSut(); - const expectedFileNames = inputFiles.map((file) => path.resolve(sandboxDirectory, path.basename(file.name))); - expect(ResilientTestRunnerFactory.create).calledWith(options, expectedFileNames, sandboxDirectory, LOGGING_CONTEXT); - }); - - it('should have created a sandbox folder', async () => { - await createSut({ testFramework: testFrameworkStub }); - expect(temporaryDirectoryMock.createRandomDirectory).calledWith('sandbox'); - }); - - it('should symlink node modules in sandbox directory if exists', async () => { - await createSut({ testFramework: testFrameworkStub }); - expect(findNodeModulesStub).calledWith(process.cwd()); - expect(symlinkJunctionStub).calledWith('node_modules', path.join(sandboxDirectory, 'node_modules')); - }); - - it('should not symlink node modules in sandbox directory if no node_modules exist', async () => { - findNodeModulesStub.resolves(null); - await createSut({ testFramework: testFrameworkStub }); - expect(log.warn).calledWithMatch('Could not find a node_modules'); - expect(log.warn).calledWithMatch(process.cwd()); - expect(symlinkJunctionStub).not.called; - }); - - it('should log a warning if "node_modules" already exists in the working folder', async () => { - findNodeModulesStub.resolves('node_modules'); - symlinkJunctionStub.rejects(fileAlreadyExistsError()); - await createSut({ testFramework: testFrameworkStub }); - expect(log.warn).calledWithMatch( - normalizeWhitespaces( - `Could not symlink "node_modules" in sandbox directory, it is already created in the sandbox. - Please remove the node_modules from your sandbox files. Alternatively, set \`symlinkNodeModules\` - to \`false\` to disable this warning.` - ) - ); - }); - - it('should log a warning if linking "node_modules" results in an unknown error', async () => { - findNodeModulesStub.resolves('basePath/node_modules'); - const error = new Error('unknown'); - symlinkJunctionStub.rejects(error); - await createSut({ testFramework: testFrameworkStub }); - expect(log.warn).calledWithMatch( - normalizeWhitespaces('Unexpected error while trying to symlink "basePath/node_modules" in sandbox directory.'), - error - ); - }); - - it('should symlink node modules in sandbox directory if `symlinkNodeModules` is `false`', async () => { - options.symlinkNodeModules = false; - await createSut({ testFramework: testFrameworkStub }); - expect(symlinkJunctionStub).not.called; - expect(findNodeModulesStub).not.called; - }); - }); - - describe('run()', () => { - it('should run the testRunner', async () => { - const sut = await createSut(); - await sut.run(231313, 'hooks'); - expect(testRunner.run).to.have.been.calledWith({ - mutatedFileName: undefined, - testHooks: 'hooks', - timeout: 231313, - }); - }); - - it('should run the testRunner with mutatedFileName', async () => { - const sut = await createSut(); - await sut.run(231313, 'hooks', 'path/to/file'); - expect(testRunner.run).to.have.been.calledWith({ - mutatedFileName: 'path/to/file', - testHooks: 'hooks', - timeout: 231313, - }); - }); - }); - - describe('runMutant()', () => { - let transpiledMutant: TranspiledMutant; - let mutant: Mutant; - const testFilterCodeFragment = 'Some code fragment'; - - beforeEach(() => { - mutant = createMutant({ fileName: expectedFileToMutate.name, replacement: 'mutated', range: [0, 8] }); - - const testableMutant = new TestableMutant('1', mutant, new SourceFile(new File('foobar.js', 'original code'))); - testableMutant.selectTest(testResult({ timeSpentMs: 10 }), 1); - testableMutant.selectTest(testResult({ timeSpentMs: 2 }), 2); - transpiledMutant = new TranspiledMutant( - testableMutant, - { outputFiles: [new File(expectedFileToMutate.name, 'mutated code')], error: null }, - true - ); - testFrameworkStub.filter.returns(testFilterCodeFragment); - }); - - it('should save the mutant to disk', async () => { - const sut = await createSut(); - await sut.runMutant(transpiledMutant); - expect(fileUtils.writeFile).calledWith(expectedTargetFileToMutate, Buffer.from('mutated code')); - expect(log.warn).not.called; - }); - - it('should nog log a warning if test selection was failed but already reported', async () => { - const sut = await createSut(); - transpiledMutant.mutant.testSelectionResult = TestSelectionResult.FailedButAlreadyReported; - await sut.runMutant(transpiledMutant); - expect(log.warn).not.called; - }); - - it('should log a warning if tests could not have been selected', async () => { - const sut = await createSut(); - transpiledMutant.mutant.testSelectionResult = TestSelectionResult.Failed; - await sut.runMutant(transpiledMutant); - const expectedLogMessage = `Failed find coverage data for this mutant, running all tests. This might have an impact on performance: ${transpiledMutant.mutant.toString()}`; - expect(log.warn).calledWith(expectedLogMessage); - }); - - it('should filter the scoped tests', async () => { - const sut = await createSut({ testFramework: testFrameworkStub }); - await sut.runMutant(transpiledMutant); - expect(testFrameworkStub.filter).to.have.been.calledWith(transpiledMutant.mutant.selectedTests); - expect(testRunner.run).calledWithMatch({ testHooks: wrapInClosure(testFilterCodeFragment) }); - }); - - it('should provide the filter code as testHooks, correct timeout and mutatedFileName', async () => { - options.timeoutMS = 1000; - const overheadTimeMS = 42; - const totalTimeSpend = 12; - const sut = await createSut({ overheadTimeMS, testFramework: testFrameworkStub }); - await sut.runMutant(transpiledMutant); - const expectedRunOptions = { - mutatedFileName: path.resolve('random-folder-3', 'file1'), - testHooks: wrapInClosure(testFilterCodeFragment), - timeout: totalTimeSpend * options.timeoutFactor + options.timeoutMS + overheadTimeMS, - }; - expect(testRunner.run).calledWith(expectedRunOptions); - }); - - it('should have reset the source file', async () => { - const sut = await createSut(); - await sut.runMutant(transpiledMutant); - const timesCalled = writeFileStub.getCalls().length - 1; - const lastCall = writeFileStub.getCall(timesCalled); - expect(lastCall.args).to.deep.equal([expectedTargetFileToMutate, Buffer.from('original code')]); - }); - - it('should not filter any tests when testFramework = null', async () => { - transpiledMutant.mutant.selectAllTests(runResult, TestSelectionResult.Success); - const sut = await createSut(); - await sut.runMutant(transpiledMutant); - expect(testRunner.run).calledWithMatch({ testHooks: undefined }); - }); - - it('should filter no tests when runAllTests = true', async () => { - // Arrange - while (transpiledMutant.mutant.selectedTests.pop()); - transpiledMutant.mutant.selectAllTests(runResult, TestSelectionResult.Success); - testFrameworkStub.filter.returns('empty filter'); - const sut = await createSut({ testFramework: testFrameworkStub }); - - // Act - await sut.runMutant(transpiledMutant); - - // Assert - expect(testRunner.run).calledWithMatch({ testHooks: wrapInClosure('empty filter') }); - expect(testFrameworkStub.filter).calledWith([]); - }); - - it('should report a runtime error when test run errored', async () => { - runResult.status = RunStatus.Error; - runResult.errorMessages = ['Cannot call "foo" of undefined (or something)']; - const sut = await createSut(); - const actualResult = await sut.runMutant(transpiledMutant); - expect(log.debug).calledWith( - 'A runtime error occurred: %s during execution of mutant: %s', - runResult.errorMessages[0], - transpiledMutant.mutant.toString() - ); - expect(actualResult.status).eq(MutantStatus.RuntimeError); - }); - - it('should report an early result when there is a transpile error', async () => { - transpiledMutant.transpileResult.error = 'Error! Cannot negate a string (or something)'; - const sut = await createSut(); - const mutantResult = await sut.runMutant(transpiledMutant); - expect(log.debug).calledWith( - `Transpile error occurred: "Error! Cannot negate a string (or something)" during transpiling of mutant ${transpiledMutant.mutant.toString()}` - ); - expect(mutantResult.status).eq(MutantStatus.TranspileError); - }); - - it('should report an early result when there are no files scoped', async () => { - // Arrange - while (transpiledMutant.mutant.selectedTests.pop()); - - // Act - const sut = await createSut(); - - // Assert - const mutantResult = await sut.runMutant(transpiledMutant); - expect(mutantResult.status).eq(MutantStatus.NoCoverage); - }); - - it('should report an early result when there are no file changes', async () => { - transpiledMutant.changedAnyTranspiledFiles = false; - const sut = await createSut(); - const mutantResult = await sut.runMutant(transpiledMutant); - expect(mutantResult.status).eq(MutantStatus.Survived); - }); - }); -}); diff --git a/packages/core/test/unit/SandboxPool.spec.ts b/packages/core/test/unit/SandboxPool.spec.ts deleted file mode 100644 index 4d5a77cb85..0000000000 --- a/packages/core/test/unit/SandboxPool.spec.ts +++ /dev/null @@ -1,253 +0,0 @@ -import * as os from 'os'; - -import { File, LogLevel } from '@stryker-mutator/api/core'; -import { commonTokens } from '@stryker-mutator/api/plugin'; -import { MutantResult } from '@stryker-mutator/api/report'; -import { TestFramework } from '@stryker-mutator/api/test_framework'; -import { RunStatus } from '@stryker-mutator/api/test_runner'; -import { factory, testInjector } from '@stryker-mutator/test-helpers'; -import { file, testFramework } from '@stryker-mutator/test-helpers/src/factory'; -import { expect } from 'chai'; -import { from } from 'rxjs'; -import { toArray } from 'rxjs/operators'; -import * as sinon from 'sinon'; - -import { coreTokens } from '../../src/di'; -import LoggingClientContext from '../../src/logging/LoggingClientContext'; -import { InitialTestRunResult } from '../../src/process/InitialTestExecutor'; -import Sandbox from '../../src/Sandbox'; -import { SandboxPool } from '../../src/SandboxPool'; -import TranspiledMutant from '../../src/TranspiledMutant'; -import { Task } from '../../src/utils/Task'; -import { TemporaryDirectory } from '../../src/utils/TemporaryDirectory'; -import { Mock, mock, transpiledMutant } from '../helpers/producers'; - -const OVERHEAD_TIME_MS = 42; -const LOGGING_CONTEXT: LoggingClientContext = Object.freeze({ - level: LogLevel.Fatal, - port: 4200, -}); - -describe(SandboxPool.name, () => { - let sut: SandboxPool; - let temporaryDirectoryMock: TemporaryDirectory; - let firstSandbox: Mock; - let secondSandbox: Mock; - let expectedTestFramework: TestFramework; - let initialTranspiledFiles: File[]; - let createStub: sinon.SinonStub; - let inputMutants: TranspiledMutant[]; - let genericSandboxForAllSubsequentCallsToNewSandbox: Mock; - - beforeEach(() => { - expectedTestFramework = testFramework(); - firstSandbox = mock(Sandbox); - secondSandbox = mock(Sandbox); - genericSandboxForAllSubsequentCallsToNewSandbox = mock(Sandbox); - firstSandbox.dispose.resolves(); - secondSandbox.dispose.resolves(); - genericSandboxForAllSubsequentCallsToNewSandbox.dispose.resolves(); - firstSandbox.runMutant.resolves(factory.runResult()); - genericSandboxForAllSubsequentCallsToNewSandbox.runMutant.resolves(factory.runResult()); - secondSandbox.runMutant.resolves(factory.runResult()); - inputMutants = [transpiledMutant()]; - createStub = sinon - .stub(Sandbox, 'create') - .resolves(genericSandboxForAllSubsequentCallsToNewSandbox) - .onCall(0) - .resolves(firstSandbox) - .onCall(1) - .resolves(secondSandbox); - - initialTranspiledFiles = [file()]; - }); - - function createSut(): SandboxPool { - temporaryDirectoryMock = testInjector.injector.injectClass(TemporaryDirectory); - - const initialRunResult: InitialTestRunResult = { - coverageMaps: {}, - overheadTimeMS: OVERHEAD_TIME_MS, - runResult: { tests: [], status: RunStatus.Complete }, - sourceMapper: { - transpiledFileNameFor: (n) => n, - transpiledLocationFor: (n) => Promise.resolve(n), - }, - }; - - return testInjector.injector - .provideValue(commonTokens.logger, factory.logger()) - .provideValue(coreTokens.testFramework, (expectedTestFramework as unknown) as TestFramework) - .provideValue(coreTokens.initialRunResult, initialRunResult) - .provideValue(coreTokens.loggingContext, LOGGING_CONTEXT) - .provideValue(coreTokens.transpiledFiles, initialTranspiledFiles) - .provideValue(coreTokens.temporaryDirectory, temporaryDirectoryMock) - .injectClass(SandboxPool); - } - - function actRunMutants() { - return sut.runMutants(from(inputMutants)).pipe(toArray()).toPromise(); - } - - describe('runMutants', () => { - it('should use maxConcurrentTestRunners when set', async () => { - testInjector.options.maxConcurrentTestRunners = 1; - sut = createSut(); - await actRunMutants(); - expect(Sandbox.create).to.have.callCount(1); - expect(Sandbox.create).calledWith(testInjector.options, 0, initialTranspiledFiles, expectedTestFramework, OVERHEAD_TIME_MS, LOGGING_CONTEXT); - }); - - it('should use cpuCount when maxConcurrentTestRunners is set too high', async () => { - sinon.stub(os, 'cpus').returns([1, 2, 3]); // stub 3 cpus - testInjector.options.maxConcurrentTestRunners = 100; - inputMutants.push(transpiledMutant('file 2.js')); - inputMutants.push(transpiledMutant('file 3.js')); - - sut = createSut(); - await actRunMutants(); - expect(Sandbox.create).to.have.callCount(3); - expect(Sandbox.create).calledWith(testInjector.options, 0, initialTranspiledFiles, expectedTestFramework, OVERHEAD_TIME_MS, LOGGING_CONTEXT); - }); - - it('should use the cpuCount when maxConcurrentTestRunners is <= 0', async () => { - sinon.stub(os, 'cpus').returns([1]); // stub 1 cpus - testInjector.options.maxConcurrentTestRunners = 0; - sut = createSut(); - await actRunMutants(); - expect(Sandbox.create).to.have.callCount(1); - expect(Sandbox.create).calledWith(testInjector.options, 0, initialTranspiledFiles, expectedTestFramework, OVERHEAD_TIME_MS, LOGGING_CONTEXT); - }); - - it('should create 2 sandboxes at a time', async () => { - // Arrange - sinon.stub(os, 'cpus').returns([1, 2, 3]); // stub 3 cpus - inputMutants.push(transpiledMutant('file 2.js')); - inputMutants.push(transpiledMutant('file 3.js')); // 3 mutants - const sut = createSut(); - const allResults: MutantResult[] = []; - const runTask = new Task(); - const createFirstSandboxTask = new Task(); - const createSecondSandboxTask = new Task(); - const createThirdSandboxTask = new Task(); - const secondResultTask = new Task(); - const firstRunMutantTask = new Task(); - const secondMutantTask = new Task(); - createStub.reset(); - createStub - .onFirstCall() - .returns(createFirstSandboxTask.promise) - .onSecondCall() - .returns(createSecondSandboxTask.promise) - .onThirdCall() - .returns(createThirdSandboxTask.promise); - firstSandbox.runMutant.reset(); - firstSandbox.runMutant.returns(firstRunMutantTask.promise); - secondSandbox.runMutant.reset(); - secondSandbox.runMutant.returns(secondMutantTask.promise); - sut.runMutants(from(inputMutants)).subscribe({ - complete: () => { - runTask.resolve(undefined); - }, - next: (result) => { - allResults.push(result); - if (allResults.length === 2) { - secondResultTask.resolve(undefined); - } - }, - }); - expect(allResults).lengthOf(0); - expect(createStub).callCount(2); - - // Act - createFirstSandboxTask.resolve((firstSandbox as unknown) as Sandbox); - createThirdSandboxTask.resolve((genericSandboxForAllSubsequentCallsToNewSandbox as unknown) as Sandbox); - await secondResultTask.promise; - expect(createStub).callCount(3); - firstRunMutantTask.resolve(factory.mutantResult()); - - // Assert - await runTask.promise; - expect(allResults).lengthOf(3); - expect(createStub).callCount(3); - expect(firstSandbox.runMutant).callCount(1); - expect(genericSandboxForAllSubsequentCallsToNewSandbox.runMutant).callCount(2); - }); - - it('should use the cpuCount - 1 when a transpiler is configured', async () => { - testInjector.options.transpilers = ['a transpiler']; - testInjector.options.maxConcurrentTestRunners = 2; - sinon.stub(os, 'cpus').returns([1, 2]); // stub 2 cpus - sut = createSut(); - await actRunMutants(); - expect(Sandbox.create).to.have.callCount(1); - }); - - it("should reject when a sandbox couldn't be created", async () => { - createStub.reset(); - const expectedError = new Error('foo error'); - createStub.rejects(expectedError); - sut = createSut(); - await expect(actRunMutants()).rejectedWith(expectedError); - }); - }); - - describe('dispose', () => { - it('should have disposed all sandboxes', async () => { - sut = createSut(); - await actRunMutants(); - await sut.dispose(); - expect(firstSandbox.dispose).called; - expect(secondSandbox.dispose).called; - }); - - it('should not do anything if no sandboxes were created', async () => { - sut = createSut(); - await sut.dispose(); - expect(firstSandbox.dispose).not.called; - expect(secondSandbox.dispose).not.called; - }); - - it('should not resolve when there are still sandboxes being created (issue #713)', async () => { - // Arrange - sut = createSut(); - sinon.stub(os, 'cpus').returns([1, 2]); // stub 2 cpus - const task = new Task(); - const task2 = new Task(); - createStub.reset(); - createStub.onCall(0).returns(task.promise).onCall(1).returns(task2.promise).onCall(2).resolves(genericSandboxForAllSubsequentCallsToNewSandbox); // promise is not yet resolved - inputMutants.push(transpiledMutant()); - - // Act - const runPromise = sut.runMutants(from(inputMutants)).toPromise(); - task.resolve((firstSandbox as unknown) as Sandbox); - await runPromise; - const disposePromise = sut.dispose(); - task2.resolve((secondSandbox as unknown) as Sandbox); - await disposePromise; - expect(secondSandbox.dispose).called; - }); - - it('should halt creating of new sandboxes', async () => { - // Arrange - sut = createSut(); - sinon.stub(os, 'cpus').returns([1, 2, 3]); // stub 3 cpus - const task = new Task(); - const task2 = new Task(); - createStub.reset(); - createStub.onCall(0).returns(task.promise).onCall(1).returns(task2.promise).onCall(2).resolves(genericSandboxForAllSubsequentCallsToNewSandbox); // promise is not yet resolved - inputMutants.push(transpiledMutant(), transpiledMutant()); // 3 mutants - - // Act - const runPromise = sut.runMutants(from(inputMutants)).pipe(toArray()).toPromise(); - const disposePromise = sut.dispose(); - task.resolve((firstSandbox as unknown) as Sandbox); - task2.resolve((secondSandbox as unknown) as Sandbox); - await disposePromise; - await runPromise; - - // Assert - expect(createStub).calledTwice; - }); - }); -}); diff --git a/packages/core/test/unit/SourceFile.spec.ts b/packages/core/test/unit/SourceFile.spec.ts deleted file mode 100644 index d71ce1716f..0000000000 --- a/packages/core/test/unit/SourceFile.spec.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { File } from '@stryker-mutator/api/core'; -import { expect } from 'chai'; - -import SourceFile from '../../src/SourceFile'; - -const content = ` -2 -3 -4234567890 -5 -6 -`.replace(/\r\n/g, '\n'); // Normalize newlines for reliable tests -const lines = content.split('\n'); - -describe('SourceFile', () => { - let sut: SourceFile; - - beforeEach(() => { - sut = new SourceFile(new File('', content)); - }); - - describe('getLocation', () => { - it('should provide correct location when given range falls a line, zero-based', () => { - const range: [number, number] = [7, 12]; - const expectedSubString = '34567'; - const loc = sut.getLocation(range); - expect(content.substring(range[0], range[1])).eq(expectedSubString); - expect(lines[loc.start.line].substring(loc.start.column, loc.end.column)).eq(expectedSubString); - expect(loc).deep.eq({ start: { line: 3, column: 2 }, end: { line: 3, column: 7 } }); - }); - - it('should provide correct location falls on line starts, zero-based', () => { - const range: [number, number] = [3, 5]; - const expectedSubString = '3\n'; - const loc = sut.getLocation(range); - expect(content.substring(range[0], range[1])).eq(expectedSubString); - expect(lines[loc.start.line].substr(loc.start.column) + '\n' + lines[loc.end.line].substr(0, loc.end.column)).eq(expectedSubString); - expect(loc).deep.eq({ start: { line: 2, column: 0 }, end: { line: 3, column: 0 } }); - }); - - it('should work for line 0', () => { - sut = new SourceFile(new File('', '1234567')); - expect(sut.getLocation([2, 4])).deep.eq({ start: { line: 0, column: 2 }, end: { line: 0, column: 4 } }); - }); - }); -}); diff --git a/packages/core/test/unit/Stryker.spec.ts b/packages/core/test/unit/Stryker.spec.ts index 1337917065..1b70e46b00 100644 --- a/packages/core/test/unit/Stryker.spec.ts +++ b/packages/core/test/unit/Stryker.spec.ts @@ -1,290 +1,202 @@ -import { File, LogLevel, StrykerOptions } from '@stryker-mutator/api/core'; -import { Logger } from '@stryker-mutator/api/logging'; -import { commonTokens } from '@stryker-mutator/api/plugin'; -import { MutantResult } from '@stryker-mutator/api/report'; -import { TestFramework } from '@stryker-mutator/api/test_framework'; -import { RunResult } from '@stryker-mutator/api/test_runner'; -import { Transpiler } from '@stryker-mutator/api/transpile'; import { factory } from '@stryker-mutator/test-helpers'; -import { mutantResult, runResult, testFramework } from '@stryker-mutator/test-helpers/src/factory'; import { expect } from 'chai'; import * as sinon from 'sinon'; import * as typedInject from 'typed-inject'; +import { PartialStrykerOptions, LogLevel } from '@stryker-mutator/api/core'; +import { MutantResult } from '@stryker-mutator/api/report'; +import { Logger } from '@stryker-mutator/api/logging'; +import { commonTokens } from '@stryker-mutator/api/plugin'; -import InputFileCollection from '../../src/input/InputFileCollection'; -import InputFileResolver from '../../src/input/InputFileResolver'; -import LogConfigurator from '../../src/logging/LogConfigurator'; -import LoggingClientContext from '../../src/logging/LoggingClientContext'; -import { MutantTestMatcher } from '../../src/mutants/MutantTestMatcher'; -import { MutatorFacade } from '../../src/mutants/MutatorFacade'; -import InitialTestExecutor from '../../src/process/InitialTestExecutor'; -import { MutationTestExecutor } from '../../src/process/MutationTestExecutor'; -import BroadcastReporter from '../../src/reporters/BroadcastReporter'; -import { MutationTestReportCalculator } from '../../src/reporters/MutationTestReportCalculator'; +import { LogConfigurator } from '../../src/logging'; import Stryker from '../../src/Stryker'; -import TestableMutant from '../../src/TestableMutant'; -import { TranspilerFacade } from '../../src/transpiler/TranspilerFacade'; -import { TemporaryDirectory } from '../../src/utils/TemporaryDirectory'; -import Timer from '../../src/utils/Timer'; -import { mock, Mock, testableMutant } from '../helpers/producers'; +import { PrepareExecutor, MutantInstrumenterExecutor, DryRunExecutor, MutationTestExecutor } from '../../src/process'; import { coreTokens } from '../../src/di'; -import * as buildMainInjectorModule from '../../src/di/buildMainInjector'; - -const LOGGING_CONTEXT: LoggingClientContext = Object.freeze({ - level: LogLevel.Debug, - port: 4200, -}); +import { ConfigError } from '../../src/errors'; +import { TemporaryDirectory } from '../../src/utils/TemporaryDirectory'; describe(Stryker.name, () => { let sut: Stryker; - let temporaryDirectoryMock: Mock; - let testFrameworkMock: TestFramework; - let inputFileResolverMock: Mock; - let initialTestExecutorMock: Mock; - let mutationTestExecutorMock: Mock; - let mutantTestMatcherMock: Mock; - let mutatorMock: Mock; - let strykerOptions: StrykerOptions; - let reporterMock: Mock; - let mutationTestReportCalculatorMock: Mock; - let configureMainProcessStub: sinon.SinonStub; - let configureLoggingServerStub: sinon.SinonStub; let shutdownLoggingStub: sinon.SinonStub; let injectorMock: sinon.SinonStubbedInstance; - let timerMock: sinon.SinonStubbedInstance; - let logMock: sinon.SinonStubbedInstance; - let transpilerMock: sinon.SinonStubbedInstance; + let cliOptions: PartialStrykerOptions; + let mutantResults: MutantResult[]; + let loggerMock: sinon.SinonStubbedInstance; + let temporaryDirectoryMock: sinon.SinonStubbedInstance; + let getLoggerStub: sinon.SinonStub; + + let prepareExecutorMock: sinon.SinonStubbedInstance; + let mutantInstrumenterExecutorMock: sinon.SinonStubbedInstance; + let dryRunExecutorMock: sinon.SinonStubbedInstance; + let mutationTestExecutorMock: sinon.SinonStubbedInstance; beforeEach(() => { - strykerOptions = factory.strykerOptions(); - logMock = factory.logger(); - reporterMock = mock(BroadcastReporter); injectorMock = factory.injector(); - mutantTestMatcherMock = mock(MutantTestMatcher); - mutatorMock = mock(MutatorFacade); - configureMainProcessStub = sinon.stub(LogConfigurator, 'configureMainProcess'); - configureLoggingServerStub = sinon.stub(LogConfigurator, 'configureLoggingServer'); - shutdownLoggingStub = sinon.stub(LogConfigurator, 'shutdown'); - configureLoggingServerStub.resolves(LOGGING_CONTEXT); - inputFileResolverMock = mock(InputFileResolver); - testFrameworkMock = testFramework(); - initialTestExecutorMock = mock(InitialTestExecutor); - mutationTestExecutorMock = mock(MutationTestExecutor); - transpilerMock = factory.transpiler(); - timerMock = sinon.createStubInstance(Timer); - - temporaryDirectoryMock = mock(TemporaryDirectory); - mutationTestReportCalculatorMock = mock(MutationTestReportCalculator); - sinon.stub(buildMainInjectorModule, 'buildMainInjector').returns(injectorMock); + loggerMock = factory.logger(); + getLoggerStub = sinon.stub(); + mutantResults = []; + temporaryDirectoryMock = sinon.createStubInstance(TemporaryDirectory); + prepareExecutorMock = sinon.createStubInstance(PrepareExecutor); + mutantInstrumenterExecutorMock = sinon.createStubInstance(MutantInstrumenterExecutor); + dryRunExecutorMock = sinon.createStubInstance(DryRunExecutor); + mutationTestExecutorMock = sinon.createStubInstance(MutationTestExecutor); injectorMock.injectClass - .withArgs(BroadcastReporter) - .returns(reporterMock) - .withArgs(InitialTestExecutor) - .returns(initialTestExecutorMock) - .withArgs(InputFileResolver) - .returns(inputFileResolverMock) - .withArgs(MutatorFacade) - .returns(mutatorMock) - .withArgs(MutantTestMatcher) - .returns(mutantTestMatcherMock) + .withArgs(PrepareExecutor) + .returns(prepareExecutorMock) + .withArgs(MutantInstrumenterExecutor) + .returns(mutantInstrumenterExecutorMock) + .withArgs(DryRunExecutor) + .returns(dryRunExecutorMock) .withArgs(MutationTestExecutor) - .returns(mutationTestExecutorMock) - .withArgs(MutationTestReportCalculator) - .returns(mutationTestReportCalculatorMock); + .returns(mutationTestExecutorMock); injectorMock.resolve - .withArgs(commonTokens.options) - .returns(strykerOptions) - .withArgs(coreTokens.timer) - .returns(timerMock) - .withArgs(coreTokens.reporter) - .returns(reporterMock) - .withArgs(coreTokens.testFramework) - .returns(testFrameworkMock) - .withArgs(coreTokens.temporaryDirectory) - .returns(temporaryDirectoryMock) .withArgs(commonTokens.getLogger) - .returns(() => logMock) - .withArgs(coreTokens.transpiler) - .returns(transpilerMock); - }); + .returns(getLoggerStub) + .withArgs(coreTokens.temporaryDirectory) + .returns(temporaryDirectoryMock); + getLoggerStub.returns(loggerMock); - describe('when constructed', () => { - beforeEach(() => { - strykerOptions.plugins = ['plugin1']; - sut = new Stryker({}); - }); + prepareExecutorMock.execute.resolves(injectorMock); + mutantInstrumenterExecutorMock.execute.resolves(injectorMock); + dryRunExecutorMock.execute.resolves(injectorMock); + mutationTestExecutorMock.execute.resolves(mutantResults); - it('should configure logging for master', () => { - expect(configureMainProcessStub).calledTwice; - }); + cliOptions = {}; + shutdownLoggingStub = sinon.stub(LogConfigurator, 'shutdown'); }); describe('runMutationTest()', () => { - let inputFiles: InputFileCollection; - let initialTranspiledFiles: File[]; - let initialRunResult: RunResult; - let transpiledFiles: File[]; - let mutants: TestableMutant[]; - let mutantResults: MutantResult[]; - beforeEach(() => { - mutants = [testableMutant('file1', 'fooMutator'), testableMutant('file2', 'barMutator'), testableMutant('file3', 'bazMutator')]; - mutantResults = [mutantResult()]; - mutantTestMatcherMock.matchWithMutants.returns(mutants); - mutatorMock.mutate.returns(mutants); - mutationTestExecutorMock.run.resolves(mutantResults); - inputFiles = new InputFileCollection([new File('input.ts', '')], ['input.ts']); - initialTranspiledFiles = [new File('input.js', '')]; - transpiledFiles = [new File('output.js', '')]; - inputFileResolverMock.resolve.resolves(inputFiles); - transpilerMock.transpile.resolves(initialTranspiledFiles); - initialRunResult = runResult(); - initialTestExecutorMock.run.resolves({ runResult: initialRunResult, transpiledFiles }); + sut = new Stryker(cliOptions, () => injectorMock); }); - describe('sad flow', () => { - beforeEach(() => { - sut = new Stryker({}); - }); - - it('should reject when logging server rejects', async () => { - const expectedError = Error('expected error'); - configureLoggingServerStub.rejects(expectedError); - await expect(sut.runMutationTest()).rejectedWith(expectedError); - }); - - it('should reject when input file globbing results in a rejection', async () => { - const expectedError = Error('expected error'); - inputFileResolverMock.resolve.rejects(expectedError); - await expect(sut.runMutationTest()).rejectedWith(expectedError); - }); - - it('should reject when initial test run rejects', async () => { - const expectedError = Error('expected error'); - initialTestExecutorMock.run.rejects(expectedError); - await expect(sut.runMutationTest()).rejectedWith(expectedError); - }); - - it('should reject when mutation tester rejects', async () => { - const expectedError = Error('expected error'); - mutationTestExecutorMock.run.rejects(expectedError); - await expect(sut.runMutationTest()).rejectedWith(expectedError); - }); + it('should execute the preparations', async () => { + await sut.runMutationTest(); + expect(prepareExecutorMock.execute).calledOnce; + }); + it('should execute the mutant instrumenter', async () => { + await sut.runMutationTest(); + expect(mutantInstrumenterExecutorMock.execute).calledOnce; + }); + it('should execute the dry run', async () => { + await sut.runMutationTest(); + expect(dryRunExecutorMock.execute).calledOnce; + }); - it('should quit early if no tests were executed in initial test run', async () => { - while (initialRunResult.tests.pop()); - const actualResults = await sut.runMutationTest(); - expect(mutationTestExecutorMock.run).not.called; - expect(actualResults).lengthOf(0); - }); + it('should execute actual mutation testing', async () => { + await sut.runMutationTest(); + expect(mutationTestExecutorMock.execute).calledOnce; + }); - it('should quit early if no mutants were generated', async () => { - while (mutants.pop()); // clear all mutants - await sut.runMutationTest(); - expect(mutationTestExecutorMock.run).not.called; - }); + it('should provide the cli options to the prepare executor', async () => { + cliOptions.logLevel = LogLevel.Trace; + const expectedCliOptions = { ...cliOptions }; + await sut.runMutationTest(); + expect(injectorMock.provideValue).calledWithExactly(coreTokens.cliOptions, expectedCliOptions); + expect(injectorMock.provideValue).calledBefore(injectorMock.injectClass); + }); - it('should log the remark to run again with logLevel trace if no tests were executed in initial test run', async () => { - while (initialRunResult.tests.pop()); - await sut.runMutationTest(); - expect(logMock.info).to.have.been.calledWith( - 'Trouble figuring out what went wrong? Try `npx stryker run --fileLogLevel trace --logLevel debug` to get some more info.' - ); - }); + it('should reject when prepare rejects', async () => { + const expectedError = new Error('expected error for testing'); + prepareExecutorMock.execute.rejects(expectedError); + await expect(sut.runMutationTest()).rejectedWith(expectedError); + }); - it('should log the remark to run again with logLevel trace if no mutants were generated', async () => { - while (mutants.pop()); // clear all mutants - await sut.runMutationTest(); - expect(logMock.info).to.have.been.calledWith( - 'Trouble figuring out what went wrong? Try `npx stryker run --fileLogLevel trace --logLevel debug` to get some more info.' - ); - }); + it('should not log a stack trace for a config error', async () => { + const expectedError = new ConfigError('foo should be bar'); + prepareExecutorMock.execute.rejects(expectedError); + await expect(sut.runMutationTest()).rejected; + expect(loggerMock.error).calledWithExactly('foo should be bar'); + }); - it('should dispose the injector', async () => { - await sut.runMutationTest(); - expect(injectorMock.dispose).called; - }); + it('should reject when execute the mutant instrumenter rejects', async () => { + const expectedError = new Error('expected error for testing'); + mutationTestExecutorMock.execute.rejects(expectedError); + await expect(sut.runMutationTest()).rejectedWith(expectedError); }); - describe('happy flow', () => { - it('should configure the logging server', async () => { - sut = new Stryker({}); - await sut.runMutationTest(); - expect(configureLoggingServerStub).calledWith(strykerOptions.logLevel, strykerOptions.fileLogLevel); - }); + it('should reject when execute the dry run rejects', async () => { + const expectedError = new Error('expected error for testing'); + dryRunExecutorMock.execute.rejects(expectedError); + await expect(sut.runMutationTest()).rejectedWith(expectedError); + }); - it('should report mutation test report ready', async () => { - sut = new Stryker({}); - await sut.runMutationTest(); - expect(mutationTestReportCalculatorMock.report).called; - }); + it('should reject when execute actual mutation testing rejects', async () => { + const expectedError = new Error('expected error for testing'); + mutationTestExecutorMock.execute.rejects(expectedError); + await expect(sut.runMutationTest()).rejectedWith(expectedError); + }); - it('should create the InputFileResolver', async () => { - sut = new Stryker({}); - await sut.runMutationTest(); - expect(inputFileResolverMock.resolve).called; - }); + it('should log the error when prepare rejects unexpectedly', async () => { + const expectedError = new Error('expected error for testing'); + prepareExecutorMock.execute.rejects(expectedError); + await expect(sut.runMutationTest()).rejected; + expect(loggerMock.error).calledWith(expectedError); + }); - it('should create the InitialTestExecutor', async () => { - sut = new Stryker({}); - await sut.runMutationTest(); - expect(injectorMock.injectClass).calledWith(InitialTestExecutor); - expect(initialTestExecutorMock.run).called; - }); + it('should disable `removeDuringDisposal` on the temp dir when dry run rejects', async () => { + dryRunExecutorMock.execute.rejects(new Error('expected error for testing')); + await expect(sut.runMutationTest()).rejected; + expect(getLoggerStub).calledWith('Stryker'); + expect(loggerMock.debug).calledWith('Not removing the temp dir because an error occurred'); + expect(temporaryDirectoryMock.removeDuringDisposal).false; + }); - it('should create the mutator', async () => { - sut = new Stryker({}); - await sut.runMutationTest(); - expect(mutatorMock.mutate).calledWith(inputFiles.filesToMutate); - }); + it('should log the error when dry run rejects unexpectedly', async () => { + const expectedError = new Error('expected error for testing'); + dryRunExecutorMock.execute.rejects(expectedError); + await expect(sut.runMutationTest()).rejected; + expect(getLoggerStub).calledWith('Stryker'); + expect(loggerMock.error).calledWith(expectedError); + }); - it('should transpile all files once before starting the mutation testing process', async () => { - sut = new Stryker({}); - await sut.runMutationTest(); - expect(transpilerMock.transpile).calledWith(inputFiles.files); - expect(injectorMock.provideValue).calledWith(coreTokens.transpiledFiles, initialTranspiledFiles); - }); + it('should log a help message when log level "trace" is not enabled', async () => { + const expectedError = new Error('expected error for testing'); + loggerMock.isTraceEnabled.returns(false); + dryRunExecutorMock.execute.rejects(expectedError); + await expect(sut.runMutationTest()).rejected; + expect(loggerMock.info).calledWith( + 'Trouble figuring out what went wrong? Try `npx stryker run --fileLogLevel trace --logLevel debug` to get some more info.' + ); + }); - it('should create the mutation test executor', async () => { - sut = new Stryker({}); - await sut.runMutationTest(); - expect(mutationTestExecutorMock.run).calledWith(mutants); - }); + it('should not log a help message when log level "trace" is enabled', async () => { + const expectedError = new Error('expected error for testing'); + loggerMock.isTraceEnabled.returns(true); + dryRunExecutorMock.execute.rejects(expectedError); + await expect(sut.runMutationTest()).rejected; + expect(loggerMock.info).not.called; + }); - it('should let the reporters wrapUp any async tasks', async () => { - sut = new Stryker({}); - await sut.runMutationTest(); - expect(reporterMock.wrapUp).to.have.been.called; - }); + it('should dispose the injector', async () => { + await sut.runMutationTest(); + expect(injectorMock.dispose).called; + }); - it('should dispose the injector', async () => { - sut = new Stryker({}); - await sut.runMutationTest(); - expect(injectorMock.dispose).called; - }); + it('should dispose also on a rejection injector', async () => { + prepareExecutorMock.execute.rejects(new Error('expected error')); + await expect(sut.runMutationTest()).rejected; + expect(injectorMock.dispose).called; + }); - it('should shutdown the log4js server', async () => { - sut = new Stryker({}); - await sut.runMutationTest(); - expect(shutdownLoggingStub).called; - expect(shutdownLoggingStub).calledAfter(injectorMock.dispose); - }); + it('should shut down the logging server', async () => { + await sut.runMutationTest(); + expect(shutdownLoggingStub).called; + }); - it('should create the transpiler with produceSourceMaps = true when coverage analysis is enabled', async () => { - strykerOptions.coverageAnalysis = 'all'; - sut = new Stryker({}); - await sut.runMutationTest(); - expect(injectorMock.provideValue).calledWith(commonTokens.produceSourceMaps, true); - expect(injectorMock.provideClass).calledWith(coreTokens.transpiler, TranspilerFacade); - }); + it('should shut down the logging server', async () => { + await sut.runMutationTest(); + expect(shutdownLoggingStub).called; + }); - it('should create the transpiler with produceSourceMaps = false when coverage analysis is "off"', async () => { - strykerOptions.coverageAnalysis = 'off'; - sut = new Stryker({}); - await sut.runMutationTest(); - expect(injectorMock.provideValue).calledWith(commonTokens.produceSourceMaps, false); - expect(injectorMock.provideClass).calledWith(coreTokens.transpiler, TranspilerFacade); - }); + it('should dispose the injector when actual mutation testing rejects', async () => { + mutationTestExecutorMock.execute.rejects(new Error('Expected error for testing')); + await expect(sut.runMutationTest()).rejected; + expect(injectorMock.dispose).called; + }); + it('should shut down the logging server when actual mutation testing rejects', async () => { + mutationTestExecutorMock.execute.rejects(new Error('Expected error for testing')); + await expect(sut.runMutationTest()).rejected; + expect(shutdownLoggingStub).called; }); }); }); diff --git a/packages/core/test/unit/StrykerCli.spec.ts b/packages/core/test/unit/StrykerCli.spec.ts index e6880d2a7a..b8340fb8a9 100644 --- a/packages/core/test/unit/StrykerCli.spec.ts +++ b/packages/core/test/unit/StrykerCli.spec.ts @@ -1,21 +1,17 @@ import { Command } from 'commander'; import * as sinon from 'sinon'; -import { Logger } from '@stryker-mutator/api/logging'; -import { logger } from '@stryker-mutator/test-helpers/src/factory'; import { expect } from 'chai'; import { DashboardOptions, StrykerOptions, ReportType, PartialStrykerOptions } from '@stryker-mutator/api/core'; -import LogConfigurator from '../../src/logging/LogConfigurator'; +import { LogConfigurator } from '../../src/logging'; import StrykerCli from '../../src/StrykerCli'; describe(StrykerCli.name, () => { let runMutationTestingStub: sinon.SinonStub; let configureLoggerStub: sinon.SinonStub; - let logMock: sinon.SinonStubbedInstance; beforeEach(() => { runMutationTestingStub = sinon.stub(); - logMock = logger(); configureLoggerStub = sinon.stub(LogConfigurator, 'configureMainProcess'); }); @@ -32,21 +28,25 @@ describe(StrykerCli.name, () => { describe('flat options', () => { const testCases: Array<[string[], PartialStrykerOptions]> = [ [['--files', 'foo.js,bar.js'], { files: ['foo.js', 'bar.js'] }], + [['--buildCommand', 'npm run build'], { buildCommand: 'npm run build' }], + [['-b', 'npm run build'], { buildCommand: 'npm run build' }], [['--mutate', 'foo.js,bar.js'], { mutate: ['foo.js', 'bar.js'] }], - [['--transpilers', 'foo,bar'], { transpilers: ['foo', 'bar'] }], [['--reporters', 'foo,bar'], { reporters: ['foo', 'bar'] }], [['--plugins', 'foo,bar'], { plugins: ['foo', 'bar'] }], - [['--mutator', 'foo'], { mutator: 'foo' }], + [['--appendPlugins', 'foo,bar'], { appendPlugins: ['foo', 'bar'] }], [['--timeoutMS', '42'], { timeoutMS: 42 }], [['--timeoutFactor', '42'], { timeoutFactor: 42 }], [['--maxConcurrentTestRunners', '42'], { maxConcurrentTestRunners: 42 }], [['--tempDirName', 'foo-tmp'], { tempDirName: 'foo-tmp' }], - [['--testFramework', 'foo-framework'], { testFramework: 'foo-framework' }], [['--testRunner', 'foo-running'], { testRunner: 'foo-running' }], [['--coverageAnalysis', 'all'], { coverageAnalysis: 'all' }], + [['--concurrency', '5'], { concurrency: 5 }], + [['--cleanTempDir', 'false'], { cleanTempDir: false }], + [['-c', '6'], { concurrency: 6 }], + [['--maxTestRunnerReuse', '3'], { maxTestRunnerReuse: 3 }], ]; testCases.forEach(([args, expected]) => { - it(`should expect option "${args.join(' ')}"`, () => { + it(`should parse option "${args.join(' ')}" as ${JSON.stringify(expected)}"`, () => { arrangeActAssertConfigOption(args, expected); }); }); @@ -91,7 +91,7 @@ describe(StrykerCli.name, () => { }); function actRun(args: string[]): void { - new StrykerCli(['node', 'stryker', 'run', ...args], new Command(), runMutationTestingStub, logMock).run(); + new StrykerCli(['node', 'stryker', 'run', ...args], new Command(), runMutationTestingStub).run(); } function arrangeActAssertConfigOption(args: string[], expectedOptions: PartialStrykerOptions): void { diff --git a/packages/core/test/unit/TestFrameworkOrchestrator.spec.ts b/packages/core/test/unit/TestFrameworkOrchestrator.spec.ts deleted file mode 100644 index 8482822dc3..0000000000 --- a/packages/core/test/unit/TestFrameworkOrchestrator.spec.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { PluginKind } from '@stryker-mutator/api/plugin'; -import { factory, testInjector } from '@stryker-mutator/test-helpers'; -import { expect } from 'chai'; -import * as sinon from 'sinon'; - -import { coreTokens } from '../../src/di'; -import { PluginCreator } from '../../src/di/PluginCreator'; -import TestFrameworkOrchestrator from '../../src/TestFrameworkOrchestrator'; - -describe('TestFrameworkOrchestrator', () => { - let sut: TestFrameworkOrchestrator; - let pluginCreatorMock: sinon.SinonStubbedInstance>; - - beforeEach(() => { - pluginCreatorMock = sinon.createStubInstance(PluginCreator); - }); - - const itShouldNotRetrieveATestFramework = () => { - it('should not retrieve a testFramework', () => { - const actualTestFramework = sut.determineTestFramework(); - expect(actualTestFramework).to.be.eq(null); - expect(testInjector.pluginResolver.resolve).not.called; - }); - }; - - const itShouldLogCoverageAnalysisOffOnDebug = () => { - it('should log on debug that coverageAnalysis was "off"', () => { - sut.determineTestFramework(); - expect(testInjector.logger.debug).calledWith( - 'The `coverageAnalysis` setting is "%s", not hooking into the test framework to achieve performance benefits.', - 'off' - ); - }); - }; - - const itShouldNotLogAWarningAboutTheMissingSetting = () => { - it('should not log a warning for the missing setting', () => { - sut.determineTestFramework(); - expect(testInjector.logger.warn).not.called; - }); - }; - - beforeEach(() => { - testInjector.options.coverageAnalysis = 'perTest'; - }); - - describe('when options contains a testFramework', () => { - beforeEach(() => { - testInjector.options.testFramework = 'fooFramework'; - }); - - describe('and coverageAnalysis is explicitly "off"', () => { - beforeEach(() => { - testInjector.options.coverageAnalysis = 'off'; - sut = createSut(); - }); - - itShouldNotRetrieveATestFramework(); - itShouldLogCoverageAnalysisOffOnDebug(); - }); - - it('should retrieve the test framework if coverageAnalysis is not "off"', () => { - const expectedTestFramework = factory.testFramework(); - pluginCreatorMock.create.returns(expectedTestFramework); - testInjector.options.coverageAnalysis = 'perTest'; - testInjector.options.testFramework = 'foo'; - sut = createSut(); - const actualTestFramework = sut.determineTestFramework(); - expect(actualTestFramework).eq(expectedTestFramework); - expect(pluginCreatorMock.create).calledWith('foo'); - }); - }); - - describe('when options does not contain a testFramework', () => { - describe('and coverageAnalysis is not "off"', () => { - beforeEach(() => { - sut = createSut(); - }); - - it('should log a warning for the missing setting', () => { - sut = createSut(); - sut.determineTestFramework(); - expect(testInjector.logger.warn).calledWith( - 'Missing config settings `testFramework`. Set `coverageAnalysis` option explicitly to "off" to ignore this warning.' - ); - }); - - itShouldNotRetrieveATestFramework(); - }); - describe('and coverageAnalysis is `off`', () => { - beforeEach(() => { - testInjector.options.coverageAnalysis = 'off'; - sut = createSut(); - }); - itShouldNotLogAWarningAboutTheMissingSetting(); - itShouldNotRetrieveATestFramework(); - itShouldLogCoverageAnalysisOffOnDebug(); - }); - }); - - function createSut() { - return testInjector.injector - .provideValue(coreTokens.pluginCreatorTestFramework, (pluginCreatorMock as unknown) as PluginCreator) - .injectClass(TestFrameworkOrchestrator); - } -}); diff --git a/packages/core/test/unit/TestableMutant.spec.ts b/packages/core/test/unit/TestableMutant.spec.ts deleted file mode 100644 index c522119fff..0000000000 --- a/packages/core/test/unit/TestableMutant.spec.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { File } from '@stryker-mutator/api/core'; -import { Mutant } from '@stryker-mutator/api/mutant'; -import { mutant, runResult, testResult } from '@stryker-mutator/test-helpers/src/factory'; -import { expect } from 'chai'; - -import SourceFile from '../../src/SourceFile'; -import TestableMutant, { TestSelectionResult } from '../../src/TestableMutant'; - -describe(TestableMutant.name, () => { - let innerMutant: Mutant; - - beforeEach(() => { - innerMutant = mutant(); - }); - - it('should pass properties from mutant and source code', () => { - const sut = new TestableMutant('3', innerMutant, new SourceFile(new File(innerMutant.fileName, 'alert("foobar")'))); - expect(sut.id).eq('3'); - expect(sut.fileName).eq(innerMutant.fileName); - expect(sut.range).eq(innerMutant.range); - expect(sut.mutatorName).eq(innerMutant.mutatorName); - expect(sut.replacement).eq(innerMutant.replacement); - expect(sut.originalCode).eq('alert("foobar")'); - }); - - it('should reflect timeSpentScopedTests, scopedTestIds and TestSelectionResult', () => { - const sut = new TestableMutant('3', innerMutant, new SourceFile(new File('foobar.js', 'alert("foobar")'))); - sut.selectAllTests( - runResult({ tests: [testResult({ name: 'spec1', timeSpentMs: 12 }), testResult({ name: 'spec2', timeSpentMs: 42 })] }), - TestSelectionResult.FailedButAlreadyReported - ); - expect(sut.timeSpentScopedTests).eq(54); - expect(sut.runAllTests).true; - expect(sut.testSelectionResult).eq(TestSelectionResult.FailedButAlreadyReported); - }); - - it('should scope tests when selecting individual tests', () => { - const sut = new TestableMutant('3', innerMutant, new SourceFile(new File('foobar.js', 'alert("foobar")'))); - sut.selectTest(testResult({ name: 'spec1', timeSpentMs: 12 }), 0); - sut.selectTest(testResult({ name: 'spec3', timeSpentMs: 32 }), 2); - expect(sut.timeSpentScopedTests).eq(44); - expect(sut.selectedTests).deep.eq([ - { id: 0, name: 'spec1' }, - { id: 2, name: 'spec3' }, - ]); - expect(sut.testSelectionResult).eq(TestSelectionResult.Success); - }); - - it('should calculate position using sourceFile', () => { - const sut = new TestableMutant('3', innerMutant, new SourceFile(new File('foobar.js', 'some content'))); - innerMutant.range = [1, 2]; - expect(sut.location).deep.eq({ start: { line: 0, column: 1 }, end: { line: 0, column: 2 } }); - }); - - it('should return original code with mutant replacement when `mutatedCode` is requested', () => { - const innerFile = new File('', 'some content'); - const sut = new TestableMutant('3', innerMutant, new SourceFile(innerFile)); - innerMutant.range = [4, 5]; - innerMutant.replacement = ' mutated! '; - expect(sut.mutatedCode).eq('some mutated! content'); - }); - - it('should be able to retrieve original lines and mutated lines', () => { - const innerFile = new File('', 'line 1\nline 2\nline 3\nline 4'); - const sut = new TestableMutant('3', innerMutant, new SourceFile(innerFile)); - innerMutant.range = [11, 12]; - innerMutant.replacement = ' mutated! '; - expect(sut.originalLines).eq('line 2'); - expect(sut.mutatedLines).eq('line mutated! 2'); - }); -}); diff --git a/packages/core/test/unit/child-proxy/ChildProcessProxy.spec.ts b/packages/core/test/unit/child-proxy/ChildProcessProxy.spec.ts index f3b57b29ce..5ceccbad77 100644 --- a/packages/core/test/unit/child-proxy/ChildProcessProxy.spec.ts +++ b/packages/core/test/unit/child-proxy/ChildProcessProxy.spec.ts @@ -18,7 +18,7 @@ import { WorkerMessage, WorkerMessageKind, } from '../../../src/child-proxy/messageProtocol'; -import LoggingClientContext from '../../../src/logging/LoggingClientContext'; +import { LoggingClientContext } from '../../../src/logging'; import { serialize } from '../../../src/utils/objectUtils'; import * as objectUtils from '../../../src/utils/objectUtils'; import currentLogMock from '../../helpers/logMock'; diff --git a/packages/core/test/unit/child-proxy/ChildProcessWorker.spec.ts b/packages/core/test/unit/child-proxy/ChildProcessWorker.spec.ts index 941f73f827..60e6e30a87 100644 --- a/packages/core/test/unit/child-proxy/ChildProcessWorker.spec.ts +++ b/packages/core/test/unit/child-proxy/ChildProcessWorker.spec.ts @@ -2,10 +2,9 @@ import * as path from 'path'; import { LogLevel } from '@stryker-mutator/api/core'; import { Logger } from '@stryker-mutator/api/logging'; -import { factory } from '@stryker-mutator/test-helpers'; +import { factory, testInjector } from '@stryker-mutator/test-helpers'; import { expect } from 'chai'; import * as sinon from 'sinon'; -import { rootInjector } from 'typed-inject'; import ChildProcessProxyWorker from '../../../src/child-proxy/ChildProcessProxyWorker'; import { @@ -18,8 +17,8 @@ import { WorkResult, } from '../../../src/child-proxy/messageProtocol'; import * as di from '../../../src/di'; -import LogConfigurator from '../../../src/logging/LogConfigurator'; -import LoggingClientContext from '../../../src/logging/LoggingClientContext'; +import { LogConfigurator } from '../../../src/logging'; +import { LoggingClientContext } from '../../../src/logging'; import { serialize } from '../../../src/utils/objectUtils'; import currentLogMock from '../../helpers/logMock'; import { Mock } from '../../helpers/producers'; @@ -53,7 +52,7 @@ describe(ChildProcessProxyWorker.name, () => { process.send = processSendStub; processChdirStub = sinon.stub(process, 'chdir'); configureChildProcessStub = sinon.stub(LogConfigurator, 'configureChildProcess'); - sinon.stub(di, 'buildChildProcessInjector').returns(rootInjector); + sinon.stub(di, 'buildChildProcessInjector').returns(testInjector.injector); }); afterEach(() => { diff --git a/packages/core/test/unit/concurrent/concurrency-token-provider.spec.ts b/packages/core/test/unit/concurrent/concurrency-token-provider.spec.ts new file mode 100644 index 0000000000..419eba4d00 --- /dev/null +++ b/packages/core/test/unit/concurrent/concurrency-token-provider.spec.ts @@ -0,0 +1,138 @@ +import os = require('os'); + +import { expect } from 'chai'; +import sinon = require('sinon'); +import { toArray } from 'rxjs/operators'; +import { testInjector } from '@stryker-mutator/test-helpers'; + +import { ConcurrencyTokenProvider } from '../../../src/concurrent'; + +describe(ConcurrencyTokenProvider.name, () => { + function createSut() { + return testInjector.injector.injectClass(ConcurrencyTokenProvider); + } + + it('should log about processes', async () => { + testInjector.options.concurrency = 9; + const sut = createSut(); + expect(testInjector.logger.info).calledWith('Creating %s test runner process(es).', 9); + sut.dispose(); + }); + + it('should log about processes created inc checkers', async () => { + testInjector.options.concurrency = 9; + testInjector.options.checkers = ['typescript']; + const sut = createSut(); + expect(testInjector.logger.info).calledWith('Creating %s checker process(es) and %s test runner process(es).', 5, 4); + sut.dispose(); + }); + + describe('testRunnerToken$', () => { + it('should use cpuCount - 1 if concurrency is not set', async () => { + sinon.stub(os, 'cpus').returns([0, 1, 2]); + const sut = createSut(); + const actualTokens = await actAllTestRunnerTokens(sut); + expect(actualTokens).deep.eq([0, 1]); + }); + + it('should allow half of the concurrency when there are checkers configured', async () => { + testInjector.options.concurrency = 8; + testInjector.options.checkers = ['typescript']; + const sut = createSut(); + const actualTokens = await actAllTestRunnerTokens(sut); + expect(actualTokens).deep.eq([0, 1, 2, 3]); + }); + + it('should allow floor half of the concurrency when there are checkers configured', async () => { + testInjector.options.concurrency = 9; + testInjector.options.checkers = ['typescript']; + const sut = createSut(); + const actualTokens = await actAllTestRunnerTokens(sut); + expect(actualTokens).deep.eq([0, 1, 2, 3]); + }); + + it('should emit 4 more tokens when the checkers are freed', async () => { + testInjector.options.concurrency = 8; + testInjector.options.checkers = ['typescript']; + const sut = createSut(); + const allTokens: number[] = []; + sut.testRunnerToken$.subscribe((token) => allTokens.push(token)); + expect(allTokens).lengthOf(4); + sut.freeCheckers(); + expect(allTokens).lengthOf(8); + sut.dispose(); + }); + + function actAllTestRunnerTokens(sut: ConcurrencyTokenProvider): Promise { + const tokens = sut.testRunnerToken$.pipe(toArray()).toPromise(); + sut.dispose(); + return tokens; + } + }); + + describe('checkerToken$', () => { + it('should emit one value when there are no checkers configured (no actual process will be created in that case)', async () => { + testInjector.options.checkers = []; + const sut = createSut(); + const tokens = await sut.checkerToken$.pipe(toArray()).toPromise(); + expect(tokens).deep.eq([0]); + sut.dispose(); + }); + + it('should emit 3 values if concurrency is 6', async () => { + testInjector.options.checkers = ['typescript']; + testInjector.options.concurrency = 6; + const sut = createSut(); + const tokens = await sut.checkerToken$.pipe(toArray()).toPromise(); + expect(tokens).deep.eq([0, 1, 2]); + sut.dispose(); + }); + + it('should emit 4 values if concurrency is 7', async () => { + testInjector.options.checkers = ['typescript']; + testInjector.options.concurrency = 7; + const sut = createSut(); + const tokens = await sut.checkerToken$.pipe(toArray()).toPromise(); + expect(tokens).deep.eq([0, 1, 2, 3]); + sut.dispose(); + }); + }); + + describe('dispose', () => { + it('should complete the subject(s)', () => { + // Arrange + testInjector.options.checkers = ['typescript']; + testInjector.options.concurrency = 6; + const sut = createSut(); + const allCheckerTokens: number[] = []; + const allTestRunnerTokens: number[] = []; + let checkersCompleted = false; + let testRunnersCompleted = false; + sut.checkerToken$.subscribe({ + next(n) { + allCheckerTokens.push(n); + }, + complete() { + checkersCompleted = true; + }, + }); + sut.testRunnerToken$.subscribe({ + next(n) { + allTestRunnerTokens.push(n); + }, + complete() { + testRunnersCompleted = true; + }, + }); + + // Act & assert + expect(allTestRunnerTokens).deep.eq([0, 1, 2]); + expect(allCheckerTokens).deep.eq([0, 1, 2]); + expect(checkersCompleted).true; + expect(testRunnersCompleted).false; + sut.dispose(); + expect(checkersCompleted).true; + expect(testRunnersCompleted).true; + }); + }); +}); diff --git a/packages/core/test/unit/concurrent/pool.spec.ts b/packages/core/test/unit/concurrent/pool.spec.ts new file mode 100644 index 0000000000..3bd064c668 --- /dev/null +++ b/packages/core/test/unit/concurrent/pool.spec.ts @@ -0,0 +1,288 @@ +import os = require('os'); + +import { expect } from 'chai'; +import { toArray } from 'rxjs/operators'; +import sinon = require('sinon'); +import { factory, tick } from '@stryker-mutator/test-helpers'; +import { Task, ExpirableTask } from '@stryker-mutator/util'; +import { ReplaySubject } from 'rxjs'; + +import { Pool, Worker } from '../../../src/concurrent'; + +describe(Pool.name, () => { + let worker1: sinon.SinonStubbedInstance>; + let worker2: sinon.SinonStubbedInstance>; + let genericWorkerForAllSubsequentCreates: sinon.SinonStubbedInstance>; + let createWorkerStub: sinon.SinonStub; + let concurrencyToken$: ReplaySubject; + let sut: Pool>; + + beforeEach(() => { + concurrencyToken$ = new ReplaySubject(); + worker1 = factory.testRunner(); + worker2 = factory.testRunner(); + genericWorkerForAllSubsequentCreates = factory.testRunner(); + createWorkerStub = sinon.stub(); + }); + + afterEach(() => { + concurrencyToken$.complete(); + sut.dispose(); + }); + + function arrangeWorkers() { + createWorkerStub.returns(genericWorkerForAllSubsequentCreates).onCall(0).returns(worker1).onCall(1).returns(worker2); + } + + function createSut() { + return new Pool>(createWorkerStub, concurrencyToken$); + } + + function setConcurrency(n: number) { + Array.from({ length: n }).forEach((_, i) => concurrencyToken$.next(i)); + } + + describe('worker$', () => { + it("should create 2 workers at a time (for performance reasons, we don't to overwhelm the device)", async () => { + // Arrange + arrangeWorkers(); + setConcurrency(3); + const initWorker1Task = new Task(); + const initWorker2Task = new Task(); + const initWorker3Task = new Task(); + worker1.init.returns(initWorker1Task.promise); + worker2.init.returns(initWorker2Task.promise); + genericWorkerForAllSubsequentCreates.init.returns(initWorker3Task.promise); + sut = createSut(); + const actualWorkers: Array> = []; + + // Act + sut.worker$.subscribe((worker) => actualWorkers.push(worker)); + + // Assert + expect(actualWorkers).lengthOf(0); + expect(createWorkerStub).callCount(2); + initWorker1Task.resolve(); + initWorker2Task.resolve(); + initWorker3Task.resolve(); + await tick(2); + await sut.dispose(); + expect(actualWorkers).lengthOf(3); + }); + + it('should eventually create all workers', async () => { + arrangeWorkers(); + setConcurrency(8); + const result = await actSubscribeAllWorkers(createSut()); + expect(result).lengthOf(8); + expect(result).deep.eq([ + worker1, + worker2, + genericWorkerForAllSubsequentCreates, + genericWorkerForAllSubsequentCreates, + genericWorkerForAllSubsequentCreates, + genericWorkerForAllSubsequentCreates, + genericWorkerForAllSubsequentCreates, + genericWorkerForAllSubsequentCreates, + ]); + }); + + it("should reject when a worker couldn't be created", async () => { + setConcurrency(1); + const expectedError = new Error('foo error'); + createWorkerStub.throws(expectedError); + sut = createSut(); + await expect(actSubscribeAllWorkers(sut)).rejectedWith(expectedError); + }); + + it('should share workers across subscribers (for sharing between dry runner and mutation test runner)', async () => { + // Arrange + setConcurrency(2); + arrangeWorkers(); + sut = createSut(); + + // Act + const firstResultPromise = sut.worker$.pipe(toArray()).toPromise(); + const secondResult = await actSubscribeAllWorkers(sut); + + // Assert + expect(await firstResultPromise).lengthOf(2); + expect(secondResult).lengthOf(2); + }); + }); + + describe('init', () => { + it('should await the init() of all workers', async () => { + // Arrange + arrangeWorkers(); + setConcurrency(2); + const initWorker2Task = new Task(); + worker2.init.returns(initWorker2Task.promise); + worker1.init.resolves(); + sut = createSut(); + + // Act + const timeoutResult = await ExpirableTask.timeout(sut.init(), 20); + initWorker2Task.resolve(); + concurrencyToken$.complete(); + await sut.init(); + await sut.dispose(); + + // Assert + expect(timeoutResult).eq(ExpirableTask.TimeoutExpired); + expect(worker1.init).called; + expect(worker2.init).called; + }); + + it('should cache the workers for later use', async () => { + // Arrange + arrangeWorkers(); + setConcurrency(1); + sut = createSut(); + concurrencyToken$.complete(); + + // Act + await sut.init(); + await sut.init(); + const allWorkers = sut.worker$.pipe(toArray()).toPromise(); + await tick(); + sut.dispose(); + + // Assert + expect(createWorkerStub).calledOnce; + expect(await allWorkers).deep.eq([worker1]); + }); + + it('should await for all concurrency tokens to be delivered', async () => { + // Arrange + arrangeWorkers(); + setConcurrency(2); + const actualWorkers: Array> = []; + sut = createSut(); + sut.worker$.subscribe((worker) => actualWorkers.push(worker)); + + // Act + const timeoutResult = await ExpirableTask.timeout(sut.init(), 20); + concurrencyToken$.complete(); + await sut.init(); + await sut.dispose(); + + // Assert + expect(timeoutResult).eq(ExpirableTask.TimeoutExpired); + expect(actualWorkers).lengthOf(2); + }); + + it('should reject when a worker rejects', async () => { + // Arrange + arrangeWorkers(); + setConcurrency(2); + const expectedError = new Error('expected error'); + worker2.init.rejects(expectedError); + sut = createSut(); + const actualWorkers = sut.worker$.toPromise(); + + // Act & Assert + await expect(sut.init()).rejectedWith(expectedError); + await expect(actualWorkers).rejectedWith(expectedError); + concurrencyToken$.complete(); + await sut.dispose(); + }); + }); + + describe('recycle', () => { + it('should re-emit the presented worker in the stream', async () => { + // Arrange + arrangeWorkers(); + setConcurrency(2); + const actualWorkers: Array> = []; + sut = createSut(); + sut.worker$.subscribe((worker) => actualWorkers.push(worker)); + await tick(2); + + // Act + sut.recycle(worker1); + await sut.dispose(); + + // Assert + expect(actualWorkers).lengthOf(3); + expect(actualWorkers).deep.eq([worker1, worker2, worker1]); + }); + }); + + describe('dispose', () => { + it('should have disposed all testRunners', async () => { + setConcurrency(8); + arrangeWorkers(); + sut = createSut(); + await actSubscribeAllWorkers(sut); + await sut.dispose(); + expect(worker1.dispose).called; + expect(worker2.dispose).called; + }); + + it('should not do anything if no workers were created', async () => { + sut = createSut(); + await sut.dispose(); + expect(worker1.dispose).not.called; + expect(worker2.dispose).not.called; + }); + + it('should not resolve when there are still workers being initialized (issue #713)', async () => { + // Arrange + arrangeWorkers(); + setConcurrency(2); + const task = new Task(); + const task2 = new Task(); + worker1.init.returns(task.promise); + worker2.init.returns(task2.promise); + sut = createSut(); + + // Act + const resultPromise = sut.worker$.pipe(toArray()).toPromise(); + task.resolve(); + await sut.dispose(); + task2.resolve(); + concurrencyToken$.complete(); + await resultPromise; + expect(worker1.dispose).called; + expect(worker2.dispose).called; + }); + + it('should halt creating of new sandboxes', async () => { + // Arrange + arrangeWorkers(); + setConcurrency(3); + const task = new Task(); + const task2 = new Task(); + worker1.init.returns(task.promise); + worker2.init.returns(task2.promise); + sut = createSut(); + + // Act + const actualTestRunnersPromise = sut.worker$.pipe(toArray()).toPromise(); + const disposePromise = sut.dispose(); + task.resolve(); + task2.resolve(); + await disposePromise; + concurrencyToken$.complete(); + await actualTestRunnersPromise; + + // Assert + expect(createWorkerStub).calledTwice; + }); + }); + + async function actSubscribeAllWorkers(sut: Pool>) { + // Eagerly get all test runners + const createAllPromise = sut.worker$.pipe(toArray()).toPromise(); + + // But don't await yet, until after dispose. + // Allow processes to be created + await tick(os.cpus().length); + + // Dispose completes the internal recycle bin subject, which in turn will complete. + await sut.dispose(); + concurrencyToken$.complete(); + return createAllPromise; + } +}); diff --git a/packages/core/test/unit/config/OptionsEditorApplier.spec.ts b/packages/core/test/unit/config/OptionsEditorApplier.spec.ts deleted file mode 100644 index 8ba8affe8f..0000000000 --- a/packages/core/test/unit/config/OptionsEditorApplier.spec.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { PluginKind } from '@stryker-mutator/api/plugin'; -import { factory, testInjector } from '@stryker-mutator/test-helpers'; -import { expect } from 'chai'; -import * as sinon from 'sinon'; - -import { OptionsEditorApplier } from '../../../src/config'; -import { coreTokens } from '../../../src/di'; -import { PluginCreator } from '../../../src/di/PluginCreator'; - -describe(OptionsEditorApplier.name, () => { - let sut: OptionsEditorApplier; - let configEditorPluginCreatorMock: sinon.SinonStubbedInstance>; - let optionsEditorPluginCreatorMock: sinon.SinonStubbedInstance>; - - beforeEach(() => { - configEditorPluginCreatorMock = sinon.createStubInstance(PluginCreator); - optionsEditorPluginCreatorMock = sinon.createStubInstance(PluginCreator); - sut = testInjector.injector - .provideValue(coreTokens.pluginCreatorConfigEditor, (configEditorPluginCreatorMock as unknown) as PluginCreator) - .provideValue(coreTokens.pluginCreatorOptionsEditor, (optionsEditorPluginCreatorMock as unknown) as PluginCreator) - .injectClass(OptionsEditorApplier); - }); - - it('should apply all config editors', () => { - // Arrange - const options = factory.strykerOptions(); - const fooConfigEditor = factory.configEditor(); - const barConfigEditor = factory.configEditor(); - const bazOptionsEditor = factory.optionsEditor(); - const quxOptionsEditor = factory.optionsEditor(); - const configEditorPlugins = [{ name: 'fooConfigEditorPlugin' }, { name: 'barConfigEditorPlugin' }]; - const optionEditorPlugins = [{ name: 'bazOptionsEditorPlugin' }, { name: 'quxOptionsEditorPlugin' }]; - testInjector.pluginResolver.resolveAll - .withArgs(PluginKind.OptionsEditor) - .returns(optionEditorPlugins) - .withArgs(PluginKind.ConfigEditor) - .returns(configEditorPlugins); - configEditorPluginCreatorMock.create - .withArgs(configEditorPlugins[0].name) - .returns(fooConfigEditor) - .withArgs(configEditorPlugins[1].name) - .returns(barConfigEditor); - optionsEditorPluginCreatorMock.create - .withArgs(optionEditorPlugins[0].name) - .returns(bazOptionsEditor) - .withArgs(optionEditorPlugins[1].name) - .returns(quxOptionsEditor); - - // Act - sut.edit(options); - - // Assert - expect(fooConfigEditor.edit).calledWith(options); - expect(barConfigEditor.edit).calledWith(options); - expect(bazOptionsEditor.edit).calledWith(options); - expect(quxOptionsEditor.edit).calledWith(options); - }); -}); diff --git a/packages/core/test/unit/config/OptionsValidator.spec.ts b/packages/core/test/unit/config/OptionsValidator.spec.ts index 9fcdb72c94..ac23578633 100644 --- a/packages/core/test/unit/config/OptionsValidator.spec.ts +++ b/packages/core/test/unit/config/OptionsValidator.spec.ts @@ -1,8 +1,9 @@ +import os = require('os'); + import sinon = require('sinon'); import { strykerCoreSchema, StrykerOptions } from '@stryker-mutator/api/core'; import { testInjector, factory } from '@stryker-mutator/test-helpers'; import { expect } from 'chai'; -import { normalizeWhitespaces } from '@stryker-mutator/util'; import { OptionsValidator, validateOptions, markUnknownOptions } from '../../../src/config/OptionsValidator'; import { coreTokens } from '../../../src/di'; @@ -43,19 +44,6 @@ describe(OptionsValidator.name, () => { }); }); - it('should be invalid with coverageAnalysis when 2 transpilers are specified (for now)', () => { - testInjector.options.transpilers.push('a transpiler'); - testInjector.options.transpilers.push('a second transpiler'); - testInjector.options.coverageAnalysis = 'all'; - actValidationErrors( - normalizeWhitespaces(` - Config option "coverageAnalysis" is invalid. Coverage analysis "all" is not supported for multiple transpilers - (configured transpilers: "a transpiler", "a second transpiler"). - Change it to "off". Please report this to the Stryker team if you whish this feature to be implemented. - `) - ); - }); - it('should be invalid with invalid logLevel', () => { testInjector.options.logLevel = 'thisTestPasses' as any; actValidationErrors( @@ -85,64 +73,50 @@ describe(OptionsValidator.name, () => { }); }); + describe('appendPlugins', () => { + it('should be invalid with non-array plugins', () => { + breakConfig('appendPlugins', '@stryker-mutator/typescript'); + actValidationErrors('Config option "appendPlugins" has the wrong type. It should be a array, but was a string.'); + }); + + it('should be invalid with non-string array elements', () => { + breakConfig('appendPlugins', ['stryker-jest', 0]); + actValidationErrors('Config option "appendPlugins[1]" has the wrong type. It should be a string, but was a number.'); + }); + }); + describe('mutator', () => { it('should be invalid with non-string mutator', () => { - breakConfig('mutator', 0); - actValidationErrors('Config option "mutator" has the wrong type. It should be a string or object, but was a number.'); + (testInjector.options.mutator as any) = 1; + actValidationErrors('Config option "mutator" has the wrong type. It should be a object, but was a number.'); + }); + + it('should report a deprecation warning for "mutator.name"', () => { + (testInjector.options.mutator as any) = { + name: 'javascript', + }; + sut.validate(testInjector.options); + expect(testInjector.logger.warn).calledWith( + 'DEPRECATED. Use of "mutator.name" is no longer needed. You can remove "mutator.name" from your configuration. Stryker now supports mutating of JavaScript and friend files out of the box.' + ); }); - describe('as an object', () => { - it('should be valid with all options', () => { - testInjector.options.mutator = { - excludedMutations: ['BooleanSubstitution'], - name: 'javascript', - plugins: ['objectRestSpread', ['decorators', { decoratorsBeforeExport: true }]], - }; - actAssertValid(); - }); - - it('should be valid with minimal options', () => { - breakConfig('mutator', { - name: 'javascript', - }); - actAssertValid(); - }); - - it('should be invalid without name', () => { - breakConfig('mutator', {}); - actValidationErrors('Config option "mutator" should have required property "name"'); - }); - - it('should be invalid with non-string mutator name', () => { - breakConfig('mutator', { - name: 0, - }); - actValidationErrors('Config option "mutator.name" has the wrong type. It should be a string, but was a number.'); - }); - - it('should be invalid with non array plugins', () => { - breakConfig('mutator', { - name: 'javascript', - plugins: 'optionalChaining', - }); - actValidationErrors('Config option "mutator.plugins" has the wrong type. It should be a array or null, but was a string.'); - }); - - it('should be invalid with non-array excluded mutations', () => { - breakConfig('mutator', { - excludedMutations: 'BooleanSubstitution', - name: 'javascript', - }); - actValidationErrors('Config option "mutator.excludedMutations" has the wrong type. It should be a array, but was a string.'); - }); - - it('should be invalid with non-string excluded mutation array elements', () => { - breakConfig('mutator', { - excludedMutations: ['BooleanSubstitution', 0], - name: 'javascript', - }); - actValidationErrors('Config option "mutator.excludedMutations[1]" has the wrong type. It should be a string, but was a number.'); - }); + it('should report a deprecation warning for mutator as a string', () => { + (testInjector.options.mutator as any) = 'javascript'; + sut.validate(testInjector.options); + expect(testInjector.logger.warn).calledWith( + 'DEPRECATED. Use of "mutator" as string is no longer needed. You can remove it from your configuration. Stryker now supports mutating of JavaScript and friend files out of the box.' + ); + }); + }); + + describe('testFramework', () => { + it('should report a deprecation warning', () => { + (testInjector.options as any).testFramework = ''; + sut.validate(testInjector.options); + expect(testInjector.logger.warn).calledWith( + 'DEPRECATED. Use of "testFramework" is no longer needed. You can remove it from your configuration. Your test runner plugin now handles its own test framework integration.' + ); }); }); @@ -181,15 +155,40 @@ describe(OptionsValidator.name, () => { }); }); - describe('transpilers', () => { - it('should be invalid with non-array transpilers', () => { - breakConfig('transpilers', '@stryker-mutator/typescript'); - actValidationErrors('Config option "transpilers" has the wrong type. It should be a array, but was a string.'); + describe('maxConcurrentTestRunners', () => { + it('should report a deprecation warning', () => { + testInjector.options.maxConcurrentTestRunners = 8; + sut.validate(testInjector.options); + expect(testInjector.logger.warn).calledWith('DEPRECATED. Use of "maxConcurrentTestRunners" is deprecated. Please use "concurrency" instead.'); }); - it('should be invalid with non-string array elements', () => { - breakConfig('transpilers', ['stryker-jest', 0]); - actValidationErrors('Config option "transpilers[1]" has the wrong type. It should be a string, but was a number.'); + it('should not configure "concurrency" if "maxConcurrentTestRunners" is >= cpus-1', () => { + testInjector.options.maxConcurrentTestRunners = 2; + sinon.stub(os, 'cpus').returns([0, 1, 2]); + sut.validate(testInjector.options); + expect(testInjector.options.concurrency).undefined; + }); + + it('should configure "concurrency" if "maxConcurrentTestRunners" is set with a lower value', () => { + testInjector.options.maxConcurrentTestRunners = 1; + sinon.stub(os, 'cpus').returns([0, 1, 2]); + sut.validate(testInjector.options); + expect(testInjector.options.concurrency).eq(1); + }); + }); + + it('should be invalid with non-numeric maxTestRunnerReuse', () => { + breakConfig('maxTestRunnerReuse', 'break'); + actValidationErrors('Config option "maxTestRunnerReuse" has the wrong type. It should be a number, but was a string.'); + }); + + describe('transpilers', () => { + it('should report a deprecation warning', () => { + (testInjector.options.transpilers as any) = ['stryker-jest']; + sut.validate(testInjector.options); + expect(testInjector.logger.warn).calledWith( + 'DEPRECATED. Support for "transpilers" is removed. You can now configure your own "buildCommand". For example, npm run build.' + ); }); }); @@ -233,7 +232,7 @@ describe(validateOptions.name, () => { it('should validate the options using given optionsValidator', () => { const options = { foo: 'bar' }; const output = validateOptions(options, (optionsValidatorMock as unknown) as OptionsValidator); - expect(options).eq(output); + expect(options).deep.eq(output); expect(optionsValidatorMock.validate).calledWith(options); }); }); diff --git a/packages/core/test/unit/config/buildSchemaWithPluginContributions.spec.ts b/packages/core/test/unit/config/buildSchemaWithPluginContributions.spec.ts index 37b1520a0a..5a2c7d3d60 100644 --- a/packages/core/test/unit/config/buildSchemaWithPluginContributions.spec.ts +++ b/packages/core/test/unit/config/buildSchemaWithPluginContributions.spec.ts @@ -8,7 +8,7 @@ import { buildSchemaWithPluginContributions } from '../../../src/config'; describe(buildSchemaWithPluginContributions.name, () => { let pluginResolverStub: sinon.SinonStubbedInstance; - let pluginContributions: object[]; + let pluginContributions: Array>; beforeEach(() => { pluginResolverStub = factory.pluginResolver(); diff --git a/packages/core/test/unit/di/buildMainInjector.spec.ts b/packages/core/test/unit/di/buildMainInjector.spec.ts index c81435883c..9aaf81db82 100644 --- a/packages/core/test/unit/di/buildMainInjector.spec.ts +++ b/packages/core/test/unit/di/buildMainInjector.spec.ts @@ -1,41 +1,34 @@ -import { commonTokens } from '@stryker-mutator/api/plugin'; +import { commonTokens, PluginKind } from '@stryker-mutator/api/plugin'; import { Reporter } from '@stryker-mutator/api/report'; -import { TestFramework } from '@stryker-mutator/api/test_framework'; import { factory } from '@stryker-mutator/test-helpers'; import { expect } from 'chai'; import * as sinon from 'sinon'; -import { MutatorDescriptor, StrykerOptions } from '@stryker-mutator/api/core'; +import { StrykerOptions, PartialStrykerOptions } from '@stryker-mutator/api/core'; +import { createInjector } from 'typed-inject'; -import * as optionsEditorApplierModule from '../../../src/config/OptionsEditorApplier'; import * as optionsValidatorModule from '../../../src/config/OptionsValidator'; import * as pluginLoaderModule from '../../../src/di/PluginLoader'; import ConfigReader, * as configReaderModule from '../../../src/config/ConfigReader'; -import { PluginCreator, PluginLoader, coreTokens } from '../../../src/di'; -import { buildMainInjector } from '../../../src/di/buildMainInjector'; +import { PluginCreator, PluginLoader, coreTokens, provideLogger } from '../../../src/di'; +import { buildMainInjector, CliOptionsProvider } from '../../../src/di/buildMainInjector'; import * as broadcastReporterModule from '../../../src/reporters/BroadcastReporter'; -import TestFrameworkOrchestrator, * as testFrameworkOrchestratorModule from '../../../src/TestFrameworkOrchestrator'; import currentLogMock from '../../helpers/logMock'; describe(buildMainInjector.name, () => { - let testFrameworkOrchestratorMock: sinon.SinonStubbedInstance; let pluginLoaderMock: sinon.SinonStubbedInstance; - let testFrameworkMock: TestFramework; let configReaderMock: sinon.SinonStubbedInstance; - let pluginCreatorMock: sinon.SinonStubbedInstance>; - let optionsEditorApplierMock: sinon.SinonStubbedInstance; + let pluginCreatorMock: sinon.SinonStubbedInstance>; let broadcastReporterMock: sinon.SinonStubbedInstance; let optionsValidatorStub: sinon.SinonStubbedInstance; let expectedConfig: StrykerOptions; - let validationSchemaContributions: object[]; + let validationSchemaContributions: Array>; + let injector: CliOptionsProvider; + let cliOptions: PartialStrykerOptions; beforeEach(() => { configReaderMock = sinon.createStubInstance(ConfigReader); pluginCreatorMock = sinon.createStubInstance(PluginCreator); pluginCreatorMock = sinon.createStubInstance(PluginCreator); - optionsEditorApplierMock = sinon.createStubInstance(optionsEditorApplierModule.OptionsEditorApplier); - testFrameworkMock = factory.testFramework(); - testFrameworkOrchestratorMock = sinon.createStubInstance(TestFrameworkOrchestrator); - testFrameworkOrchestratorMock.determineTestFramework.returns(testFrameworkMock); pluginLoaderMock = sinon.createStubInstance(PluginLoader); optionsValidatorStub = sinon.createStubInstance(optionsValidatorModule.OptionsValidator); validationSchemaContributions = []; @@ -43,13 +36,13 @@ describe(buildMainInjector.name, () => { expectedConfig = factory.strykerOptions(); broadcastReporterMock = factory.reporter('broadcast'); configReaderMock.readConfig.returns(expectedConfig); + cliOptions = {}; + injector = provideLogger(createInjector()).provideValue(coreTokens.cliOptions, cliOptions); stubInjectable(PluginCreator, 'createFactory').returns(() => pluginCreatorMock); - stubInjectable(optionsEditorApplierModule, 'OptionsEditorApplier').returns(optionsEditorApplierMock); stubInjectable(optionsValidatorModule, 'OptionsValidator').returns(optionsValidatorStub); stubInjectable(pluginLoaderModule, 'PluginLoader').returns(pluginLoaderMock); stubInjectable(configReaderModule, 'default').returns(configReaderMock); stubInjectable(broadcastReporterModule, 'default').returns(broadcastReporterMock); - stubInjectable(testFrameworkOrchestratorModule, 'default').returns(testFrameworkOrchestratorMock); }); function stubInjectable(obj: T, method: keyof T) { @@ -61,75 +54,54 @@ describe(buildMainInjector.name, () => { describe('resolve options', () => { it('should supply readonly stryker options', () => { - const actualOptions = buildMainInjector({}).resolve(commonTokens.options); + const actualOptions = buildMainInjector(injector).resolve(commonTokens.options); expect(actualOptions).frozen; }); it('should load default plugins', () => { - buildMainInjector({}).resolve(commonTokens.options); + buildMainInjector(injector).resolve(commonTokens.options); expect(PluginLoader).calledWithNew; expect(PluginLoader).calledWith(currentLogMock(), ['@stryker-mutator/*', require.resolve('../../../src/reporters')]); }); it('should load plugins', () => { - buildMainInjector({}).resolve(commonTokens.options); + buildMainInjector(injector).resolve(commonTokens.options); expect(pluginLoaderMock.load).called; }); - it('should apply config editors', () => { - buildMainInjector({}).resolve(commonTokens.options); - expect(optionsEditorApplierMock.edit).called; - }); - it('should cache the config', () => { - const injector = buildMainInjector({}); - injector.resolve(commonTokens.options); - injector.resolve(commonTokens.options); + const actualInjector = buildMainInjector(injector); + actualInjector.resolve(commonTokens.options); + actualInjector.resolve(commonTokens.options); expect(configReaderMock.readConfig).calledOnce; }); it('should inject the `cliOptions` in the config reader', () => { - const expectedCliOptions = { foo: 'bar' }; - buildMainInjector(expectedCliOptions).resolve(commonTokens.options); - expect(configReaderModule.default).calledWith(expectedCliOptions); + cliOptions.mutate = ['some', 'files']; + buildMainInjector(injector).resolve(commonTokens.options); + expect(configReaderModule.default).calledWith(cliOptions); }); it('should validate the options', () => { - buildMainInjector({}).resolve(commonTokens.options); + buildMainInjector(injector).resolve(commonTokens.options); expect(optionsValidatorStub.validate).calledWith(expectedConfig); }); it('should warn about unknown properties', () => { expectedConfig.foo = 'bar'; - buildMainInjector({}).resolve(commonTokens.options); + buildMainInjector(injector).resolve(commonTokens.options); expect(currentLogMock().warn).calledWithMatch('Unknown stryker config option "foo"'); }); }); - it('should supply mutatorDescriptor', () => { - const expected: MutatorDescriptor = { - name: 'javascript', - plugins: null, - excludedMutations: [], - }; - const mutatorDescriptor = buildMainInjector({}).resolve(commonTokens.mutatorDescriptor); - expect(mutatorDescriptor).deep.eq(expected); - }); - - it('should be able to supply the test framework', () => { - const actualTestFramework = buildMainInjector({}).resolve(coreTokens.testFramework); - expect(testFrameworkMock).eq(actualTestFramework); - }); - it('should be able to supply the reporter', () => { - const actualReporter = buildMainInjector({}).resolve(coreTokens.reporter); + const actualReporter = buildMainInjector(injector).resolve(coreTokens.reporter); expect(actualReporter).eq(broadcastReporterMock); }); - it('should supply pluginCreators for Reporter, ConfigEditor and TestFramework plugins', () => { - const injector = buildMainInjector({}); - expect(injector.resolve(coreTokens.pluginCreatorReporter)).eq(pluginCreatorMock); - expect(injector.resolve(coreTokens.pluginCreatorTestFramework)).eq(pluginCreatorMock); - expect(injector.resolve(coreTokens.pluginCreatorConfigEditor)).eq(pluginCreatorMock); + it('should supply pluginCreators for Reporter and Checker plugins', () => { + const actualInjector = buildMainInjector(injector); + expect(actualInjector.resolve(coreTokens.pluginCreatorReporter)).eq(pluginCreatorMock); + expect(actualInjector.resolve(coreTokens.pluginCreatorChecker)).eq(pluginCreatorMock); }); }); diff --git a/packages/core/test/unit/initializer/Presets.spec.ts b/packages/core/test/unit/initializer/Presets.spec.ts index 5a8088d6cc..2a92425e8e 100644 --- a/packages/core/test/unit/initializer/Presets.spec.ts +++ b/packages/core/test/unit/initializer/Presets.spec.ts @@ -23,11 +23,6 @@ describe('Presets', () => { expect(angularPreset.name).to.eq('angular-cli'); }); - it('should mutate typescript', async () => { - const config = await angularPreset.createConfig(); - expect(config.config.mutator).to.eq('typescript'); - }); - it('should use the angular-cli', async () => { const config = await angularPreset.createConfig(); expect((config.config.karma as any).projectType).to.eq('angular-cli'); @@ -44,38 +39,6 @@ describe('Presets', () => { it('should have the name "create-react-app"', () => { expect(reactPreset.name).to.eq('create-react-app'); }); - - it('should mutate typescript when TSX is chosen', async () => { - inquirerPrompt.resolves({ - choice: 'TSX', - }); - const config = await reactPreset.createConfig(); - expect(config.config.mutator).to.eq('typescript'); - }); - - it('should install @stryker-mutator/typescript when TSX is chosen', async () => { - inquirerPrompt.resolves({ - choice: 'TSX', - }); - const config = await reactPreset.createConfig(); - expect(config.dependencies).to.include('@stryker-mutator/typescript'); - }); - - it('should mutate javascript when JSX is chosen', async () => { - inquirerPrompt.resolves({ - choice: 'JSX', - }); - const config = await reactPreset.createConfig(); - expect(config.config.mutator).to.eq('javascript'); - }); - - it('should install @stryker-mutator/javascript-mutator when JSX is chosen', async () => { - inquirerPrompt.resolves({ - choice: 'JSX', - }); - const config = await reactPreset.createConfig(); - expect(config.dependencies).to.include('@stryker-mutator/javascript-mutator'); - }); }); describe('VueJsPreset', () => { @@ -85,26 +48,21 @@ describe('Presets', () => { vueJsPreset = new VueJsPreset(); inquirerPrompt.resolves({ script: 'typescript', - testRunner: 'karma', + testRunner: 'jest', }); }); - it('should have the name "vueJs"', () => { - expect(vueJsPreset.name).to.eq('vueJs'); + it('should have the name "vue-cli"', () => { + expect(vueJsPreset.name).to.eq('vue-cli'); }); - it('should use the vue mutator', async () => { - const config = await vueJsPreset.createConfig(); - expect(config.config.mutator).to.contain('vue'); - }); - - it('should install @stryker-mutator/karma-runner when karma is chosen', async () => { + it('should install @stryker-mutator/mocha-runner when mocha is chosen', async () => { inquirerPrompt.resolves({ script: 'typescript', - testRunner: 'karma', + testRunner: 'mocha', }); const config = await vueJsPreset.createConfig(); - expect(config.dependencies).to.include('@stryker-mutator/karma-runner'); + expect(config.dependencies).to.include('@stryker-mutator/mocha-runner'); }); it('should install @stryker-mutator/jest-runner when jest is chosen', async () => { @@ -115,23 +73,5 @@ describe('Presets', () => { const config = await vueJsPreset.createConfig(); expect(config.dependencies).to.include('@stryker-mutator/jest-runner'); }); - - it('should install @stryker-mutator/typescript when typescript is chosen', async () => { - inquirerPrompt.resolves({ - script: 'typescript', - testRunner: 'karma', - }); - const config = await vueJsPreset.createConfig(); - expect(config.dependencies).to.include('@stryker-mutator/typescript'); - }); - - it('should install @stryker-mutator/javascript-mutator when javascript is chosen', async () => { - inquirerPrompt.resolves({ - script: 'javascript', - testRunner: 'karma', - }); - const config = await vueJsPreset.createConfig(); - expect(config.dependencies).to.include('@stryker-mutator/javascript-mutator'); - }); }); }); diff --git a/packages/core/test/unit/initializer/StrykerInitializer.spec.ts b/packages/core/test/unit/initializer/StrykerInitializer.spec.ts index dd312f961b..06fe976512 100644 --- a/packages/core/test/unit/initializer/StrykerInitializer.spec.ts +++ b/packages/core/test/unit/initializer/StrykerInitializer.spec.ts @@ -63,15 +63,9 @@ describe(StrykerInitializer.name, () => { describe('initialize()', () => { beforeEach(() => { stubTestRunners('@stryker-mutator/awesome-runner', 'stryker-hyper-runner', 'stryker-ghost-runner'); - stubTestFrameworks( - { name: '@stryker-mutator/awesome-framework', keywords: ['@stryker-mutator/awesome-runner'], version: '1.1.1' }, - { name: 'stryker-hyper-framework', keywords: ['stryker-hyper-runner'], version: '1.1.1' } - ); stubMutators('@stryker-mutator/typescript', '@stryker-mutator/javascript-mutator'); - stubTranspilers('@stryker-mutator/typescript', '@stryker-mutator/webpack'); stubReporters('stryker-dimension-reporter', '@stryker-mutator/mars-reporter'); stubPackageClient({ - '@stryker-mutator/awesome-framework': null, '@stryker-mutator/awesome-runner': null, '@stryker-mutator/javascript-mutator': null, '@stryker-mutator/mars-reporter': null, @@ -79,7 +73,6 @@ describe(StrykerInitializer.name, () => { '@stryker-mutator/webpack': null, 'stryker-dimension-reporter': null, 'stryker-ghost-runner': null, - 'stryker-hyper-framework': null, 'stryker-hyper-runner': { files: [], someOtherSetting: 'enabled', @@ -89,37 +82,22 @@ describe(StrykerInitializer.name, () => { presets.push(presetMock); }); - it('should prompt for preset, test runner, test framework, mutator, transpilers, reporters, package manager and config type', async () => { + it('should prompt for preset, test runner, reporters, package manager and config type', async () => { arrangeAnswers({ - mutator: 'typescript', packageManager: 'yarn', reporters: ['dimension', 'mars'], - testFramework: 'awesome', testRunner: 'awesome', - transpilers: ['webpack'], }); await sut.initialize(); - expect(inquirerPrompt).callCount(8); - const [ - promptPreset, - promptTestRunner, - promptTestFramework, - promptMutator, - promptPackageManagers, - promptConfigTypes, - ]: Array> = [ + expect(inquirerPrompt).callCount(5); + const [promptPreset, promptTestRunner, promptReporters, promptPackageManagers, promptConfigTypes]: inquirer.ListQuestion[] = [ inquirerPrompt.getCall(0).args[0], inquirerPrompt.getCall(1).args[0], inquirerPrompt.getCall(2).args[0], inquirerPrompt.getCall(3).args[0], - inquirerPrompt.getCall(6).args[0], - inquirerPrompt.getCall(7).args[0], - ]; - const [promptTranspilers, promptReporters]: Array> = [ inquirerPrompt.getCall(4).args[0], - inquirerPrompt.getCall(5).args[0], ]; expect(promptPreset.type).to.eq('list'); expect(promptPreset.name).to.eq('preset'); @@ -127,12 +105,6 @@ describe(StrykerInitializer.name, () => { expect(promptTestRunner.type).to.eq('list'); expect(promptTestRunner.name).to.eq('testRunner'); expect(promptTestRunner.choices).to.deep.eq(['awesome', 'hyper', 'ghost', new inquirer.Separator(), 'command']); - expect(promptTestFramework.type).to.eq('list'); - expect(promptTestFramework.choices).to.deep.eq(['awesome', 'None/other']); - expect(promptMutator.type).to.eq('list'); - expect(promptMutator.choices).to.deep.eq(['typescript', 'javascript']); - expect(promptTranspilers.type).to.eq('checkbox'); - expect(promptTranspilers.choices).to.deep.eq(['typescript', 'webpack']); expect(promptReporters.type).to.eq('checkbox'); expect(promptReporters.choices).to.deep.eq(['dimension', 'mars', 'html', 'clear-text', 'progress', 'dashboard']); expect(promptPackageManagers.type).to.eq('list'); @@ -150,18 +122,13 @@ describe(StrykerInitializer.name, () => { resolvePresetConfig(); await sut.initialize(); expect(inquirerPrompt).callCount(3); - expect(out).calledWith( - 'Done configuring stryker. Please review "stryker.conf.json", you might need to configure transpilers or your test runner correctly.' - ); + expect(out).calledWith('Done configuring stryker. Please review "stryker.conf.json", you might need to configure your test runner correctly.'); expect(out).calledWith("Let's kill some mutants with this command: `stryker run`"); }); it('should correctly write and format the stryker js configuration file', async () => { const handbookUrl = 'https://awesome-preset.org'; - const config = { - comment: `This config was generated using a preset. Please see the handbook for more information: ${handbookUrl}`, - awesomeConf: 'awesome', - }; + const config = { awesomeConf: 'awesome' }; childExec.resolves(); resolvePresetConfig({ config, @@ -171,7 +138,7 @@ describe(StrykerInitializer.name, () => { * @type {import('@stryker-mutator/api/core').StrykerOptions} */ module.exports = { - "comment": "${config.comment}", + "_comment": "This config was generated using a preset. Please see the handbook for more information: https://awesome-preset.org", "awesomeConf": "${config.awesomeConf}" };`; inquirerPrompt.resolves({ @@ -224,7 +191,7 @@ describe(StrykerInitializer.name, () => { }); await sut.initialize(); expect(inquirerPrompt).callCount(3); - const [promptPreset, promptConfigType, promptPackageManager]: Array> = [ + const [promptPreset, promptConfigType, promptPackageManager]: inquirer.ListQuestion[] = [ inquirerPrompt.getCall(0).args[0], inquirerPrompt.getCall(1).args[0], inquirerPrompt.getCall(2).args[0], @@ -238,80 +205,43 @@ describe(StrykerInitializer.name, () => { expect(promptPackageManager.choices).to.deep.eq(['npm', 'yarn']); }); - it('should not prompt for testFramework if test runner is "command"', async () => { - arrangeAnswers({ testRunner: 'command' }); - await sut.initialize(); - expect(inquirer.prompt).not.calledWithMatch(sinon.match({ name: 'testFramework' })); - }); - - it('should configure coverageAnalysis: "all" when the user did not select a testFramework', async () => { - inquirerPrompt.resolves({ - packageManager: 'npm', - reporters: ['dimension', 'mars'], - testFramework: 'None/other', - testRunner: 'awesome', - transpilers: ['webpack'], - configType: 'JSON', - }); - await sut.initialize(); - expect(inquirerPrompt).callCount(8); - expect(out).calledWith('OK, downgrading coverageAnalysis to "all"'); - expect(fs.promises.writeFile).calledWith('stryker.conf.json', sinon.match('"coverageAnalysis": "all"')); - }); - it('should install any additional dependencies', async () => { inquirerPrompt.resolves({ - mutator: 'typescript', packageManager: 'npm', reporters: ['dimension', 'mars'], - testFramework: 'awesome', testRunner: 'awesome', - transpilers: ['webpack'], configType: 'JSON', }); await sut.initialize(); expect(out).calledWith('Installing NPM dependencies...'); - expect( - childExecSync - ).calledWith( - 'npm i --save-dev @stryker-mutator/awesome-runner @stryker-mutator/awesome-framework @stryker-mutator/typescript @stryker-mutator/webpack stryker-dimension-reporter @stryker-mutator/mars-reporter', - { stdio: [0, 1, 2] } - ); + expect(childExecSync).calledWith('npm i --save-dev @stryker-mutator/awesome-runner stryker-dimension-reporter @stryker-mutator/mars-reporter', { + stdio: [0, 1, 2], + }); }); - it('should configure testFramework, testRunner, mutator, transpilers, reporters, and packageManager', async () => { + it('should configure testRunner, reporters, and packageManager', async () => { inquirerPrompt.resolves({ - mutator: 'typescript', packageManager: 'npm', reporters: ['dimension', 'mars', 'progress'], - testFramework: 'awesome', testRunner: 'awesome', - transpilers: ['webpack'], configType: 'JSON', }); await sut.initialize(); - const matchNormalized = (expected: string) => - sinon.match((actual: string) => normalizeWhitespaces(actual).includes(normalizeWhitespaces(expected))); - expect(fs.promises.writeFile).calledWith( - 'stryker.conf.json', - matchNormalized('"testRunner": "awesome"') - .and(matchNormalized('"testFramework": "awesome"')) - .and(matchNormalized('"packageManager": "npm"')) - .and(matchNormalized('"coverageAnalysis": "perTest"')) - .and(matchNormalized('"mutator": "typescript"')) - .and(matchNormalized('"transpilers": [ "webpack" ]')) - .and(matchNormalized('"dimension", "mars", "progress"')) - ); + expect(fsWriteFile).calledOnce; + const [fileName, content] = fsWriteFile.getCall(0).args; + expect(fileName).eq('stryker.conf.json'); + const normalizedContent = normalizeWhitespaces(content); + expect(normalizedContent).contains('"testRunner": "awesome"'); + expect(normalizedContent).contains('"packageManager": "npm"'); + expect(normalizedContent).contains('"coverageAnalysis": "perTest"'); + expect(normalizedContent).contains('"dimension", "mars", "progress"'); }); it('should configure the additional settings from the plugins', async () => { inquirerPrompt.resolves({ - mutator: 'javascript', packageManager: 'npm', reporters: [], - testFramework: 'hyper', testRunner: 'hyper', - transpilers: ['webpack'], configType: 'JSON', }); await sut.initialize(); @@ -319,30 +249,15 @@ describe(StrykerInitializer.name, () => { expect(fs.promises.writeFile).calledWith('stryker.conf.json', sinon.match('"files": []')); }); - describe('but no testFramework can be found that supports the testRunner', () => { - beforeEach(() => - inquirerPrompt.resolves({ - packageManager: 'npm', - reporters: ['dimension', 'mars'], - testRunner: 'ghost', - transpilers: ['webpack'], - configType: 'JSON', - }) - ); - - it('should not prompt for test framework', async () => { - await sut.initialize(); - - expect(inquirerPrompt).callCount(7); - expect(inquirerPrompt).not.calledWithMatch(sinon.match({ name: 'testFramework' })); - }); - - it('should configure coverageAnalysis: "all"', async () => { - await sut.initialize(); - - expect(out).calledWith('No stryker test framework plugin found that is compatible with ghost, downgrading coverageAnalysis to "all"'); - expect(fs.promises.writeFile).calledWith('stryker.conf.json', sinon.match('"coverageAnalysis": "all"')); + it('should set "coverageAnalysis" to "off" when the command test runner is chosen', async () => { + inquirerPrompt.resolves({ + packageManager: 'npm', + reporters: [], + testRunner: 'command', + configType: 'JSON', }); + await sut.initialize(); + expect(fs.promises.writeFile).calledWith('stryker.conf.json', sinon.match('"coverageAnalysis": "off"')); }); it('should reject with that error', () => { @@ -352,7 +267,6 @@ describe(StrykerInitializer.name, () => { packageManager: 'npm', reporters: [], testRunner: 'ghost', - transpilers: ['webpack'], configType: 'JSON', }); @@ -365,17 +279,12 @@ describe(StrykerInitializer.name, () => { packageManager: 'npm', reporters: [], testRunner: 'ghost', - transpilers: ['webpack'], configType: 'JSON', }); - stubTranspilers('@stryker-mutator/webpack-transpiler'); - stubPackageClient({ '@stryker-mutator/webpack-transpiler': null }); await sut.initialize(); - expect(out).calledWith( - 'An error occurred during installation, please try it yourself: "npm i --save-dev stryker-ghost-runner @stryker-mutator/webpack-transpiler"' - ); + expect(out).calledWith('An error occurred during installation, please try it yourself: "npm i --save-dev stryker-ghost-runner"'); expect(fs.promises.writeFile).called; }); }); @@ -384,13 +293,11 @@ describe(StrykerInitializer.name, () => { it('should log error and continue when fetching test runners', async () => { restClientSearch.get.withArgs('/v2/search?q=keywords:@stryker-mutator/test-runner-plugin').rejects(); stubMutators('stryker-javascript'); - stubTranspilers('stryker-webpack'); stubReporters(); stubPackageClient({ 'stryker-javascript': null, 'stryker-webpack': null }); inquirerPrompt.resolves({ packageManager: 'npm', reporters: ['clear-text'], - transpilers: ['webpack'], configType: 'JSON', }); @@ -399,92 +306,17 @@ describe(StrykerInitializer.name, () => { expect(testInjector.logger.error).calledWith( 'Unable to reach npms.io (for query /v2/search?q=keywords:@stryker-mutator/test-runner-plugin). Please check your internet connection.' ); - expect(out).calledWith('Unable to select a test runner. You will need to configure it manually.'); - expect(fs.promises.writeFile).called; - }); - - it('should log error and continue when fetching test frameworks', async () => { - stubTestRunners('stryker-awesome-runner'); - restClientSearch.get.withArgs('/v2/search?q=keywords:@stryker-mutator/test-framework-plugin').rejects(); - inquirerPrompt.resolves({ - packageManager: 'npm', - reporters: ['clear-text'], - testRunner: 'awesome', - transpilers: ['webpack'], - configType: 'JSON', - }); - stubMutators('stryker-javascript'); - stubTranspilers('stryker-webpack'); - stubReporters(); - stubPackageClient({ 'stryker-awesome-runner': null, 'stryker-javascript': null, 'stryker-webpack': null }); - - await sut.initialize(); - - expect(testInjector.logger.error).calledWith( - 'Unable to reach npms.io (for query /v2/search?q=keywords:@stryker-mutator/test-framework-plugin). Please check your internet connection.' - ); - expect(out).calledWith('No stryker test framework plugin found that is compatible with awesome, downgrading coverageAnalysis to "all"'); - expect(fs.promises.writeFile).called; - }); - - it('should log error and continue when fetching mutators', async () => { - stubTestRunners('stryker-awesome-runner'); - stubTestFrameworks({ name: 'stryker-awesome-framework', keywords: ['stryker-awesome-runner'], version: '1.1.1' }); - restClientSearch.get.withArgs('/v2/search?q=keywords:@stryker-mutator/mutator-plugin').rejects(); - stubTranspilers('stryker-webpack'); - stubReporters(); - inquirerPrompt.resolves({ - packageManager: 'npm', - reporters: ['clear-text'], - testRunner: 'awesome', - transpilers: ['webpack'], - configType: 'JSON', - }); - stubPackageClient({ 'stryker-awesome-runner': null, 'stryker-webpack': null }); - - await sut.initialize(); - - expect(testInjector.logger.error).calledWith( - 'Unable to reach npms.io (for query /v2/search?q=keywords:@stryker-mutator/mutator-plugin). Please check your internet connection.' - ); - expect(out).calledWith('Unable to select a mutator. You will need to configure it manually.'); - expect(fs.promises.writeFile).called; - }); - - it('should log error and continue when fetching transpilers', async () => { - stubTestRunners('stryker-awesome-runner'); - stubTestFrameworks({ name: 'stryker-awesome-framework', keywords: ['stryker-awesome-runner'], version: '1.1.1' }); - stubMutators('stryker-javascript'); - restClientSearch.get.withArgs('/v2/search?q=keywords:@stryker-mutator/transpiler-plugin').rejects(); - stubReporters(); - inquirerPrompt.resolves({ - packageManager: 'npm', - reporters: ['clear-text'], - testRunner: 'awesome', - configType: 'JSON', - }); - stubPackageClient({ 'stryker-awesome-runner': null, 'stryker-javascript': null }); - - await sut.initialize(); - - expect(testInjector.logger.error).calledWith( - 'Unable to reach npms.io (for query /v2/search?q=keywords:@stryker-mutator/transpiler-plugin). Please check your internet connection.' - ); - expect(out).calledWith('Unable to select transpilers. You will need to configure it manually, if you want to use any.'); - expect(fs.promises.writeFile).called; + expect(fs.promises.writeFile).calledWith('stryker.conf.json', sinon.match('"testRunner": "command"')); }); it('should log error and continue when fetching stryker reporters', async () => { stubTestRunners('stryker-awesome-runner'); - stubTestFrameworks({ name: 'stryker-awesome-framework', keywords: ['stryker-awesome-runner'], version: '1.1.1' }); stubMutators('stryker-javascript'); - stubTranspilers('stryker-webpack'); restClientSearch.get.withArgs('/v2/search?q=keywords:@stryker-mutator/reporter-plugin').rejects(); inquirerPrompt.resolves({ packageManager: 'npm', reporters: ['clear-text'], testRunner: 'awesome', - transpilers: ['webpack'], configType: 'JSON', }); stubPackageClient({ 'stryker-awesome-runner': null, 'stryker-javascript': null, 'stryker-webpack': null }); @@ -499,15 +331,12 @@ describe(StrykerInitializer.name, () => { it('should log warning and continue when fetching custom config', async () => { stubTestRunners('stryker-awesome-runner'); - stubTestFrameworks(); stubMutators(); - stubTranspilers('webpack'); stubReporters(); inquirerPrompt.resolves({ packageManager: 'npm', reporters: ['clear-text'], testRunner: 'awesome', - transpilers: ['webpack'], configType: 'JSON', }); restClientPackage.get.rejects(); @@ -539,15 +368,6 @@ describe(StrykerInitializer.name, () => { }); }; - const stubTestFrameworks = (...testFrameworks: PackageInfo[]) => { - restClientSearch.get.withArgs('/v2/search?q=keywords:@stryker-mutator/test-framework-plugin').resolves({ - result: { - results: testFrameworks.map((testFramework) => ({ package: testFramework })), - }, - statusCode: 200, - }); - }; - const stubMutators = (...mutators: string[]) => { restClientSearch.get.withArgs('/v2/search?q=keywords:@stryker-mutator/mutator-plugin').resolves({ result: { @@ -557,15 +377,6 @@ describe(StrykerInitializer.name, () => { }); }; - const stubTranspilers = (...transpilers: string[]) => { - restClientSearch.get.withArgs('/v2/search?q=keywords:@stryker-mutator/transpiler-plugin').resolves({ - result: { - results: transpilers.map((transpiler) => ({ package: { name: transpiler, version: '1.1.1' } })), - }, - statusCode: 200, - }); - }; - const stubReporters = (...reporters: string[]) => { restClientSearch.get.withArgs('/v2/search?q=keywords:@stryker-mutator/reporter-plugin').resolves({ result: { @@ -574,9 +385,9 @@ describe(StrykerInitializer.name, () => { statusCode: 200, }); }; - const stubPackageClient = (packageConfigPerPackage: { [packageName: string]: object | null }) => { + const stubPackageClient = (packageConfigPerPackage: { [packageName: string]: Record | null }) => { Object.keys(packageConfigPerPackage).forEach((packageName) => { - const pkgConfig: PackageInfo & { initStrykerConfig?: object } = { + const pkgConfig: PackageInfo & { initStrykerConfig?: Record } = { keywords: [], name: packageName, version: '1.1.1', @@ -594,10 +405,7 @@ describe(StrykerInitializer.name, () => { interface StrykerInitAnswers { preset: string | null; - testFramework: string; testRunner: string; - mutator: string; - transpilers: string[]; reporters: string[]; packageManager: string; } @@ -605,13 +413,10 @@ describe(StrykerInitializer.name, () => { function arrangeAnswers(answerOverrides?: Partial) { const answers: StrykerInitAnswers = Object.assign( { - mutator: 'typescript', packageManager: 'yarn', preset: null, reporters: ['dimension', 'mars'], - testFramework: 'awesome', testRunner: 'awesome', - transpilers: ['webpack'], }, answerOverrides ); @@ -628,10 +433,8 @@ describe(StrykerInitializer.name, () => { } function expectStrykerConfWritten(expectedRawConfig: string) { - expect(fsWriteFile).calledWithMatch( - sinon.match('stryker.conf.js'), - sinon.match((actualConf: string) => normalizeWhitespaces(expectedRawConfig) === normalizeWhitespaces(actualConf)) - ); - fsWriteFile.getCall(0); + const [fileName, actualConfig] = fsWriteFile.getCall(0).args; + expect(fileName).eq('stryker.conf.js'); + expect(normalizeWhitespaces(actualConfig)).deep.eq(normalizeWhitespaces(expectedRawConfig)); } }); diff --git a/packages/core/test/unit/input/InputFileResolver.spec.ts b/packages/core/test/unit/input/InputFileResolver.spec.ts index 4c46c56867..150ad62bad 100644 --- a/packages/core/test/unit/input/InputFileResolver.spec.ts +++ b/packages/core/test/unit/input/InputFileResolver.spec.ts @@ -1,12 +1,12 @@ import * as os from 'os'; import * as path from 'path'; -import * as fs from 'fs'; +import fs = require('fs'); import { File } from '@stryker-mutator/api/core'; import { SourceFile } from '@stryker-mutator/api/report'; -import { testInjector, factory } from '@stryker-mutator/test-helpers'; +import { testInjector, factory, assertions, tick } from '@stryker-mutator/test-helpers'; import { createIsDirError, fileNotFoundError } from '@stryker-mutator/test-helpers/src/factory'; -import { childProcessAsPromised, errorToString } from '@stryker-mutator/util'; +import { childProcessAsPromised, errorToString, Task } from '@stryker-mutator/util'; import { expect } from 'chai'; import * as sinon from 'sinon'; @@ -29,10 +29,8 @@ describe(InputFileResolver.name, () => { beforeEach(() => { reporterMock = mock(BroadcastReporter); globStub = sinon.stub(fileUtils, 'glob'); - readFileStub = sinon - .stub(fs.promises, 'readFile') - .withArgs(sinon.match.string) - .resolves(Buffer.from('')) // fallback + readFileStub = sinon.stub(fs.promises, 'readFile'); + readFileStub .withArgs(sinon.match.string) .resolves(Buffer.from('')) // fallback .withArgs(sinon.match('file1')) @@ -45,6 +43,7 @@ describe(InputFileResolver.name, () => { .resolves(Buffer.from('mutate 1 content')) .withArgs(sinon.match('mute2')) .resolves(Buffer.from('mutate 2 content')); + globStub.withArgs('mute*').resolves(['/mute1.js', '/mute2.js']); globStub.withArgs('mute1').resolves(['/mute1.js']); globStub.withArgs('mute2').resolves(['/mute2.js']); @@ -134,6 +133,63 @@ describe(InputFileResolver.name, () => { expect(result.files).lengthOf(0); }); + it('should decode encoded file names', async () => { + sut = createSut(); + childProcessExecStub.resolves({ + // \303\245 = å + // \360\237\220\261\342\200\215\360\237\221\223 = 🐱‍👓 + // On linux, files are allowed to contain `\`, which is also escaped in git output + stdout: Buffer.from(` + "\\303\\245.js" + "src/\\360\\237\\220\\261\\342\\200\\215\\360\\237\\221\\223ninja.cat.js" + "a\\\\test\\\\file.js" + `), + }); + const files = await sut.resolve(); + assertions.expectTextFilesEqual(files.files, [ + new File(path.resolve('a\\test\\file.js'), ''), + new File(path.resolve('src/🐱‍👓ninja.cat.js'), ''), + new File(path.resolve('å.js'), ''), + ]); + }); + + it('should reject when a globbing expression results in a reject', () => { + testInjector.options.files = ['fileError', 'fileError']; + testInjector.options.mutate = ['file1']; + sut = createSut(); + const expectedError = new Error('ERROR: something went wrong'); + globStub.withArgs('fileError').rejects(expectedError); + return expect(sut.resolve()).rejectedWith(expectedError); + }); + + it('should not open too many file handles', async () => { + // Arrange + const maxFileIO = 256; + sut = createSut(); + const fileHandles: Array<{ fileName: string; task: Task }> = []; + for (let i = 0; i < maxFileIO + 1; i++) { + const fileName = `file_${i}.js`; + const readFileTask = new Task(); + fileHandles.push({ fileName, task: readFileTask }); + readFileStub.withArgs(sinon.match(fileName)).returns(readFileTask.promise); + } + childProcessExecStub.resolves({ + stdout: Buffer.from(fileHandles.map(({ fileName }) => fileName).join(os.EOL)), + }); + + // Act + const onGoingWork = sut.resolve(); + await tick(); + expect(readFileStub).callCount(maxFileIO); + fileHandles[0].task.resolve(Buffer.from('content')); + await tick(); + + // Assert + expect(readFileStub).callCount(maxFileIO + 1); + fileHandles.forEach(({ task }) => task.resolve(Buffer.from('content'))); + await onGoingWork; + }); + describe('with mutate file expressions', () => { it('should result in the expected mutate files', async () => { testInjector.options.mutate = ['mute*']; @@ -143,10 +199,10 @@ describe(InputFileResolver.name, () => { expect(result.filesToMutate.map((_) => _.name)).to.deep.equal([path.resolve('/mute1.js'), path.resolve('/mute2.js')]); expect(result.files.map((file) => file.name)).to.deep.equal([ path.resolve('/file1.js'), - path.resolve('/mute1.js'), path.resolve('/file2.js'), - path.resolve('/mute2.js'), path.resolve('/file3.js'), + path.resolve('/mute1.js'), + path.resolve('/mute2.js'), ]); }); @@ -165,10 +221,10 @@ describe(InputFileResolver.name, () => { await sut.resolve(); const expected: SourceFile[] = [ { path: path.resolve('/file1.js'), content: 'file 1 content' }, - { path: path.resolve('/mute1.js'), content: 'mutate 1 content' }, { path: path.resolve('/file2.js'), content: 'file 2 content' }, - { path: path.resolve('/mute2.js'), content: 'mutate 2 content' }, { path: path.resolve('/file3.js'), content: 'file 3 content' }, + { path: path.resolve('/mute1.js'), content: 'mutate 1 content' }, + { path: path.resolve('/mute2.js'), content: 'mutate 2 content' }, ]; expect(reporterMock.onAllSourceFilesRead).calledWith(expected); }); @@ -180,10 +236,10 @@ describe(InputFileResolver.name, () => { await sut.resolve(); const expected: SourceFile[] = [ { path: path.resolve('/file1.js'), content: 'file 1 content' }, - { path: path.resolve('/mute1.js'), content: 'mutate 1 content' }, { path: path.resolve('/file2.js'), content: 'file 2 content' }, - { path: path.resolve('/mute2.js'), content: 'mutate 2 content' }, { path: path.resolve('/file3.js'), content: 'file 3 content' }, + { path: path.resolve('/mute1.js'), content: 'mutate 1 content' }, + { path: path.resolve('/mute2.js'), content: 'mutate 2 content' }, ]; expected.forEach((sourceFile) => expect(reporterMock.onSourceFileRead).calledWith(sourceFile)); }); @@ -238,15 +294,6 @@ describe(InputFileResolver.name, () => { }); }); - it('should reject when a globbing expression results in a reject', () => { - testInjector.options.files = ['fileError', 'fileError']; - testInjector.options.mutate = ['file1']; - sut = createSut(); - const expectedError = new Error('ERROR: something went wrong'); - globStub.withArgs('fileError').rejects(expectedError); - return expect(sut.resolve()).rejectedWith(expectedError); - }); - describe('when excluding files with "!"', () => { it('should exclude the files that were previously included', async () => { testInjector.options.files = ['file2', 'file1', '!file2']; @@ -286,7 +333,7 @@ describe(InputFileResolver.name, () => { it('should order files by expression order', async () => { testInjector.options.files = ['file2', 'file*']; const result = await createSut().resolve(); - assertFilesEqual(result.files, files(['/file2.js', 'file 2 content'], ['/file1.js', 'file 1 content'], ['/file3.js', 'file 3 content'])); + assertFilesEqual(result.files, files(['/file1.js', 'file 1 content'], ['/file2.js', 'file 2 content'], ['/file3.js', 'file 3 content'])); }); }); diff --git a/packages/core/test/unit/logging/LogConfigurator.spec.ts b/packages/core/test/unit/logging/LogConfigurator.spec.ts index 77c0528df8..7c9e642b02 100644 --- a/packages/core/test/unit/logging/LogConfigurator.spec.ts +++ b/packages/core/test/unit/logging/LogConfigurator.spec.ts @@ -3,8 +3,8 @@ import { expect } from 'chai'; import * as log4js from 'log4js'; import * as sinon from 'sinon'; -import LogConfigurator from '../../../src/logging/LogConfigurator'; -import LoggingClientContext from '../../../src/logging/LoggingClientContext'; +import { LogConfigurator } from '../../../src/logging'; +import { LoggingClientContext } from '../../../src/logging'; import * as netUtils from '../../../src/utils/netUtils'; describe('LogConfigurator', () => { diff --git a/packages/core/test/unit/logging/MultiAppender.spec.ts b/packages/core/test/unit/logging/MultiAppender.spec.ts index f40bc675ae..d04379de08 100644 --- a/packages/core/test/unit/logging/MultiAppender.spec.ts +++ b/packages/core/test/unit/logging/MultiAppender.spec.ts @@ -28,7 +28,7 @@ describe('MultiAppender', () => { categoryName: 'category', context: null, data: ['foo data'], - level: (log4js.levels as any).DEBUG, + level: log4js.levels.DEBUG, pid: 42, startTime: new Date(42), }; diff --git a/packages/core/test/unit/mutants/MutantTestMatcher.spec.ts b/packages/core/test/unit/mutants/MutantTestMatcher.spec.ts deleted file mode 100644 index 2cfea3ece3..0000000000 --- a/packages/core/test/unit/mutants/MutantTestMatcher.spec.ts +++ /dev/null @@ -1,554 +0,0 @@ -import { File } from '@stryker-mutator/api/core'; -import { Mutant } from '@stryker-mutator/api/mutant'; -import { MatchedMutant } from '@stryker-mutator/api/report'; -import { TestSelection } from '@stryker-mutator/api/test_framework'; -import { CoverageCollection, CoveragePerTestResult, RunStatus, TestResult, TestStatus } from '@stryker-mutator/api/test_runner'; -import { testInjector } from '@stryker-mutator/test-helpers'; -import { mutant, testResult } from '@stryker-mutator/test-helpers/src/factory'; -import { expect } from 'chai'; -import * as sinon from 'sinon'; - -import { coreTokens } from '../../../src/di'; -import InputFileCollection from '../../../src/input/InputFileCollection'; -import { MutantTestMatcher } from '../../../src/mutants/MutantTestMatcher'; -import { InitialTestRunResult } from '../../../src/process/InitialTestExecutor'; -import BroadcastReporter from '../../../src/reporters/BroadcastReporter'; -import SourceFile from '../../../src/SourceFile'; -import TestableMutant, { TestSelectionResult } from '../../../src/TestableMutant'; -import { CoverageMapsByFile } from '../../../src/transpiler/CoverageInstrumenterTranspiler'; -import { MappedLocation, PassThroughSourceMapper } from '../../../src/transpiler/SourceMapper'; -import { Mock, mock } from '../../helpers/producers'; - -describe(MutantTestMatcher.name, () => { - let sut: MutantTestMatcher; - let mutants: Mutant[]; - let initialRunResult: InitialTestRunResult; - let input: InputFileCollection; - let fileCoverageDictionary: CoverageMapsByFile; - let reporter: Mock; - - beforeEach(() => { - mutants = []; - fileCoverageDictionary = Object.create(null); - initialRunResult = { - coverageMaps: fileCoverageDictionary, - overheadTimeMS: 42, - runResult: { tests: [], status: RunStatus.Complete }, - sourceMapper: new PassThroughSourceMapper(), - }; - reporter = mock(BroadcastReporter); - input = new InputFileCollection( - [new File('fileWithMutantOne', '\n\n\n\n12345'), new File('fileWithMutantTwo', '\n\n\n\n\n\n\n\n\n\n')], - ['fileWithMutantOne', 'fileWithMutantTwo'] - ); - sinon.spy(initialRunResult.sourceMapper, 'transpiledLocationFor'); - }); - - describe('with coverageAnalysis: "perTest"', () => { - beforeEach(() => { - testInjector.options.coverageAnalysis = 'perTest'; - sut = createSut(); - }); - - describe('matchWithMutants(mutants)', () => { - describe('with 2 mutants and 2 testResults', () => { - let mutantOne: Mutant; - let mutantTwo: Mutant; - let testResultOne: TestResult; - let testResultTwo: TestResult; - - beforeEach(() => { - mutantOne = { - fileName: 'fileWithMutantOne', - mutatorName: 'myMutator', - range: [9, 9], // line 4:5 -> line 4:5 - replacement: '>', - // location: { start: { line: 4, column: 5 }, end: { line: 4, column: 5 } }, - }; - - mutantTwo = { - fileName: 'fileWithMutantTwo', - mutatorName: 'myMutator', - range: [9, 9], // line 9:0 -> line 9:0 - replacement: '<', - // location: { start: { line: 9, column: 0 }, end: { line: 9, column: 0 } }, - }; - - testResultOne = { - name: 'test one', - status: TestStatus.Success, - timeSpentMs: 5, - }; - testResultTwo = { - name: 'test two', - status: TestStatus.Success, - timeSpentMs: 5, - }; - initialRunResult.runResult.tests.push(testResultOne, testResultTwo); - mutants.push(mutantOne); - mutants.push(mutantTwo); - }); - - describe('without code coverage info', () => { - it('should run all tests for the mutants and report failure', async () => { - const result = await sut.matchWithMutants(mutants); - - expect(result[0].runAllTests).true; - expect(result[1].runAllTests).true; - expect(TestSelectionResult[result[0].testSelectionResult]).eq(TestSelectionResult[TestSelectionResult.FailedButAlreadyReported]); - expect(TestSelectionResult[result[1].testSelectionResult]).eq(TestSelectionResult[TestSelectionResult.FailedButAlreadyReported]); - expect(testInjector.logger.warn).calledWith( - 'No coverage result found, even though coverageAnalysis is "%s". Assuming that all tests cover each mutant. This might have a big impact on the performance.', - 'perTest' - ); - }); - - it('should have both mutants matched', async () => { - const result = await sut.matchWithMutants(mutants); - - const matchedMutants: MatchedMutant[] = [ - { - fileName: result[0].fileName, - id: '0', - mutatorName: result[0].mutatorName, - replacement: result[0].replacement, - runAllTests: true, - scopedTestIds: [], - timeSpentScopedTests: result[0].timeSpentScopedTests, - }, - { - fileName: result[1].fileName, - id: '1', - mutatorName: result[1].mutatorName, - replacement: result[1].replacement, - runAllTests: true, - scopedTestIds: [], - timeSpentScopedTests: result[1].timeSpentScopedTests, - }, - ]; - - expect(reporter.onAllMutantsMatchedWithTests).calledWith(Object.freeze(matchedMutants)); - }); - }); - - describe('without the tests having covered the mutants', () => { - beforeEach(() => { - const covCollectionPerFile: CoveragePerTestResult = { - baseline: {}, - deviations: { - 0: { - anOtherFile: { s: { 1: 1 }, f: {} }, // covers, but in wrong src file - }, - 1: { - fileWithMutantOne: { s: { 1: 1, 2: 1, 3: 0 }, f: {} }, // Covers, but not smallest statement based on column - fileWithMutantTwo: { s: { 1: 1, 2: 0, 3: 1 }, f: {} }, // Covers, but not smallest statement based on row number - }, - }, - }; - initialRunResult.runResult.coverage = covCollectionPerFile; - - fileCoverageDictionary.anOtherFile = { - fnMap: {}, - statementMap: { - 1: { - // covers but in wrong src file - end: { line: 4, column: 7 }, - start: { line: 4, column: 0 }, - }, - }, - }; - fileCoverageDictionary.fileWithMutantOne = { - fnMap: {}, - statementMap: { - 1: { - end: { line: 4, column: 9 }, - start: { line: 2, column: 0 }, - }, - 2: { - end: { line: 4, column: 9 }, - start: { line: 4, column: 0 }, - }, - 3: { - // Smallest statement that surrounds the mutant. Differs based on column number - end: { line: 4, column: 7 }, - start: { line: 4, column: 3 }, - }, - }, - }; - fileCoverageDictionary.fileWithMutantTwo = { - fnMap: {}, - statementMap: { - 1: { - end: { line: 9, column: 4 }, - start: { line: 0, column: 0 }, - }, - 2: { - // Smallest statement that surround the mutant. Differs based on line number - end: { line: 9, column: 4 }, - start: { line: 8, column: 0 }, - }, - 3: { - end: { line: 9, column: 4 }, - start: { line: 9, column: 1 }, - }, - }, - }; - }); - - it('should not have added the run results to the mutants', async () => { - const result = await sut.matchWithMutants(mutants); - - expect(result[0].selectedTests).lengthOf(0); - expect(result[1].selectedTests).lengthOf(0); - }); - }); - - describe('with tests having covered the mutants based on statements', () => { - beforeEach(() => { - fileCoverageDictionary.fileWithMutantOne = { - fnMap: {}, - statementMap: { - 1: { start: { line: 4, column: 0 }, end: { line: 6, column: 0 } }, - }, - }; - fileCoverageDictionary.fileWithMutantTwo = { - fnMap: {}, - statementMap: { - 1: { start: { line: 0, column: 0 }, end: { line: 10, column: 0 } }, - }, - }; - - initialRunResult.runResult.coverage = { - baseline: {}, - deviations: { - 0: { - fileWithMutantOne: { s: { 1: 1 }, f: {} }, - fileWithMutantTwo: { s: { 1: 1 }, f: {} }, - }, - 1: { - fileWithMutantOne: { s: { 1: 1 }, f: {} }, - }, - }, - }; - sut = createSut(); - }); - - it('should have added the run results to the mutants', async () => { - const expectedTestSelectionFirstMutant: TestSelection[] = [ - { id: 0, name: 'test one' }, - { id: 1, name: 'test two' }, - ]; - - const result = await sut.matchWithMutants(mutants); - - const expectedTestSelectionSecondMutant: TestSelection[] = [{ id: 0, name: 'test one' }]; - expect(result[0].selectedTests).deep.eq(expectedTestSelectionFirstMutant); - expect(result[1].selectedTests).deep.eq(expectedTestSelectionSecondMutant); - expect(result[0].testSelectionResult).deep.eq(TestSelectionResult.Success); - expect(result[1].testSelectionResult).deep.eq(TestSelectionResult.Success); - }); - }); - - describe('without matching statements or functions', () => { - beforeEach(() => { - fileCoverageDictionary.fileWithMutantOne = { statementMap: {}, fnMap: {} }; - fileCoverageDictionary.fileWithMutantTwo = { statementMap: {}, fnMap: {} }; - initialRunResult.runResult.coverage = { baseline: {}, deviations: {} }; - sut = createSut(); - }); - - it('should select all test in the test run but not report the error yet', async () => { - const result = await sut.matchWithMutants(mutants); - - expect(result[0].runAllTests).true; - expect(result[1].runAllTests).true; - expect(result[0].testSelectionResult).eq(TestSelectionResult.Failed); - expect(result[1].testSelectionResult).eq(TestSelectionResult.Failed); - expect(testInjector.logger.warn).not.called; - }); - }); - - describe('with a mutant being covered using function coverage', () => { - beforeEach(() => { - fileCoverageDictionary.fileWithMutantOne = { - fnMap: { - 1: { start: { line: 4, column: 0 }, end: { line: 6, column: 0 } }, - }, - statementMap: {}, - }; - fileCoverageDictionary.fileWithMutantTwo = { statementMap: {}, fnMap: {} }; - initialRunResult.runResult.coverage = { - baseline: {}, - deviations: { 0: { fileWithMutantOne: { s: {}, f: { 1: 1 } } } }, - }; - sut = createSut(); - }); - - it('should have added the run results to the mutant', async () => { - const expectedTestSelection = [{ id: 0, name: 'test one' }]; - - const result = await sut.matchWithMutants(mutants); - - expect(result[0].selectedTests).deep.eq(expectedTestSelection); - }); - }); - - describe('with baseline covering a mutant', () => { - beforeEach(() => { - fileCoverageDictionary.fileWithMutantOne = { - fnMap: {}, - statementMap: { - 1: { start: { line: 4, column: 0 }, end: { line: 6, column: 0 } }, - }, - }; - fileCoverageDictionary.fileWithMutantTwo = { - fnMap: {}, - statementMap: { - 1: { start: { line: 10, column: 0 }, end: { line: 10, column: 0 } }, - }, - }; - initialRunResult.runResult.coverage = { - baseline: { - fileWithMutantOne: { s: { 1: 1 }, f: {} }, - }, - deviations: {}, - }; - sut = createSut(); - }); - - it('should add all test results to the mutant that is covered by the baseline', async () => { - const result = await sut.matchWithMutants(mutants); - - expect(result[0].runAllTests).true; - expect(result[1].runAllTests).true; - }); - }); - }); - }); - - describe('should not result in regression', () => { - it('should match up mutant for issue #151 (https://github.com/stryker-mutator/stryker/issues/151)', async () => { - // Arrange - const sourceFile = new SourceFile(new File('', '')); - sourceFile.getLocation = () => ({ start: { line: 13, column: 38 }, end: { line: 24, column: 5 } }); - const testableMutant = new TestableMutant( - '1', - mutant({ - fileName: 'juice-shop\\app\\js\\controllers\\SearchResultController.js', - }), - sourceFile - ); - - const coverageResult: CoverageCollection = { - 'juice-shop\\app\\js\\controllers\\SearchResultController.js': { - s: { - 1: 1, - 2: 1, - 3: 1, - 4: 0, - 5: 1, - 6: 0, - 7: 0, - 8: 0, - 9: 0, - 10: 0, - 11: 0, - 12: 0, - 13: 0, - 14: 0, - 15: 0, - 16: 0, - 17: 0, - 18: 0, - 19: 0, - 20: 0, - 21: 0, - 22: 0, - 23: 0, - 24: 0, - 25: 0, - 26: 0, - 27: 0, - 28: 0, - 29: 0, - 30: 0, - 31: 0, - 32: 1, - 33: 1, - 34: 1, - 35: 1, - 36: 0, - 37: 0, - }, - f: {}, - }, - }; - - fileCoverageDictionary['juice-shop\\app\\js\\controllers\\SearchResultController.js'] = { - statementMap: { - 1: { start: { line: 1, column: 0 }, end: { line: 84, column: 5 } }, - 2: { start: { line: 13, column: 4 }, end: { line: 24, column: 5 } }, - 3: { start: { line: 14, column: 6 }, end: { line: 23, column: 8 } }, - 4: { start: { line: 20, column: 12 }, end: { line: 20, column: 21 } }, - 5: { start: { line: 26, column: 4 }, end: { line: 72, column: 5 } }, - 6: { start: { line: 27, column: 6 }, end: { line: 71, column: 8 } }, - 7: { start: { line: 28, column: 8 }, end: { line: 28, column: 51 } }, - 8: { start: { line: 29, column: 8 }, end: { line: 29, column: 25 } }, - 9: { start: { line: 30, column: 8 }, end: { line: 53, column: 9 } }, - 10: { start: { line: 31, column: 10 }, end: { line: 52, column: 11 } }, - 11: { start: { line: 32, column: 12 }, end: { line: 32, column: 24 } }, - 12: { start: { line: 33, column: 12 }, end: { line: 50, column: 14 } }, - 13: { start: { line: 34, column: 14 }, end: { line: 34, column: 68 } }, - 14: { start: { line: 35, column: 14 }, end: { line: 47, column: 16 } }, - 15: { start: { line: 36, column: 16 }, end: { line: 44, column: 18 } }, - 16: { start: { line: 37, column: 18 }, end: { line: 41, column: 20 } }, - 17: { start: { line: 38, column: 20 }, end: { line: 38, column: 62 } }, - 18: { start: { line: 40, column: 20 }, end: { line: 40, column: 55 } }, - 19: { start: { line: 43, column: 18 }, end: { line: 43, column: 34 } }, - 20: { start: { line: 46, column: 16 }, end: { line: 46, column: 32 } }, - 21: { start: { line: 49, column: 14 }, end: { line: 49, column: 30 } }, - 22: { start: { line: 51, column: 12 }, end: { line: 51, column: 17 } }, - 23: { start: { line: 54, column: 8 }, end: { line: 68, column: 9 } }, - 24: { start: { line: 55, column: 10 }, end: { line: 67, column: 12 } }, - 25: { start: { line: 56, column: 12 }, end: { line: 64, column: 14 } }, - 26: { start: { line: 57, column: 14 }, end: { line: 61, column: 16 } }, - 27: { start: { line: 58, column: 16 }, end: { line: 58, column: 54 } }, - 28: { start: { line: 60, column: 16 }, end: { line: 60, column: 51 } }, - 29: { start: { line: 63, column: 14 }, end: { line: 63, column: 30 } }, - 30: { start: { line: 66, column: 12 }, end: { line: 66, column: 28 } }, - 31: { start: { line: 70, column: 8 }, end: { line: 70, column: 24 } }, - 32: { start: { line: 74, column: 4 }, end: { line: 74, column: 63 } }, - 33: { start: { line: 76, column: 4 }, end: { line: 83, column: 6 } }, - 34: { start: { line: 77, column: 6 }, end: { line: 77, column: 37 } }, - 35: { start: { line: 78, column: 6 }, end: { line: 80, column: 7 } }, - 36: { start: { line: 79, column: 8 }, end: { line: 79, column: 89 } }, - 37: { start: { line: 82, column: 6 }, end: { line: 82, column: 22 } }, - }, - fnMap: {}, - }; - - initialRunResult.runResult.coverage = { baseline: {}, deviations: { 0: coverageResult } }; - initialRunResult.runResult.tests.push({ - name: 'controllers SearchResultController should open a modal dialog with product details', - status: TestStatus.Success, - timeSpentMs: 5, - }); - sut = createSut(); - - // Act - await sut.enrichWithCoveredTests(testableMutant); - - // Assert - expect(testableMutant.selectedTests).deep.eq([ - { - id: 0, - name: 'controllers SearchResultController should open a modal dialog with product details', - }, - ]); - }); - }); - }); - - describe('with coverageAnalysis: "all"', () => { - beforeEach(() => { - testInjector.options.coverageAnalysis = 'all'; - sut = createSut(); - }); - - it('should match all mutants to all tests and log a warning when there is no coverage data', async () => { - mutants.push(mutant({ fileName: 'fileWithMutantOne' }), mutant({ fileName: 'fileWithMutantTwo' })); - initialRunResult.runResult.tests.push(testResult(), testResult()); - - const result = await sut.matchWithMutants(mutants); - - expect(result[0].runAllTests).true; - expect(result[1].runAllTests).true; - expect(result[0].testSelectionResult).deep.eq(TestSelectionResult.FailedButAlreadyReported); - expect(result[1].testSelectionResult).deep.eq(TestSelectionResult.FailedButAlreadyReported); - expect(testInjector.logger.warn).to.have.been.calledWith( - 'No coverage result found, even though coverageAnalysis is "%s". Assuming that all tests cover each mutant. This might have a big impact on the performance.', - 'all' - ); - }); - - describe('when there is coverage data', () => { - beforeEach(() => { - initialRunResult.runResult.coverage = { - fileWithMutantOne: { s: { 0: 1 }, f: {} }, - }; - fileCoverageDictionary.fileWithMutantOne = { - fnMap: {}, - statementMap: { - 0: { start: { line: 0, column: 0 }, end: { line: 6, column: 0 } }, - }, - }; - }); - - it('should retrieves source mapped location', async () => { - // Arrange - mutants.push(mutant({ fileName: 'fileWithMutantOne', range: [4, 5] })); - - // Act - await sut.matchWithMutants(mutants); - - // Assert - const expectedLocation: MappedLocation = { - fileName: 'fileWithMutantOne', - location: { - end: { line: 4, column: 1 }, - start: { line: 4, column: 0 }, - }, - }; - expect(initialRunResult.sourceMapper.transpiledLocationFor).calledWith(expectedLocation); - }); - - it('should match mutant to single test result', async () => { - // Arrange - mutants.push(mutant({ fileName: 'fileWithMutantOne', range: [4, 5] })); - initialRunResult.runResult.tests.push(testResult({ name: 'test 1' }), testResult({ name: 'test 2' })); - - // Act - const result = await sut.matchWithMutants(mutants); - - // Assert - const expectedTestSelection: TestSelection[] = [ - { - id: 0, - name: 'test 1', - }, - { - id: 1, - name: 'test 2', - }, - ]; - expect(result).lengthOf(1); - expect(result[0].selectedTests).deep.eq(expectedTestSelection); - }); - }); - }); - - describe('with coverageAnalysis: "off"', () => { - beforeEach(() => { - testInjector.options.coverageAnalysis = 'off'; - sut = createSut(); - }); - - it('should match all mutants to all tests', async () => { - mutants.push(mutant({ fileName: 'fileWithMutantOne' }), mutant({ fileName: 'fileWithMutantTwo' })); - initialRunResult.runResult.tests.push(testResult(), testResult()); - - const result = await sut.matchWithMutants(mutants); - - expect(result[0].runAllTests).true; - expect(result[1].runAllTests).true; - }); - }); - - function createSut() { - return testInjector.injector - .provideValue(coreTokens.inputFiles, input) - .provideValue(coreTokens.initialRunResult, initialRunResult) - .provideValue(coreTokens.reporter, reporter) - .injectClass(MutantTestMatcher); - } -}); diff --git a/packages/core/test/unit/mutants/MutatorFacade.spec.ts b/packages/core/test/unit/mutants/MutatorFacade.spec.ts deleted file mode 100644 index 5b4d4111c9..0000000000 --- a/packages/core/test/unit/mutants/MutatorFacade.spec.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { Mutator } from '@stryker-mutator/api/mutant'; -import { PluginKind } from '@stryker-mutator/api/plugin'; -import { factory, testInjector } from '@stryker-mutator/test-helpers'; -import { file } from '@stryker-mutator/test-helpers/src/factory'; -import { expect } from 'chai'; -import * as sinon from 'sinon'; - -import { coreTokens, PluginCreator } from '../../../src/di'; -import { MutatorFacade } from '../../../src/mutants/MutatorFacade'; -import { Mock } from '../../helpers/producers'; - -describe('MutatorFacade', () => { - let mutatorMock: Mock; - let pluginCreatorMock: Mock>; - - beforeEach(() => { - mutatorMock = { - mutate: sinon.stub(), - }; - pluginCreatorMock = sinon.createStubInstance(PluginCreator); - pluginCreatorMock.create.returns(mutatorMock); - }); - - describe('mutate', () => { - it('should create the configured Mutator', () => { - testInjector.mutatorDescriptor.name = 'fooMutator'; - const mutants = [factory.mutant()]; - mutatorMock.mutate.returns(mutants); - const sut = createSut(); - const inputFiles = [file()]; - expect(sut.mutate(inputFiles)).eq(mutants); - expect(mutatorMock.mutate).calledWith(inputFiles); - expect(pluginCreatorMock.create).calledWith('fooMutator'); - }); - - it('should log the number of mutants generated', async () => { - mutatorMock.mutate.returns([factory.mutant(), factory.mutant(), factory.mutant()]); - createSut().mutate([]); - expect(testInjector.logger.info).to.have.been.calledWith('3 Mutant(s) generated'); - }); - - it('should log the number of mutants generated and excluded', async () => { - mutatorMock.mutate.returns([ - factory.mutant({ mutatorName: 'foo' }), - factory.mutant({ mutatorName: 'bar' }), - factory.mutant({ mutatorName: 'baz' }), - ]); - testInjector.mutatorDescriptor.excludedMutations = ['foo']; - createSut().mutate([]); - expect(testInjector.logger.info).calledWith('2 Mutant(s) generated (1 Mutant(s) excluded)'); - }); - - it('should log the absence of mutants and the excluded number when all mutants are excluded', async () => { - mutatorMock.mutate.returns([ - factory.mutant({ mutatorName: 'foo' }), - factory.mutant({ mutatorName: 'bar' }), - factory.mutant({ mutatorName: 'baz' }), - ]); - testInjector.mutatorDescriptor.excludedMutations = ['foo', 'bar', 'baz']; - testInjector.mutatorDescriptor.name = 'javascript'; - createSut().mutate([]); - expect(testInjector.logger.info).calledWith("It's a mutant-free world, nothing to test. (3 Mutant(s) excluded)"); - }); - - it('should log the absence of mutants if no mutants were generated', async () => { - mutatorMock.mutate.returns([]); - createSut().mutate([]); - expect(testInjector.logger.info).calledWith("It's a mutant-free world, nothing to test."); - }); - }); - - function createSut() { - return testInjector.injector - .provideValue(coreTokens.pluginCreatorMutator, (pluginCreatorMock as unknown) as PluginCreator) - .injectClass(MutatorFacade); - } -}); diff --git a/packages/core/test/unit/mutants/findMutantTestCoverage.spec.ts b/packages/core/test/unit/mutants/findMutantTestCoverage.spec.ts new file mode 100644 index 0000000000..114dcc080f --- /dev/null +++ b/packages/core/test/unit/mutants/findMutantTestCoverage.spec.ts @@ -0,0 +1,261 @@ +import sinon = require('sinon'); +import { expect } from 'chai'; +import { factory, testInjector } from '@stryker-mutator/test-helpers'; +import { CompleteDryRunResult } from '@stryker-mutator/api/test_runner'; +import { Mutant } from '@stryker-mutator/api/core'; +import { Reporter, MatchedMutant } from '@stryker-mutator/api/report'; + +import { findMutantTestCoverage as sut, MutantTestCoverage } from '../../../src/mutants/findMutantTestCoverage'; +import { coreTokens } from '../../../src/di'; + +describe(sut.name, () => { + let reporterMock: sinon.SinonStubbedInstance>; + + beforeEach(() => { + reporterMock = factory.reporter(); + }); + + function act(dryRunResult: CompleteDryRunResult, mutants: Mutant[]) { + return testInjector.injector + .provideValue(coreTokens.reporter, reporterMock) + .provideValue(coreTokens.dryRunResult, dryRunResult) + .provideValue(coreTokens.mutants, mutants) + .injectFunction(sut); + } + + it('should not match ignored mutants to any tests', () => { + const mutant = factory.mutant({ id: 2, ignoreReason: 'foo should ignore' }); + const dryRunResult = factory.completeDryRunResult({ mutantCoverage: { static: {}, perTest: { '1': { 2: 2 } } } }); + + // Act + const result = act(dryRunResult, [mutant]); + + // Assert + const expected: MutantTestCoverage[] = [{ mutant, estimatedNetTime: 0, coveredByTests: false }]; + expect(result).deep.eq(expected); + }); + + describe('without mutant coverage data', () => { + it('should disable test filtering', () => { + // Arrange + const mutant1 = factory.mutant({ id: 1 }); + const mutant2 = factory.mutant({ id: 2 }); + const mutants = [mutant1, mutant2]; + const dryRunResult = factory.completeDryRunResult({ mutantCoverage: undefined }); + + // Act + const result = act(dryRunResult, mutants); + + // Assert + const expected: MutantTestCoverage[] = [ + { mutant: mutant1, estimatedNetTime: 0, testFilter: undefined, coveredByTests: true }, + { mutant: mutant2, estimatedNetTime: 0, testFilter: undefined, coveredByTests: true }, + ]; + expect(result).deep.eq(expected); + }); + + it('should calculate estimatedNetTime as the sum of all tests', () => { + // Arrange + const mutant1 = factory.mutant({ id: 1 }); + const mutants = [mutant1]; + const dryRunResult = factory.completeDryRunResult({ + tests: [factory.successTestResult({ timeSpentMs: 20 }), factory.successTestResult({ timeSpentMs: 22 })], + mutantCoverage: undefined, + }); + + // Act + const result = act(dryRunResult, mutants); + + // Assert + expect(result[0].estimatedNetTime).eq(42); + }); + + it('should report onAllMutantsMatchedWithTests', () => { + // Arrange + const mutants = [ + factory.mutant({ id: 1, fileName: 'foo.js', mutatorName: 'fooMutator', replacement: '<=' }), + factory.mutant({ id: 2, fileName: 'bar.js', mutatorName: 'barMutator', replacement: '{}' }), + ]; + const dryRunResult = factory.completeDryRunResult({ + tests: [factory.successTestResult({ timeSpentMs: 20 }), factory.successTestResult({ timeSpentMs: 22 })], + mutantCoverage: undefined, + }); + + // Act + act(dryRunResult, mutants); + + // Assert + expect(reporterMock.onAllMutantsMatchedWithTests).calledWithExactly([ + factory.matchedMutant({ + id: '1', + fileName: 'foo.js', + mutatorName: 'fooMutator', + replacement: '<=', + runAllTests: true, + testFilter: undefined, + timeSpentScopedTests: 42, + }), + factory.matchedMutant({ + id: '2', + fileName: 'bar.js', + mutatorName: 'barMutator', + replacement: '{}', + runAllTests: true, + testFilter: undefined, + timeSpentScopedTests: 42, + }), + ]); + }); + }); + + describe('with static coverage', () => { + it('should disable test filtering', () => { + // Arrange + const mutant = factory.mutant({ id: 1 }); + const mutants = [mutant]; + const dryRunResult = factory.completeDryRunResult({ + tests: [factory.successTestResult({ id: 'spec1', timeSpentMs: 0 })], + mutantCoverage: { static: { 1: 1 }, perTest: {} }, + }); + + // Act + const result = act(dryRunResult, mutants); + + // Assert + const expected: MutantTestCoverage[] = [{ mutant, estimatedNetTime: 0, testFilter: undefined, coveredByTests: true }]; + expect(result).deep.eq(expected); + }); + + it('should calculate estimatedNetTime as the sum of all tests', () => { + // Arrange + const mutant = factory.mutant({ id: 1 }); + const mutants = [mutant]; + const dryRunResult = factory.completeDryRunResult({ + tests: [factory.successTestResult({ id: 'spec1', timeSpentMs: 20 }), factory.successTestResult({ id: 'spec1', timeSpentMs: 22 })], + mutantCoverage: { static: { 1: 1 }, perTest: {} }, + }); + + // Act + const result = act(dryRunResult, mutants); + + // Assert + expect(result[0].estimatedNetTime).eq(42); + }); + + it('should report onAllMutantsMatchedWithTests with correct `runAllTests` value', () => { + // Arrange + const mutants = [factory.mutant({ id: 1 }), factory.mutant({ id: 2 })]; + const dryRunResult = factory.completeDryRunResult({ + tests: [factory.successTestResult()], + mutantCoverage: { static: { 1: 1 }, perTest: {} }, + }); + + // Act + act(dryRunResult, mutants); + + // Assert + const expectedFirstMatch: Partial = { + id: '1', + runAllTests: true, + testFilter: undefined, + }; + const expectedSecondMatch: Partial = { + id: '2', + runAllTests: false, + testFilter: undefined, + }; + expect(reporterMock.onAllMutantsMatchedWithTests).calledWithMatch([sinon.match(expectedFirstMatch), sinon.match(expectedSecondMatch)]); + }); + }); + + describe('with perTest coverage', () => { + it('should enable test filtering for covered tests', () => { + // Arrange + const mutant1 = factory.mutant({ id: 1 }); + const mutant2 = factory.mutant({ id: 2 }); + const mutants = [mutant1, mutant2]; + const dryRunResult = factory.completeDryRunResult({ + tests: [factory.successTestResult({ id: 'spec1', timeSpentMs: 0 }), factory.successTestResult({ id: 'spec2', timeSpentMs: 0 })], + mutantCoverage: { static: { 1: 0 }, perTest: { spec1: { 1: 1 }, spec2: { 1: 0, 2: 1 } } }, + }); + + // Act + const result = act(dryRunResult, mutants); + + // Assert + const expected: MutantTestCoverage[] = [ + { mutant: mutant1, estimatedNetTime: 0, testFilter: ['spec1'], coveredByTests: true }, + { mutant: mutant2, estimatedNetTime: 0, testFilter: ['spec2'], coveredByTests: true }, + ]; + expect(result).deep.eq(expected); + }); + + it('should calculate estimatedNetTime as the sum of covered tests', () => { + // Arrange + const mutant1 = factory.mutant({ id: 1 }); + const mutant2 = factory.mutant({ id: 2 }); + const mutants = [mutant1, mutant2]; + const dryRunResult = factory.completeDryRunResult({ + tests: [ + factory.successTestResult({ id: 'spec1', timeSpentMs: 20 }), + factory.successTestResult({ id: 'spec2', timeSpentMs: 10 }), + factory.successTestResult({ id: 'spec3', timeSpentMs: 22 }), + ], + mutantCoverage: { static: { 1: 0 }, perTest: { spec1: { 1: 1 }, spec2: { 1: 0, 2: 1 }, spec3: { 1: 2 } } }, + }); + + // Act + const actualMatches = act(dryRunResult, mutants); + + // Assert + expect(actualMatches.find((mutant) => mutant.mutant.id === 1)?.estimatedNetTime).eq(42); // spec1 + spec3 + expect(actualMatches.find((mutant) => mutant.mutant.id === 2)?.estimatedNetTime).eq(10); // spec2 + }); + + it('should report onAllMutantsMatchedWithTests with correct `testFilter` value', () => { + // Arrange + const mutants = [factory.mutant({ id: 1 }), factory.mutant({ id: 2 })]; + const dryRunResult = factory.completeDryRunResult({ + tests: [factory.successTestResult({ id: 'spec1', timeSpentMs: 0 }), factory.successTestResult({ id: 'spec2', timeSpentMs: 0 })], + mutantCoverage: { static: { 1: 0 }, perTest: { spec1: { 1: 1 }, spec2: { 1: 0, 2: 1 } } }, + }); + + // Act + act(dryRunResult, mutants); + + // Assert + const expectedFirstMatch: Partial = { + id: '1', + runAllTests: false, + testFilter: ['spec1'], + }; + const expectedSecondMatch: Partial = { + id: '2', + runAllTests: false, + testFilter: ['spec2'], + }; + expect(reporterMock.onAllMutantsMatchedWithTests).calledWithMatch([sinon.match(expectedFirstMatch), sinon.match(expectedSecondMatch)]); + }); + + it('should allow for non-existing tests (#2485)', () => { + // Arrange + const mutant1 = factory.mutant({ id: 1 }); + const mutant2 = factory.mutant({ id: 2 }); + const mutants = [mutant1, mutant2]; + const dryRunResult = factory.completeDryRunResult({ + tests: [factory.successTestResult({ id: 'spec1', timeSpentMs: 20 })], // test result for spec2 is missing + mutantCoverage: { static: {}, perTest: { spec1: { 1: 1 }, spec2: { 1: 0, 2: 1 } } }, + }); + + // Act + const actualMatches = act(dryRunResult, mutants); + + // Assert + expect(actualMatches.find((mutant) => mutant.mutant.id === 1)?.testFilter).deep.eq(['spec1']); + expect(actualMatches.find((mutant) => mutant.mutant.id === 2)?.coveredByTests).deep.eq(false); + expect(testInjector.logger.debug).calledWith( + 'Found test with id "spec2" in coverage data, but not in the test results of the dry run. Not taking coverage data for this test into account' + ); + }); + }); +}); diff --git a/packages/core/test/unit/process/1-PrepareExecutor.spec.ts b/packages/core/test/unit/process/1-PrepareExecutor.spec.ts new file mode 100644 index 0000000000..1b06725530 --- /dev/null +++ b/packages/core/test/unit/process/1-PrepareExecutor.spec.ts @@ -0,0 +1,110 @@ +import { Injector } from 'typed-inject'; +import { expect } from 'chai'; +import { testInjector, factory } from '@stryker-mutator/test-helpers'; +import { PartialStrykerOptions, File, LogLevel } from '@stryker-mutator/api/core'; +import { commonTokens } from '@stryker-mutator/api/plugin'; + +import sinon = require('sinon'); + +import { PrepareExecutor } from '../../../src/process'; +import { coreTokens } from '../../../src/di'; +import { LogConfigurator, LoggingClientContext } from '../../../src/logging'; +import * as buildMainInjectorModule from '../../../src/di/buildMainInjector'; +import Timer from '../../../src/utils/Timer'; +import InputFileResolver from '../../../src/input/InputFileResolver'; +import InputFileCollection from '../../../src/input/InputFileCollection'; + +import { TemporaryDirectory } from '../../../src/utils/TemporaryDirectory'; +import { ConfigError } from '../../../src/errors'; + +describe(PrepareExecutor.name, () => { + let cliOptions: PartialStrykerOptions; + let configureMainProcessStub: sinon.SinonStub; + let configureLoggingServerStub: sinon.SinonStub; + let injectorMock: sinon.SinonStubbedInstance; + let timerMock: sinon.SinonStubbedInstance; + let inputFileResolverMock: sinon.SinonStubbedInstance; + let inputFiles: InputFileCollection; + let temporaryDirectoryMock: sinon.SinonStubbedInstance; + let sut: PrepareExecutor; + + beforeEach(() => { + inputFiles = new InputFileCollection([new File('index.js', 'console.log("hello world");')], ['index.js']); + cliOptions = {}; + timerMock = sinon.createStubInstance(Timer); + temporaryDirectoryMock = sinon.createStubInstance(TemporaryDirectory); + inputFileResolverMock = sinon.createStubInstance(InputFileResolver); + configureMainProcessStub = sinon.stub(LogConfigurator, 'configureMainProcess'); + configureLoggingServerStub = sinon.stub(LogConfigurator, 'configureLoggingServer'); + injectorMock = factory.injector(); + sinon.stub(buildMainInjectorModule, 'buildMainInjector').returns(injectorMock); + injectorMock.resolve + .withArgs(commonTokens.options) + .returns(testInjector.options) + .withArgs(coreTokens.timer) + .returns(timerMock) + .withArgs(coreTokens.temporaryDirectory) + .returns(temporaryDirectoryMock); + injectorMock.injectClass.withArgs(InputFileResolver).returns(inputFileResolverMock); + inputFileResolverMock.resolve.returns(inputFiles); + sut = new PrepareExecutor(cliOptions, injectorMock); + }); + + it('should configure logging for the main process', async () => { + await sut.execute(); + expect(configureMainProcessStub).calledOnce; + }); + + it('should configure the logging server', async () => { + const expectedLoggingContext: LoggingClientContext = { + level: LogLevel.Fatal, + port: 1337, + }; + configureLoggingServerStub.resolves(expectedLoggingContext); + testInjector.options.logLevel = LogLevel.Information; + testInjector.options.fileLogLevel = LogLevel.Trace; + testInjector.options.allowConsoleColors = true; + await sut.execute(); + expect(configureLoggingServerStub).calledWithExactly(LogLevel.Information, LogLevel.Trace, true); + expect(injectorMock.provideValue).calledWithExactly(coreTokens.loggingContext, expectedLoggingContext); + }); + + it('should build the main injector', async () => { + await sut.execute(); + expect(buildMainInjectorModule.buildMainInjector).calledWith(injectorMock); + }); + + it('should reset the timer', async () => { + await sut.execute(); + expect(timerMock.reset).calledOnce; + }); + + it('should resolve input files', async () => { + await sut.execute(); + expect(inputFileResolverMock.resolve).called; + expect(injectorMock.provideValue).calledWithExactly(coreTokens.inputFiles, inputFiles); + }); + + it('should reject when logging server rejects', async () => { + const expectedError = Error('expected error'); + configureLoggingServerStub.rejects(expectedError); + await expect(sut.execute()).rejectedWith(expectedError); + }); + + it('should reject when input file globbing results in a rejection', async () => { + const expectedError = Error('expected error'); + inputFileResolverMock.resolve.rejects(expectedError); + await expect(sut.execute()).rejectedWith(expectedError); + }); + + it('should reject when no input files where found', async () => { + inputFileResolverMock.resolve.resolves(new InputFileCollection([], [])); + await expect(sut.execute()).rejectedWith(ConfigError, 'No input files found'); + }); + + it('should not create the temp directory when no input files where found', async () => { + inputFileResolverMock.resolve.resolves(new InputFileCollection([], [])); + await expect(sut.execute()).rejected; + expect(temporaryDirectoryMock.initialize).not.called; + }); +}); diff --git a/packages/core/test/unit/process/2-MutantInstrumenterExecutor.spec.ts b/packages/core/test/unit/process/2-MutantInstrumenterExecutor.spec.ts new file mode 100644 index 0000000000..0bf74e6078 --- /dev/null +++ b/packages/core/test/unit/process/2-MutantInstrumenterExecutor.spec.ts @@ -0,0 +1,113 @@ +import sinon = require('sinon'); +import { expect } from 'chai'; +import { File } from '@stryker-mutator/api/core'; +import { Injector } from 'typed-inject'; +import { factory, testInjector } from '@stryker-mutator/test-helpers'; +import { Instrumenter, InstrumentResult, InstrumenterOptions } from '@stryker-mutator/instrumenter'; +import { Checker } from '@stryker-mutator/api/check'; + +import { MutantInstrumenterExecutor } from '../../../src/process'; +import InputFileCollection from '../../../src/input/InputFileCollection'; +import { coreTokens } from '../../../src/di'; +import { createConcurrencyTokenProviderMock, createCheckerPoolMock, PoolMock, ConcurrencyTokenProviderMock } from '../../helpers/producers'; +import { createCheckerFactory } from '../../../src/checker/CheckerFacade'; +import { createPreprocessor, FilePreprocessor, Sandbox } from '../../../src/sandbox'; + +describe(MutantInstrumenterExecutor.name, () => { + let sut: MutantInstrumenterExecutor; + let inputFiles: InputFileCollection; + let injectorMock: sinon.SinonStubbedInstance; + let instrumenterMock: sinon.SinonStubbedInstance; + let sandboxFilePreprocessorMock: sinon.SinonStubbedInstance; + let instrumentResult: InstrumentResult; + let sandboxMock: sinon.SinonStubbedInstance; + let checkerPoolMock: PoolMock; + let concurrencyTokenProviderMock: ConcurrencyTokenProviderMock; + let mutatedFile: File; + let originalFile: File; + let testFile: File; + + beforeEach(() => { + mutatedFile = new File('foo.js', 'console.log(global.activeMutant === 1? "": "bar")'); + originalFile = new File('foo.js', 'console.log("bar")'); + testFile = new File('foo.spec.js', ''); + concurrencyTokenProviderMock = createConcurrencyTokenProviderMock(); + checkerPoolMock = createCheckerPoolMock(); + + instrumentResult = { + files: [mutatedFile], + mutants: [factory.mutant({ id: 1, replacement: 'bar' })], + }; + sandboxMock = sinon.createStubInstance(Sandbox); + instrumenterMock = sinon.createStubInstance(Instrumenter); + sandboxFilePreprocessorMock = { + preprocess: sinon.stub(), + }; + sandboxFilePreprocessorMock.preprocess.resolves([mutatedFile, testFile]); + inputFiles = new InputFileCollection([originalFile, testFile], [mutatedFile.name]); + injectorMock = factory.injector(); + sut = new MutantInstrumenterExecutor(injectorMock, inputFiles, testInjector.options); + injectorMock.injectClass.withArgs(Instrumenter).returns(instrumenterMock); + injectorMock.injectFunction.withArgs(createPreprocessor).returns(sandboxFilePreprocessorMock); + injectorMock.injectFunction.withArgs(Sandbox.create).returns(sandboxMock); + injectorMock.resolve + .withArgs(coreTokens.concurrencyTokenProvider) + .returns(concurrencyTokenProviderMock) + .withArgs(coreTokens.checkerPool) + .returns(checkerPoolMock); + instrumenterMock.instrument.resolves(instrumentResult); + }); + + it('should instrument the given files', async () => { + testInjector.options.mutator.plugins = ['functionSent']; + testInjector.options.mutator.excludedMutations = ['fooMutator']; + await sut.execute(); + const expectedInstrumenterOptions: InstrumenterOptions = testInjector.options.mutator; + expect(instrumenterMock.instrument).calledOnceWithExactly([originalFile], expectedInstrumenterOptions); + }); + + it('result in the new injector', async () => { + const result = await sut.execute(); + expect(result).eq(injectorMock); + }); + + it('should preprocess files before initializing the sandbox', async () => { + await sut.execute(); + expect(sandboxFilePreprocessorMock.preprocess).calledWithExactly([mutatedFile, testFile]); + expect(sandboxFilePreprocessorMock.preprocess).calledBefore(injectorMock.injectFunction); + }); + + it('should provide the mutated files to the sandbox', async () => { + await sut.execute(); + expect(injectorMock.provideValue).calledWithExactly(coreTokens.files, [mutatedFile, testFile]); + expect(injectorMock.provideValue.withArgs(coreTokens.files)).calledBefore(injectorMock.injectFunction); + }); + + it('should provide checkerToken$ to the checker pool', async () => { + concurrencyTokenProviderMock.checkerToken$.next(0); + concurrencyTokenProviderMock.checkerToken$.next(1); + await sut.execute(); + expect(injectorMock.provideValue).calledWith(coreTokens.checkerConcurrencyTokens, concurrencyTokenProviderMock.checkerToken$); + }); + + it('should provide the checker factory to the checker pool', async () => { + await sut.execute(); + expect(injectorMock.provideFactory).calledWith(coreTokens.checkerFactory, createCheckerFactory); + }); + + it('should initialize the CheckerPool before creating the sandbox', async () => { + // This is important for in-place mutation. We need to initialize the typescript checker(s) before we write mutated files to disk. + await sut.execute(); + expect(checkerPoolMock.init).calledBefore(injectorMock.injectFunction.withArgs(Sandbox.create)); + }); + + it('should provide mutants in the result', async () => { + await sut.execute(); + expect(injectorMock.provideValue).calledWithExactly(coreTokens.mutants, instrumentResult.mutants); + }); + + it('should provide the sandbox in the result', async () => { + await sut.execute(); + expect(injectorMock.provideValue).calledWithExactly(coreTokens.sandbox, sandboxMock); + }); +}); diff --git a/packages/core/test/unit/process/3-DryRunExecutor.spec.ts b/packages/core/test/unit/process/3-DryRunExecutor.spec.ts new file mode 100644 index 0000000000..a3a5a8ed7b --- /dev/null +++ b/packages/core/test/unit/process/3-DryRunExecutor.spec.ts @@ -0,0 +1,172 @@ +import { EOL } from 'os'; + +import { Injector } from 'typed-inject'; +import { factory, testInjector } from '@stryker-mutator/test-helpers'; +import sinon = require('sinon'); +import { TestRunner, CompleteDryRunResult, ErrorDryRunResult, TimeoutDryRunResult } from '@stryker-mutator/api/test_runner'; +import { expect } from 'chai'; + +import Timer from '../../../src/utils/Timer'; +import { DryRunExecutor } from '../../../src/process'; +import { coreTokens } from '../../../src/di'; +import { ConfigError } from '../../../src/errors'; +import { ConcurrencyTokenProvider } from '../../../src/concurrent'; +import { createTestRunnerPoolMock, PoolMock } from '../../helpers/producers'; + +describe(DryRunExecutor.name, () => { + let injectorMock: sinon.SinonStubbedInstance; + let testRunnerPoolMock: PoolMock; + let sut: DryRunExecutor; + let timerMock: sinon.SinonStubbedInstance; + let testRunnerMock: sinon.SinonStubbedInstance>; + let concurrencyTokenProviderMock: sinon.SinonStubbedInstance; + + beforeEach(() => { + timerMock = sinon.createStubInstance(Timer); + testRunnerMock = factory.testRunner(); + testRunnerPoolMock = createTestRunnerPoolMock(); + testRunnerPoolMock.worker$.next(testRunnerMock); + concurrencyTokenProviderMock = sinon.createStubInstance(ConcurrencyTokenProvider); + injectorMock = factory.injector(); + injectorMock.resolve.withArgs(coreTokens.testRunnerPool).returns(testRunnerPoolMock); + sut = new DryRunExecutor(injectorMock, testInjector.logger, testInjector.options, timerMock, concurrencyTokenProviderMock); + }); + + it('should pass through any rejections', async () => { + const expectedError = new Error('expected error'); + testRunnerMock.dryRun.rejects(expectedError); + await expect(sut.execute()).rejectedWith(expectedError); + }); + + describe('when the dryRun completes', () => { + let runResult: CompleteDryRunResult; + + beforeEach(() => { + runResult = factory.completeDryRunResult(); + testRunnerMock.dryRun.resolves(runResult); + }); + + it('should log about that this might take a while', async () => { + runResult.tests.push(factory.successTestResult()); + await sut.execute(); + expect(testInjector.logger.info).calledWith('Starting initial test run. This may take a while.'); + }); + + describe('with successful tests', () => { + it('should calculate the overhead time milliseconds', async () => { + // Arrange + runResult.tests.push(factory.successTestResult({ timeSpentMs: 10 })); + runResult.tests.push(factory.successTestResult({ timeSpentMs: 2 })); + runResult.tests.push(factory.successTestResult({ timeSpentMs: 6 })); + const expectedOverHeadTimeMs = 82; + timerMock.elapsedMs.returns(100); + + // Act + const actualResultInjector = await sut.execute(); + + // Assert + expect(timerMock.mark).calledWith('Initial test run'); + expect(timerMock.elapsedMs).calledWith('Initial test run'); + expect(timerMock.mark).calledBefore(timerMock.elapsedMs); + expect(actualResultInjector.provideValue).calledWithExactly(coreTokens.timeOverheadMS, expectedOverHeadTimeMs); + }); + + it('should never calculate a negative overhead time', async () => { + runResult.tests.push(factory.successTestResult({ timeSpentMs: 10 })); + timerMock.elapsedMs.returns(9); + const injector = await sut.execute(); + expect(injector.provideValue).calledWithExactly(coreTokens.timeOverheadMS, 0); + }); + + it('should provide the result', async () => { + timerMock.elapsedMs.returns(42); + runResult.tests.push(factory.successTestResult()); + runResult.mutantCoverage = { + perTest: {}, + static: {}, + }; + const actualInjector = await sut.execute(); + expect(actualInjector.provideValue).calledWithExactly(coreTokens.dryRunResult, runResult); + }); + + it('should have logged the amount of tests ran', async () => { + runResult.tests.push(factory.successTestResult({ timeSpentMs: 10 })); + runResult.tests.push(factory.successTestResult({ timeSpentMs: 10 })); + timerMock.humanReadableElapsed.returns('30 seconds'); + timerMock.humanReadableElapsed.withArgs('Initial test run').returns('2 seconds'); + timerMock.elapsedMs.returns(30000); + timerMock.elapsedMs.withArgs('Initial test run').returns(2000); + + await sut.execute(); + + expect(testInjector.logger.info).to.have.been.calledWith( + 'Initial test run succeeded. Ran %s tests in %s (net %s ms, overhead %s ms).', + 2, + '2 seconds', + 20, + 1980 + ); + }); + + it('should log when there were no tests', async () => { + await expect(sut.execute()).rejectedWith( + ConfigError, + 'No tests were executed. Stryker will exit prematurely. Please check your configuration.' + ); + }); + }); + describe('with failed tests', () => { + beforeEach(() => { + runResult.tests.push(factory.failedTestResult({ name: 'foo is bar', failureMessage: 'foo was baz' })); + runResult.tests.push(factory.failedTestResult({ name: 'bar is baz', failureMessage: 'bar was qux' })); + }); + + it('should have logged the errors', async () => { + await expect(sut.execute()).rejected; + expect(testInjector.logger.error).calledWith( + `One or more tests failed in the initial test run:${EOL}\tfoo is bar${EOL}\t\tfoo was baz${EOL}\tbar is baz${EOL}\t\tbar was qux` + ); + }); + + it('should reject with correct message', async () => { + await expect(sut.execute()).rejectedWith(ConfigError, 'There were failed tests in the initial test run.'); + }); + }); + }); + + describe('when dryRun errors', () => { + let runResult: ErrorDryRunResult; + + beforeEach(() => { + runResult = factory.errorDryRunResult(); + testRunnerMock.dryRun.resolves(runResult); + }); + + it('should have logged the errors', async () => { + runResult.errorMessage = 'cannot call foo() on undefined'; + await expect(sut.execute()).rejected; + expect(testInjector.logger.error).calledWith(`One or more tests resulted in an error:${EOL}\tcannot call foo() on undefined`); + }); + it('should reject with correct message', async () => { + await expect(sut.execute()).rejectedWith('Something went wrong in the initial test run'); + }); + }); + + describe('when dryRun timedOut', () => { + let runResult: TimeoutDryRunResult; + + beforeEach(() => { + runResult = factory.timeoutDryRunResult(); + testRunnerMock.dryRun.resolves(runResult); + }); + + it('should have logged the timeout', async () => { + await expect(sut.execute()).rejected; + expect(testInjector.logger.error).calledWith('Initial test run timed out!'); + }); + + it('should reject with correct message', async () => { + await expect(sut.execute()).rejectedWith('Something went wrong in the initial test run'); + }); + }); +}); diff --git a/packages/core/test/unit/process/4-MutationTestExecutor.spec.ts b/packages/core/test/unit/process/4-MutationTestExecutor.spec.ts new file mode 100644 index 0000000000..7d2ac0c671 --- /dev/null +++ b/packages/core/test/unit/process/4-MutationTestExecutor.spec.ts @@ -0,0 +1,323 @@ +import sinon = require('sinon'); +import { expect } from 'chai'; +import { testInjector, factory, tick } from '@stryker-mutator/test-helpers'; +import { Reporter } from '@stryker-mutator/api/report'; +import { TestRunner, MutantRunStatus, MutantRunOptions, MutantRunResult } from '@stryker-mutator/api/test_runner'; +import { Checker, CheckStatus, CheckResult } from '@stryker-mutator/api/check'; +import { Task } from '@stryker-mutator/util'; + +import { MutationTestExecutor } from '../../../src/process'; +import { coreTokens } from '../../../src/di'; +import { createTestRunnerPoolMock, createMutantTestCoverage, PoolMock, createCheckerPoolMock } from '../../helpers/producers'; +import { MutantTestCoverage } from '../../../src/mutants/findMutantTestCoverage'; +import { MutationTestReportHelper } from '../../../src/reporters/MutationTestReportHelper'; +import Timer from '../../../src/utils/Timer'; +import { ConcurrencyTokenProvider } from '../../../src/concurrent'; +import { Sandbox } from '../../../src/sandbox'; + +describe(MutationTestExecutor.name, () => { + let reporterMock: Required; + let testRunnerPoolMock: PoolMock; + let checkerPoolMock: PoolMock; + let sut: MutationTestExecutor; + let mutants: MutantTestCoverage[]; + let checker1: sinon.SinonStubbedInstance; + let checker2: sinon.SinonStubbedInstance; + let mutationTestReportCalculatorMock: sinon.SinonStubbedInstance; + let timerMock: sinon.SinonStubbedInstance; + let testRunner1: sinon.SinonStubbedInstance>; + let testRunner2: sinon.SinonStubbedInstance>; + let concurrencyTokenProviderMock: sinon.SinonStubbedInstance; + let sandboxMock: sinon.SinonStubbedInstance; + + beforeEach(() => { + reporterMock = factory.reporter(); + mutationTestReportCalculatorMock = sinon.createStubInstance(MutationTestReportHelper); + timerMock = sinon.createStubInstance(Timer); + testRunner1 = factory.testRunner(); + testRunner2 = factory.testRunner(); + testRunnerPoolMock = createTestRunnerPoolMock(); + checkerPoolMock = createCheckerPoolMock(); + checker1 = factory.checker(); + checker2 = factory.checker(); + concurrencyTokenProviderMock = sinon.createStubInstance(ConcurrencyTokenProvider); + sandboxMock = sinon.createStubInstance(Sandbox); + + mutants = []; + sut = testInjector.injector + .provideValue(coreTokens.reporter, reporterMock) + .provideValue(coreTokens.checkerPool, checkerPoolMock) + .provideValue(coreTokens.testRunnerPool, testRunnerPoolMock) + .provideValue(coreTokens.timeOverheadMS, 42) + .provideValue(coreTokens.mutantsWithTestCoverage, mutants) + .provideValue(coreTokens.mutationTestReportHelper, mutationTestReportCalculatorMock) + .provideValue(coreTokens.sandbox, sandboxMock) + .provideValue(coreTokens.timer, timerMock) + .provideValue(coreTokens.testRunnerPool, testRunnerPoolMock) + .provideValue(coreTokens.concurrencyTokenProvider, concurrencyTokenProviderMock) + .injectClass(MutationTestExecutor); + }); + + function arrangePools() { + arrangeTestRunners(); + arrangeCheckers(); + } + + function arrangeTestRunners() { + testRunnerPoolMock.worker$.next(testRunner1); + testRunnerPoolMock.worker$.next(testRunner2); + testRunner1.mutantRun.resolves(factory.survivedMutantRunResult()); + testRunner2.mutantRun.resolves(factory.survivedMutantRunResult()); + } + + function arrangeCheckers() { + checkerPoolMock.worker$.next(checker1); + checkerPoolMock.worker$.next(checker2); + checker1.check.resolves(factory.checkResult()); + checker2.check.resolves(factory.checkResult()); + } + + it('should run the mutants in the test runners from the test runner pool', async () => { + // Arrange + arrangePools(); + const mutant1 = factory.mutant({ id: 1 }); + const mutant2 = factory.mutant({ id: 2 }); + mutants.push(createMutantTestCoverage({ mutant: mutant1 })); + mutants.push(createMutantTestCoverage({ mutant: mutant2 })); + + // Act + await sut.execute(); + + // Assert + expect(testRunner1.mutantRun).calledOnce; + expect(testRunner1.mutantRun).calledWithMatch({ activeMutant: mutant1 }); + expect(testRunner2.mutantRun).calledOnce; + expect(testRunner2.mutantRun).calledWithMatch({ activeMutant: mutant2 }); + }); + + it('should short circuit ignored mutants (not check them or run them)', async () => { + // Arrange + arrangePools(); + mutants.push(createMutantTestCoverage({ mutant: factory.mutant({ id: 1, ignoreReason: '1 is ignored' }) })); + mutants.push(createMutantTestCoverage({ mutant: factory.mutant({ id: 2, ignoreReason: '2 is ignored' }) })); + + // Act + const actualResults = await sut.execute(); + + // Assert + expect(testRunner1.mutantRun).not.called; + expect(checker1.check).not.called; + expect(testRunner2.mutantRun).not.called; + expect(checker2.check).not.called; + expect(actualResults).lengthOf(2); + }); + + it('should check the mutants before running them', async () => { + // Arrange + arrangePools(); + const mutant1 = factory.mutant({ id: 1 }); + const mutant2 = factory.mutant({ id: 2 }); + mutants.push(createMutantTestCoverage({ mutant: mutant1 })); + mutants.push(createMutantTestCoverage({ mutant: mutant2 })); + + // Act + await sut.execute(); + + // Assert + expect(checker1.check).calledOnce; + expect(checker1.check).calledWithMatch(mutant1); + expect(checker2.check).calledOnce; + expect(checker2.check).calledWithMatch(mutant2); + }); + + it('should calculate timeout correctly', async () => { + // Arrange + arrangePools(); + mutants.push(createMutantTestCoverage({ mutant: factory.mutant({ id: 1 }), estimatedNetTime: 10 })); + testInjector.options.timeoutFactor = 1.5; + testInjector.options.timeoutMS = 27; + + // Act + await sut.execute(); + + // Assert + const expected: Partial = { timeout: 84 }; // 42 (overhead) + 10*1.5 + 27 + expect(testRunner1.mutantRun).calledWithMatch(expected); + }); + + it('should passthrough the test filter', async () => { + // Arrange + arrangePools(); + const expectedTestFilter = ['spec1', 'foo', 'bar']; + mutants.push(createMutantTestCoverage({ testFilter: expectedTestFilter })); + testInjector.options.timeoutFactor = 1.5; + testInjector.options.timeoutMS = 27; + + // Act + await sut.execute(); + + // Assert + const expected: Partial = { testFilter: expectedTestFilter }; + expect(testRunner1.mutantRun).calledWithMatch(expected); + }); + + it('should provide the sandboxFileName', async () => { + // Arrange + arrangePools(); + const expectedTestFilter = ['spec1', 'foo', 'bar']; + sandboxMock.sandboxFileFor.returns('.stryker-tmp/sandbox1234/src/foo.js'); + mutants.push(createMutantTestCoverage({ testFilter: expectedTestFilter, mutant: factory.mutant({ fileName: 'src/foo.js' }) })); + testInjector.options.timeoutFactor = 1.5; + testInjector.options.timeoutMS = 27; + + // Act + await sut.execute(); + + // Assert + const expected: Partial = { sandboxFileName: '.stryker-tmp/sandbox1234/src/foo.js' }; + expect(testRunner1.mutantRun).calledWithMatch(expected); + expect(sandboxMock.sandboxFileFor).calledWithExactly('src/foo.js'); + }); + + it('should recycle a test runner after it is done with it', async () => { + // Arrange + arrangeCheckers(); + testRunnerPoolMock.worker$.next(testRunner1); // schedule only one test runner + testRunnerPoolMock.recycle.callsFake((testRunner) => testRunnerPoolMock.worker$.next(testRunner)); + const mutant1 = factory.mutant({ id: 1 }); + const mutant2 = factory.mutant({ id: 2 }); + mutants.push(createMutantTestCoverage({ mutant: mutant1 })); + mutants.push(createMutantTestCoverage({ mutant: mutant2 })); + testRunner1.mutantRun.resolves(factory.survivedMutantRunResult()); + + // Act + await sut.execute(); + + // Assert + expect(testRunner1.mutantRun).calledTwice; + expect(testRunner1.mutantRun).calledWithMatch({ activeMutant: mutant1 }); + expect(testRunner1.mutantRun).calledWithMatch({ activeMutant: mutant2 }); + expect(testRunner2.mutantRun).not.called; + }); + + it('should recycle a checker after it is done with it', async () => { + // Arrange + arrangeTestRunners(); + checkerPoolMock.worker$.next(checker1); // schedule only one + checkerPoolMock.recycle.callsFake((testRunner) => checkerPoolMock.worker$.next(testRunner)); + const mutant1 = factory.mutant({ id: 1 }); + const mutant2 = factory.mutant({ id: 2 }); + mutants.push(createMutantTestCoverage({ mutant: mutant1 })); + mutants.push(createMutantTestCoverage({ mutant: mutant2 })); + checker1.check.resolves(factory.checkResult()); + + // Act + await sut.execute(); + + // Assert + expect(checker1.check).calledTwice; + expect(checker1.check).calledWithMatch(mutant1); + expect(checker1.check).calledWithMatch(mutant2); + expect(checker2.check).not.called; + }); + + it('should not run mutants that are uncovered by tests', async () => { + // Arrange + arrangePools(); + const mutant1 = factory.mutant({ id: 1 }); + mutants.push(createMutantTestCoverage({ mutant: mutant1, coveredByTests: false })); + + // Act + await sut.execute(); + + // Assert + expect(testRunner1.mutantRun).not.called; + }); + + it('should report an ignored mutant as `Ignored`', async () => { + // Arrange + const mutant = factory.mutant({ id: 1, ignoreReason: '1 is ignored' }); + mutants.push(createMutantTestCoverage({ mutant, coveredByTests: false })); + + // Act + await sut.execute(); + + // Assert + expect(mutationTestReportCalculatorMock.reportMutantIgnored).calledWithExactly(mutant); + }); + + it('should report an uncovered mutant with `NoCoverage`', async () => { + // Arrange + arrangePools(); + const mutant = factory.mutant({ id: 1 }); + mutants.push(createMutantTestCoverage({ mutant: factory.mutant({ id: 1 }), coveredByTests: false })); + + // Act + await sut.execute(); + + // Assert + expect(mutationTestReportCalculatorMock.reportNoCoverage).calledWithExactly(mutant); + }); + + it('should report non-passed check results as "checkFailed"', async () => { + // Arrange + checkerPoolMock.worker$.next(checker1); + const mutant = factory.mutant({ id: 1 }); + const failedCheckResult = factory.checkResult({ reason: 'Cannot find foo() of `undefined`', status: CheckStatus.CompileError }); + checker1.check.resolves(failedCheckResult); + mutants.push(createMutantTestCoverage({ mutant })); + + // Act + await sut.execute(); + + // Assert + expect(mutationTestReportCalculatorMock.reportCheckFailed).calledWithExactly(mutant, failedCheckResult); + }); + + it('should free checker resources after checking stage is complete', async () => { + // Arrange + checkerPoolMock.worker$.next(checker1); + testRunnerPoolMock.worker$.next(testRunner1); + mutants.push(createMutantTestCoverage({ mutant: factory.mutant({ id: 1 }) })); + const checkTask = new Task(); + const testRunnerTask = new Task(); + testRunner1.mutantRun.returns(testRunnerTask.promise); + checker1.check.returns(checkTask.promise); + + // Act & assert + const executePromise = sut.execute(); + checkTask.resolve(factory.checkResult()); + await tick(2); + expect(checkerPoolMock.dispose).called; + expect(concurrencyTokenProviderMock.freeCheckers).called; + testRunnerTask.resolve(factory.killedMutantRunResult()); + await executePromise; + }); + + it('should report mutant run results', async () => { + // Arrange + arrangeCheckers(); + testRunnerPoolMock.worker$.next(testRunner1); + const mutant = createMutantTestCoverage(); + const mutantRunResult = factory.killedMutantRunResult({ status: MutantRunStatus.Killed }); + mutants.push(mutant); + testRunner1.mutantRun.resolves(mutantRunResult); + + // Act + await sut.execute(); + + // Assert + expect(mutationTestReportCalculatorMock.reportMutantRunResult).calledWithExactly(mutant, mutantRunResult); + }); + + it('should log a done message when it is done', async () => { + // Arrange + timerMock.humanReadableElapsed.returns('2 seconds, tops!'); + + // Act + await sut.execute(); + + // Assert + expect(testInjector.logger.info).calledWithExactly('Done in %s.', '2 seconds, tops!'); + }); +}); diff --git a/packages/core/test/unit/process/InitialTestExecutor.spec.ts b/packages/core/test/unit/process/InitialTestExecutor.spec.ts deleted file mode 100644 index c9edf2db2b..0000000000 --- a/packages/core/test/unit/process/InitialTestExecutor.spec.ts +++ /dev/null @@ -1,279 +0,0 @@ -import { EOL } from 'os'; - -import { File, LogLevel } from '@stryker-mutator/api/core'; -import { commonTokens } from '@stryker-mutator/api/plugin'; -import { TestFramework } from '@stryker-mutator/api/test_framework'; -import { RunResult, RunStatus, TestStatus } from '@stryker-mutator/api/test_runner'; -import { Transpiler } from '@stryker-mutator/api/transpile'; -import { testInjector } from '@stryker-mutator/test-helpers'; -import { runResult, testFramework, testResult, transpiler } from '@stryker-mutator/test-helpers/src/factory'; -import { expect } from 'chai'; -import * as sinon from 'sinon'; - -import { coreTokens } from '../../../src/di'; -import InputFileCollection from '../../../src/input/InputFileCollection'; -import LoggingClientContext from '../../../src/logging/LoggingClientContext'; -import InitialTestExecutor, { InitialTestRunResult } from '../../../src/process/InitialTestExecutor'; -import Sandbox from '../../../src/Sandbox'; -import * as coverageHooks from '../../../src/transpiler/coverageHooks'; -import CoverageInstrumenterTranspiler, * as coverageInstrumenterTranspiler from '../../../src/transpiler/CoverageInstrumenterTranspiler'; -import SourceMapper, { PassThroughSourceMapper } from '../../../src/transpiler/SourceMapper'; -import { TemporaryDirectory } from '../../../src/utils/TemporaryDirectory'; -import Timer from '../../../src/utils/Timer'; -import * as producers from '../../helpers/producers'; -import { coverageMaps, Mock } from '../../helpers/producers'; - -const EXPECTED_INITIAL_TIMEOUT = 60 * 1000 * 5; -const LOGGING_CONTEXT: LoggingClientContext = Object.freeze({ - level: LogLevel.Fatal, - port: 4200, -}); - -describe('InitialTestExecutor run', () => { - let strykerSandboxMock: producers.Mock; - let sut: InitialTestExecutor; - let testFrameworkMock: TestFramework | null; - let coverageInstrumenterTranspilerMock: producers.Mock; - let transpilerMock: producers.Mock; - let transpiledFiles: File[]; - let coverageAnnotatedFiles: File[]; - let sourceMapperMock: producers.Mock; - let expectedRunResult: RunResult; - let inputFiles: InputFileCollection; - let timerMock: sinon.SinonStubbedInstance; - let temporaryDirectoryMock: Mock; - - function createSut() { - temporaryDirectoryMock = producers.mock(TemporaryDirectory); - - return testInjector.injector - .provideValue(coreTokens.inputFiles, inputFiles) - .provideValue(coreTokens.loggingContext, LOGGING_CONTEXT) - .provideValue(coreTokens.testFramework, testFrameworkMock) - .provideValue(coreTokens.transpiler, transpilerMock as Transpiler) - .provideValue(coreTokens.timer, (timerMock as unknown) as Timer) - .provideValue(coreTokens.temporaryDirectory, (temporaryDirectoryMock as unknown) as TemporaryDirectory) - .injectClass(InitialTestExecutor); - } - - beforeEach(() => { - timerMock = sinon.createStubInstance(Timer); - strykerSandboxMock = producers.mock(Sandbox as any); - transpilerMock = transpiler(); - coverageInstrumenterTranspilerMock = producers.mock(CoverageInstrumenterTranspiler); - sinon.stub(Sandbox, 'create').resolves(strykerSandboxMock); - sinon.stub(coverageInstrumenterTranspiler, 'default').returns(coverageInstrumenterTranspilerMock); - sourceMapperMock = producers.mock(PassThroughSourceMapper); - sinon.stub(SourceMapper, 'create').returns(sourceMapperMock); - testFrameworkMock = testFramework(); - coverageAnnotatedFiles = [new File('cov-annotated-transpiled-file-1.js', ''), new File('cov-annotated-transpiled-file-2.js', '')]; - transpiledFiles = [new File('transpiled-file-1.js', ''), new File('transpiled-file-2.js', '')]; - coverageInstrumenterTranspilerMock.transpile.returns(coverageAnnotatedFiles); - transpilerMock.transpile.returns(transpiledFiles); - expectedRunResult = runResult(); - strykerSandboxMock.run.resolves(expectedRunResult); - }); - - describe('with input files', () => { - beforeEach(() => { - inputFiles = new InputFileCollection([new File('mutate.js', ''), new File('mutate.spec.js', '')], ['mutate.js']); - }); - - it('should create a sandbox with correct arguments', async () => { - sut = createSut(); - await sut.run(); - expect(Sandbox.create).calledWith(testInjector.injector.resolve(commonTokens.options), 0, coverageAnnotatedFiles, testFrameworkMock); - }); - - it('should initialize, run and dispose the sandbox', async () => { - sut = createSut(); - await sut.run(); - expect(strykerSandboxMock.run).to.have.been.calledWith(EXPECTED_INITIAL_TIMEOUT); - expect(strykerSandboxMock.dispose).to.have.been.called; - }); - - it('should calculate the overhead time milliseconds', async () => { - // Arrange - const expectedOverHeadTimeMs = 82; - expectedRunResult.tests[0].timeSpentMs = 10; - expectedRunResult.tests.push(testResult({ timeSpentMs: 2 })); - expectedRunResult.tests.push(testResult({ timeSpentMs: 6 })); - timerMock.elapsedMs.returns(100); - sut = createSut(); - - // Act - const { overheadTimeMS } = await sut.run(); - - // Assert - expect(timerMock.mark).calledWith('Initial test run'); - expect(timerMock.elapsedMs).calledWith('Initial test run'); - expect(timerMock.mark).calledBefore(timerMock.elapsedMs); - expect(overheadTimeMS).eq(expectedOverHeadTimeMs); - }); - - it('should never calculate a negative overhead time', async () => { - expectedRunResult.tests[0].timeSpentMs = 10; - timerMock.elapsedMs.returns(9); - sut = createSut(); - const { overheadTimeMS } = await sut.run(); - expect(overheadTimeMS).eq(0); - }); - - it('should pass through the result', async () => { - const coverageData = coverageMaps(); - coverageInstrumenterTranspilerMock.fileCoverageMaps = { someFile: coverageData } as any; - timerMock.elapsedMs.returns(42); - const expectedResult: InitialTestRunResult = { - coverageMaps: { - someFile: coverageData, - }, - overheadTimeMS: 42 - expectedRunResult.tests[0].timeSpentMs, - runResult: expectedRunResult, - sourceMapper: sourceMapperMock, - }; - sut = createSut(); - const actualRunResult = await sut.run(); - expect(actualRunResult).deep.eq(expectedResult); - }); - - it('should log the transpiled results if transpilers are specified', async () => { - testInjector.options.transpilers = ['a transpiler']; - testInjector.logger.isDebugEnabled.returns(true); - sut = createSut(); - await sut.run(); - const actualLogMessage: string = testInjector.logger.debug.getCall(0).args[0]; - const expectedLogMessage = `Transpiled files: ${JSON.stringify( - coverageAnnotatedFiles.map((_) => _.name), - null, - 2 - )}`; - expect(actualLogMessage).eq(expectedLogMessage); - }); - - it('should not log the transpiled results if transpilers are not specified', async () => { - testInjector.logger.isDebugEnabled.returns(true); - sut = createSut(); - await sut.run(); - expect(testInjector.logger.debug).not.calledWithMatch('Transpiled files'); - }); - - it('should have logged the amount of tests ran', async () => { - expectedRunResult.tests.push(testResult()); - timerMock.humanReadableElapsed.returns('2 seconds'); - timerMock.elapsedMs.returns(50); - sut = createSut(); - await sut.run(); - expect(testInjector.logger.info).to.have.been.calledWith( - 'Initial test run succeeded. Ran %s tests in %s (net %s ms, overhead %s ms).', - 2, - '2 seconds', - 20, - 30 - ); - }); - - it('should log when there were no tests', async () => { - while (expectedRunResult.tests.pop()); - sut = createSut(); - await sut.run(); - expect(testInjector.logger.warn).to.have.been.calledWith( - 'No tests were executed. Stryker will exit prematurely. Please check your configuration.' - ); - }); - - it('should pass through any rejections', async () => { - const expectedError = new Error('expected error'); - strykerSandboxMock.run.rejects(expectedError); - sut = createSut(); - await expect(sut.run()).rejectedWith(expectedError); - }); - - it('should create the coverage instrumenter transpiler with source-mapped files to mutate', async () => { - sourceMapperMock.transpiledFileNameFor.returns('mutate.min.js'); - sut = createSut(); - await sut.run(); - expect(coverageInstrumenterTranspiler.default).calledWithNew; - expect(coverageInstrumenterTranspiler.default).calledWith(testInjector.injector.resolve(commonTokens.options), ['mutate.min.js']); - expect(sourceMapperMock.transpiledFileNameFor).calledWith('mutate.js'); - }); - - it('should also add a collectCoveragePerTest file when coverage analysis is "perTest" and there is a testFramework', async () => { - testInjector.options.coverageAnalysis = 'perTest'; - sinon.stub(coverageHooks, 'coveragePerTestHooks').returns('test hook foobar'); - sut = createSut(); - await sut.run(); - expect(strykerSandboxMock.run).calledWith(EXPECTED_INITIAL_TIMEOUT, 'test hook foobar'); - }); - - it('should result log a warning if coverage analysis is "perTest" and there is no testFramework', async () => { - testInjector.options.coverageAnalysis = 'perTest'; - testFrameworkMock = null; - sut = createSut(); - sinon.stub(coverageHooks, 'coveragePerTestHooks').returns('test hook foobar'); - sut = createSut(); - await sut.run(); - expect(testInjector.logger.warn).calledWith( - 'Cannot measure coverage results per test, there is no testFramework and thus no way of executing code right before and after each test.' - ); - }); - - describe('and run has test failures', () => { - beforeEach(() => { - expectedRunResult.tests = [ - testResult({ name: 'foobar test' }), - testResult({ name: 'example test', status: TestStatus.Failed, failureMessages: ['expected error'] }), - testResult({ name: '2nd example test', status: TestStatus.Failed }), - ]; - }); - - it('should have logged the errors', async () => { - sut = createSut(); - await expect(sut.run()).rejected; - expect(testInjector.logger.error).calledWith( - `One or more tests failed in the initial test run:${EOL}\texample test${EOL}\t\texpected error${EOL}\t2nd example test` - ); - }); - it('should reject with correct message', async () => { - sut = createSut(); - await expect(sut.run()).rejectedWith('There were failed tests in the initial test run.'); - }); - }); - - describe('and run has some errors', () => { - beforeEach(() => { - expectedRunResult.status = RunStatus.Error; - expectedRunResult.errorMessages = ['foobar', 'example']; - }); - - it('should have logged the errors', async () => { - sut = createSut(); - await expect(sut.run()).rejected; - expect(testInjector.logger.error).calledWith(`One or more tests resulted in an error:${EOL}\tfoobar${EOL}\texample`); - }); - it('should reject with correct message', async () => { - sut = createSut(); - await expect(sut.run()).rejectedWith('Something went wrong in the initial test run'); - }); - }); - - describe('and run timed out', () => { - beforeEach(() => { - expectedRunResult.status = RunStatus.Timeout; - expectedRunResult.tests = [testResult({ name: 'foobar test' }), testResult({ name: 'example test', status: TestStatus.Failed })]; - }); - - it('should have logged the timeout', async () => { - sut = createSut(); - await expect(sut.run()).rejected; - expect(testInjector.logger.error).calledWith( - `Initial test run timed out! Ran following tests before timeout:${EOL}\tfoobar test (Success)${EOL}\texample test (Failed)` - ); - }); - - it('should reject with correct message', async () => { - sut = createSut(); - await expect(sut.run()).rejectedWith('Something went wrong in the initial test run'); - }); - }); - }); -}); diff --git a/packages/core/test/unit/process/MutationTestExecutor.spec.ts b/packages/core/test/unit/process/MutationTestExecutor.spec.ts deleted file mode 100644 index 39502ff4eb..0000000000 --- a/packages/core/test/unit/process/MutationTestExecutor.spec.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { File } from '@stryker-mutator/api/core'; -import { MutantResult, MutantStatus } from '@stryker-mutator/api/report'; -import { factory, testInjector } from '@stryker-mutator/test-helpers'; -import { expect } from 'chai'; -import { of } from 'rxjs'; -import { from, Observable } from 'rxjs'; -import * as sinon from 'sinon'; - -import { coreTokens } from '../../../src/di'; -import InputFileCollection from '../../../src/input/InputFileCollection'; -import { MutationTestExecutor } from '../../../src/process/MutationTestExecutor'; -import BroadcastReporter from '../../../src/reporters/BroadcastReporter'; -import { SandboxPool } from '../../../src/SandboxPool'; -import TestableMutant from '../../../src/TestableMutant'; -import TranspiledMutant from '../../../src/TranspiledMutant'; -import { MutantTranspileScheduler } from '../../../src/transpiler/MutantTranspileScheduler'; -import { Mock, mock, testableMutant, transpiledMutant } from '../../helpers/producers'; - -describe(MutationTestExecutor.name, () => { - let sandboxPoolMock: Mock; - let mutantTranspileSchedulerMock: Mock; - let transpiledMutants: Observable; - let inputFiles: InputFileCollection; - let reporter: Mock; - let sut: MutationTestExecutor; - let mutants: TestableMutant[]; - let mutantResults: MutantResult[]; - - beforeEach(() => { - sandboxPoolMock = mock(SandboxPool); - mutantTranspileSchedulerMock = mock(MutantTranspileScheduler); - mutantTranspileSchedulerMock.scheduleNext = sinon.stub(); - sandboxPoolMock.dispose.resolves(); - reporter = mock(BroadcastReporter); - inputFiles = new InputFileCollection([new File('input.ts', '')], []); - mutants = [testableMutant()]; - transpiledMutants = of(transpiledMutant('foo.js'), transpiledMutant('bar.js')); - mutantResults = [factory.mutantResult({ status: MutantStatus.RuntimeError }), factory.mutantResult({ status: MutantStatus.Survived })]; - mutantTranspileSchedulerMock.scheduleTranspileMutants.returns(transpiledMutants); - sandboxPoolMock.runMutants.returns(from(mutantResults)); - sut = createSut(); - }); - - function createSut(): MutationTestExecutor { - return testInjector.injector - .provideValue(coreTokens.sandboxPool, (sandboxPoolMock as unknown) as SandboxPool) - .provideValue(coreTokens.mutantTranspileScheduler, (mutantTranspileSchedulerMock as unknown) as MutantTranspileScheduler) - .provideValue(coreTokens.inputFiles, inputFiles) - .provideValue(coreTokens.reporter, reporter) - .injectClass(MutationTestExecutor); - } - - describe('run', () => { - it('should have ran the mutants in the sandbox pool', async () => { - await sut.run(mutants); - expect(mutantTranspileSchedulerMock.scheduleTranspileMutants).calledWith(mutants); - expect(sandboxPoolMock.runMutants).calledWith(transpiledMutants); - }); - - it('should schedule next mutants to be transpiled', async () => { - await sut.run(mutants); - expect(mutantTranspileSchedulerMock.scheduleNext).callCount(2); - }); - - it('should have reported `onMutantTested` on all mutants', async () => { - await sut.run(mutants); - expect(reporter.onMutantTested).to.have.callCount(2); - expect(reporter.onMutantTested).to.have.been.calledWith(mutantResults[0]); - expect(reporter.onMutantTested).to.have.been.calledWith(mutantResults[1]); - }); - - it('should have reported `onAllMutantsTested`', async () => { - const actualResults = await sut.run(mutants); - expect(reporter.onAllMutantsTested).to.have.been.calledWith(actualResults); - }); - - it('should eventually resolve the correct mutant results', async () => { - const actualResults = await sut.run(mutants); - expect(actualResults).deep.eq(mutantResults); - }); - }); -}); diff --git a/packages/core/test/unit/reporters/BroadcastReporter.spec.ts b/packages/core/test/unit/reporters/BroadcastReporter.spec.ts index d813aef772..276fb7926e 100644 --- a/packages/core/test/unit/reporters/BroadcastReporter.spec.ts +++ b/packages/core/test/unit/reporters/BroadcastReporter.spec.ts @@ -79,9 +79,9 @@ describe('BroadcastReporter', () => { }); describe('when "wrapUp" returns promises', () => { - let wrapUpResolveFn: Function; - let wrapUpResolveFn2: Function; - let wrapUpRejectFn: Function; + let wrapUpResolveFn: (value?: void | PromiseLike) => void; + let wrapUpResolveFn2: (value?: void | PromiseLike) => void; + let wrapUpRejectFn: (reason?: any) => void; let result: Promise; let isResolved: boolean; @@ -158,14 +158,14 @@ describe('BroadcastReporter', () => { } function captureTTY() { - isTTY = (process.stdout as any).isTTY; + isTTY = process.stdout.isTTY; } function restoreTTY() { - (process.stdout as any).isTTY = isTTY; + process.stdout.isTTY = isTTY; } function setTTY(val: boolean) { - (process.stdout as any).isTTY = val; + process.stdout.isTTY = val; } }); diff --git a/packages/core/test/unit/reporters/ClearTextReporter.spec.ts b/packages/core/test/unit/reporters/ClearTextReporter.spec.ts index 4c52ff8721..d064263567 100644 --- a/packages/core/test/unit/reporters/ClearTextReporter.spec.ts +++ b/packages/core/test/unit/reporters/ClearTextReporter.spec.ts @@ -1,19 +1,14 @@ import * as os from 'os'; -import { MutantResult, MutantStatus, mutationTestReportSchema } from '@stryker-mutator/api/report'; -import { testInjector } from '@stryker-mutator/test-helpers'; -import { mutantResult, mutationScoreThresholds } from '@stryker-mutator/test-helpers/src/factory'; +import { mutationTestReportSchema, MutantStatus } from '@stryker-mutator/api/report'; +import { testInjector, factory } from '@stryker-mutator/test-helpers'; +import { mutationScoreThresholds } from '@stryker-mutator/test-helpers/src/factory'; import { expect } from 'chai'; import * as sinon from 'sinon'; import chalk = require('chalk'); import ClearTextReporter from '../../../src/reporters/ClearTextReporter'; -import { createClearTextReporterOptions } from '../../helpers/producers'; - -const colorizeFileAndPosition = (sourceFilePath: string, line: number, column: number) => { - return [chalk.cyan(sourceFilePath), chalk.yellow(`${line}`), chalk.yellow(`${column}`)].join(':'); -}; describe(ClearTextReporter.name, () => { let sut: ClearTextReporter; @@ -77,196 +72,145 @@ describe(ClearTextReporter.name, () => { }); }); - describe('when coverageAnalysis is "all"', () => { - beforeEach(() => { - testInjector.options.coverageAnalysis = 'all'; - testInjector.options.clearTextReporter = createClearTextReporterOptions({ logTests: true }); + describe('onAllMutantsTested', () => { + it('should report a killed mutant to debug', async () => { + sut.onAllMutantsTested([ + factory.killedMutantResult({ id: '1', mutatorName: 'Math', killedBy: 'foo should be bar', originalLines: 'foo', mutatedLines: 'bar' }), + ]); + expect(testInjector.logger.debug).calledWithMatch(sinon.match('1. [Killed] Math')); + expect(testInjector.logger.debug).calledWith(`${chalk.red('- foo')}`); + expect(testInjector.logger.debug).calledWith(`${chalk.green('+ bar')}`); + expect(testInjector.logger.debug).calledWith('Killed by: foo should be bar'); }); - describe('onAllMutantsTested() all mutants except error', () => { - beforeEach(() => { - sut.onAllMutantsTested(mutantResults(MutantStatus.Killed, MutantStatus.Survived, MutantStatus.TimedOut, MutantStatus.NoCoverage)); - }); - it('should not report the error', () => { - expect(process.stdout.write).to.not.have.been.calledWithMatch(sinon.match(/error/)); - }); + it('should report a transpileError mutant to debug', async () => { + sut.onAllMutantsTested([ + factory.invalidMutantResult({ + id: '1', + mutatorName: 'Math', + errorMessage: 'could not call bar of undefined', + status: MutantStatus.CompileError, + originalLines: 'foo', + mutatedLines: 'bar', + }), + ]); + expect(testInjector.logger.debug).calledWithMatch(sinon.match('1. [CompileError] Math')); + expect(testInjector.logger.debug).calledWith(`${chalk.red('- foo')}`); + expect(testInjector.logger.debug).calledWith(`${chalk.green('+ bar')}`); + expect(testInjector.logger.debug).calledWith('Error message: could not call bar of undefined'); }); - describe('onAllMutantsTested() with mutants of all kinds', () => { - beforeEach(() => { - sut.onAllMutantsTested( - mutantResults( - MutantStatus.Killed, - MutantStatus.Survived, - MutantStatus.TimedOut, - MutantStatus.NoCoverage, - MutantStatus.RuntimeError, - MutantStatus.TranspileError - ) - ); - }); - - it('should report on the survived mutant', () => { - expect(process.stdout.write).to.have.been.calledWithMatch(sinon.match('1. [Survived] Math')); - expect(process.stdout.write).to.have.been.calledWith(`${chalk.red('- original line')}${os.EOL}`); - expect(process.stdout.write).to.have.been.calledWith(`${chalk.green('+ mutated line')}${os.EOL}`); - }); - - it('should not log individual ran tests', () => { - expect(process.stdout.write).to.not.have.been.calledWithMatch(sinon.match('Tests ran:')); - expect(process.stdout.write).to.have.been.calledWithMatch(sinon.match('Ran all tests for this mutant.')); - }); + it('should report a NoCoverage mutant to stdout', async () => { + sut.onAllMutantsTested([ + factory.undetectedMutantResult({ + id: '1', + mutatorName: 'Math', + status: MutantStatus.NoCoverage, + originalLines: 'foo', + mutatedLines: 'bar', + }), + ]); + expect(stdoutStub).calledWithMatch(sinon.match('1. [NoCoverage] Math')); + expect(stdoutStub).calledWith(`${chalk.red('- foo')}${os.EOL}`); + expect(stdoutStub).calledWith(`${chalk.green('+ bar')}${os.EOL}`); }); - }); - - describe('when coverageAnalysis: "perTest"', () => { - describe('onAllMutantsTested()', () => { - it('should log source file names with colored text when clearTextReporter is not false', () => { - testInjector.options.coverageAnalysis = 'perTest'; - - sut.onAllMutantsTested(mutantResults(MutantStatus.Killed, MutantStatus.Survived, MutantStatus.TimedOut, MutantStatus.NoCoverage)); - - expect(process.stdout.write).to.have.been.calledWithMatch(sinon.match(colorizeFileAndPosition('sourceFile.ts', 1, 2))); - }); - - it('should log source file names without colored text when clearTextReporter is not false and allowConsoleColors is false', () => { - testInjector.options.coverageAnalysis = 'perTest'; - testInjector.options.allowConsoleColors = false; - // Recreate, color setting is set in constructor - sut = testInjector.injector.injectClass(ClearTextReporter); - - sut.onAllMutantsTested(mutantResults(MutantStatus.Killed, MutantStatus.Survived, MutantStatus.TimedOut, MutantStatus.NoCoverage)); - - expect(process.stdout.write).to.have.been.calledWithMatch(sinon.match('sourceFile.ts:1:2')); - }); - - it('should not log source file names with colored text when clearTextReporter is false', () => { - testInjector.options.coverageAnalysis = 'perTest'; - - sut.onAllMutantsTested(mutantResults(MutantStatus.Killed, MutantStatus.Survived, MutantStatus.TimedOut, MutantStatus.NoCoverage)); - - expect(process.stdout.write).to.have.been.calledWithMatch(colorizeFileAndPosition('sourceFile.ts', 1, 2)); - }); - - it('should not log individual ran tests when logTests is not true', () => { - testInjector.options.coverageAnalysis = 'perTest'; - testInjector.options.clearTextReporter.logTests = false; - - sut.onAllMutantsTested(mutantResults(MutantStatus.Killed, MutantStatus.Survived, MutantStatus.TimedOut, MutantStatus.NoCoverage)); - - expect(process.stdout.write).to.not.have.been.calledWithMatch(sinon.match('Tests ran: ')); - expect(process.stdout.write).to.not.have.been.calledWithMatch(sinon.match(' a test')); - expect(process.stdout.write).to.not.have.been.calledWithMatch(sinon.match(' a second test')); - expect(process.stdout.write).to.not.have.been.calledWithMatch(sinon.match(' a third test')); - expect(process.stdout.write).to.not.have.been.calledWithMatch(sinon.match('Ran all tests for this mutant.')); - }); - - it('should log individual ran tests when logTests is true', () => { - testInjector.options.coverageAnalysis = 'perTest'; - testInjector.options.clearTextReporter = createClearTextReporterOptions({ logTests: true }); - sut.onAllMutantsTested(mutantResults(MutantStatus.Killed, MutantStatus.Survived, MutantStatus.TimedOut, MutantStatus.NoCoverage)); - - expect(process.stdout.write).to.have.been.calledWithMatch(sinon.match('Tests ran: ')); - expect(process.stdout.write).to.have.been.calledWithMatch(sinon.match(' a test')); - expect(process.stdout.write).to.have.been.calledWithMatch(sinon.match(' a second test')); - expect(process.stdout.write).to.have.been.calledWithMatch(sinon.match(' a third test')); - expect(process.stdout.write).to.not.have.been.calledWithMatch(sinon.match('Ran all tests for this mutant.')); - }); - - describe('with fewer tests that may be logged', () => { - it('should log fewer tests', () => { - testInjector.options.coverageAnalysis = 'perTest'; - testInjector.options.clearTextReporter = createClearTextReporterOptions({ logTests: true, maxTestsToLog: 1 }); + it('should report a Survived mutant to stdout', async () => { + sut.onAllMutantsTested([factory.undetectedMutantResult({ id: '42', mutatorName: 'Math', status: MutantStatus.Survived })]); + expect(stdoutStub).calledWithMatch(sinon.match('42. [Survived] Math')); + }); - sut.onAllMutantsTested(mutantResults(MutantStatus.Killed, MutantStatus.Survived, MutantStatus.TimedOut, MutantStatus.NoCoverage)); + it('should report a Timeout mutant to stdout', async () => { + sut.onAllMutantsTested([factory.timeoutMutantResult({ id: '42', mutatorName: 'Math', status: MutantStatus.TimedOut })]); + expect(testInjector.logger.debug).calledWithMatch(sinon.match('42. [TimedOut] Math')); + }); - expect(process.stdout.write).to.have.been.calledWithMatch(sinon.match('Tests ran:')); - expect(process.stdout.write).to.have.been.calledWithMatch(sinon.match(' a test')); - expect(process.stdout.write).to.have.been.calledWithMatch(sinon.match(' and 2 more tests!')); - expect(process.stdout.write).to.not.have.been.calledWithMatch(sinon.match('Ran all tests for this mutant.')); - }); - }); + it('should report the tests ran for a Survived mutant to stdout for "perTest" coverage analysis', async () => { + testInjector.options.coverageAnalysis = 'perTest'; + sut.onAllMutantsTested([ + factory.undetectedMutantResult({ + status: MutantStatus.Survived, + testFilter: ['foo should be bar', 'baz should be qux', 'quux should be corge'], + }), + ]); + expect(stdoutStub).calledWithExactly(`Tests ran:${os.EOL}`); + expect(stdoutStub).calledWithExactly(` foo should be bar${os.EOL}`); + expect(stdoutStub).calledWithExactly(` baz should be qux${os.EOL}`); + expect(stdoutStub).calledWithExactly(` quux should be corge${os.EOL}`); + }); - describe('with more tests that may be logged', () => { - it('should log all tests', () => { - testInjector.options.coverageAnalysis = 'perTest'; - testInjector.options.clearTextReporter = createClearTextReporterOptions({ logTests: true, maxTestsToLog: 10 }); + it('should report the max tests to log and however many more tests', async () => { + testInjector.options.coverageAnalysis = 'perTest'; + testInjector.options.clearTextReporter.maxTestsToLog = 2; + sut.onAllMutantsTested([ + factory.undetectedMutantResult({ + status: MutantStatus.Survived, + testFilter: ['foo should be bar', 'baz should be qux', 'quux should be corge'], + }), + ]); + expect(stdoutStub).calledWithExactly(`Tests ran:${os.EOL}`); + expect(stdoutStub).calledWithExactly(` foo should be bar${os.EOL}`); + expect(stdoutStub).calledWithExactly(` baz should be qux${os.EOL}`); + expect(stdoutStub).not.calledWithMatch(sinon.match('quux should be corge')); + expect(stdoutStub).calledWithExactly(` and 1 more test!${os.EOL}`); + }); - sut.onAllMutantsTested(mutantResults(MutantStatus.Killed, MutantStatus.Survived, MutantStatus.TimedOut, MutantStatus.NoCoverage)); + it('should report that all tests have ran for a mutant when coverage analysis when testFilter is not defined', async () => { + testInjector.options.coverageAnalysis = 'perTest'; + testInjector.options.clearTextReporter.maxTestsToLog = 2; + sut.onAllMutantsTested([ + factory.undetectedMutantResult({ + status: MutantStatus.Survived, + testFilter: undefined, + }), + ]); + expect(stdoutStub).calledWithExactly(`Ran all tests for this mutant.${os.EOL}`); + }); - expect(process.stdout.write).to.have.been.calledWithMatch(sinon.match('Tests ran:')); - expect(process.stdout.write).to.have.been.calledWithMatch(sinon.match(' a test')); - expect(process.stdout.write).to.have.been.calledWithMatch(sinon.match(' a second test')); - expect(process.stdout.write).to.have.been.calledWithMatch(sinon.match(' a third test')); - expect(process.stdout.write).to.not.have.been.calledWithMatch(sinon.match('Ran all tests for this mutant.')); - }); - }); + it('should not log individual ran tests when logTests is not true', () => { + testInjector.options.coverageAnalysis = 'perTest'; + testInjector.options.clearTextReporter.logTests = false; + sut.onAllMutantsTested([factory.undetectedMutantResult({ status: MutantStatus.Survived, testFilter: ['foo should be bar'] })]); - describe('with the default amount of tests that may be logged', () => { - it('should log all tests', () => { - testInjector.options.coverageAnalysis = 'perTest'; - testInjector.options.clearTextReporter = createClearTextReporterOptions({ logTests: true, maxTestsToLog: 3 }); + expect(process.stdout.write).not.calledWithMatch(sinon.match('Tests ran: ')); + expect(process.stdout.write).not.calledWithMatch(sinon.match('foo should be bar')); + expect(process.stdout.write).not.calledWithMatch(sinon.match('Ran all tests for this mutant.')); + }); - sut.onAllMutantsTested(mutantResults(MutantStatus.Killed, MutantStatus.Survived, MutantStatus.TimedOut, MutantStatus.NoCoverage)); + it('should report that all tests have ran for a mutant when coverage analysis = "all"', async () => { + testInjector.options.coverageAnalysis = 'all'; + sut.onAllMutantsTested([factory.undetectedMutantResult({ status: MutantStatus.Survived, testFilter: [] })]); + expect(stdoutStub).calledWithExactly(`Ran all tests for this mutant.${os.EOL}`); + }); - expect(process.stdout.write).to.have.been.calledWithMatch(sinon.match('Tests ran:')); - expect(process.stdout.write).to.have.been.calledWithMatch(sinon.match(' a test')); - expect(process.stdout.write).to.have.been.calledWithMatch(sinon.match(' a second test')); - expect(process.stdout.write).to.have.been.calledWithMatch(sinon.match(' a third test')); - expect(process.stdout.write).to.not.have.been.calledWithMatch(sinon.match('Ran all tests for this mutant.')); - }); - }); + it('should correctly report tests run per mutant on avg', () => { + sut.onAllMutantsTested([ + factory.undetectedMutantResult({ nrOfTestsRan: 4 }), + factory.killedMutantResult({ nrOfTestsRan: 5 }), + factory.undetectedMutantResult({ nrOfTestsRan: 1 }), + ]); + expect(stdoutStub).calledWithExactly(`Ran 3.33 tests per mutant on average.${os.EOL}`); + }); - describe('with no tests that may be logged', () => { - it('should not log a test', () => { - testInjector.options.coverageAnalysis = 'perTest'; - testInjector.options.clearTextReporter = createClearTextReporterOptions({ logTests: true, maxTestsToLog: 0 }); + it('should log source file location', () => { + testInjector.options.coverageAnalysis = 'perTest'; - sut.onAllMutantsTested(mutantResults(MutantStatus.Killed, MutantStatus.Survived, MutantStatus.TimedOut, MutantStatus.NoCoverage)); + sut.onAllMutantsTested([factory.undetectedMutantResult({ fileName: 'foo.js', location: factory.location({ start: { line: 4, column: 6 } }) })]); - expect(process.stdout.write).to.not.have.been.calledWithMatch(sinon.match('Tests ran: \n')); - expect(process.stdout.write).to.not.have.been.calledWithMatch(sinon.match(' a test\n')); - expect(process.stdout.write).to.not.have.been.calledWithMatch(sinon.match(' a second test\n')); - expect(process.stdout.write).to.not.have.been.calledWithMatch(sinon.match(' a third test\n')); - expect(process.stdout.write).to.not.have.been.calledWithMatch(sinon.match('Ran all tests for this mutant.\n')); - }); - }); + expect(stdoutStub).to.have.been.calledWithMatch(sinon.match(`${chalk.cyan('foo.js')}:${chalk.yellow('4')}:${chalk.yellow('6')}`)); }); - }); - describe('when coverageAnalysis: "off"', () => { - beforeEach(() => (testInjector.options.coverageAnalysis = 'off')); - - describe('onAllMutantsTested()', () => { - beforeEach(() => { - sut.onAllMutantsTested(mutantResults(MutantStatus.Killed, MutantStatus.Survived, MutantStatus.TimedOut, MutantStatus.NoCoverage)); - }); + it('should log source file names without colored text when clearTextReporter is not false and allowConsoleColors is false', () => { + testInjector.options.coverageAnalysis = 'perTest'; + testInjector.options.allowConsoleColors = false; + // Recreate, color setting is set in constructor + sut = testInjector.injector.injectClass(ClearTextReporter); - it('should not log individual ran tests', () => { - expect(process.stdout.write).to.not.have.been.calledWithMatch(sinon.match('Tests ran:')); - expect(process.stdout.write).to.have.been.calledWithMatch(sinon.match('Ran all tests for this mutant.')); - }); + sut.onAllMutantsTested([ + factory.killedMutantResult({ fileName: 'sourceFile.ts', location: factory.location({ start: { line: 1, column: 2 } }) }), + ]); - it('should report the average amount of tests ran', () => - expect(process.stdout.write).to.have.been.calledWithMatch(sinon.match('Ran 3.00 tests per mutant on average.'))); + expect(testInjector.logger.debug).calledWithMatch(sinon.match('sourceFile.ts:1:2')); }); }); - - function mutantResults(...status: MutantStatus[]): MutantResult[] { - return status.map((status) => { - const result: MutantResult = mutantResult({ - location: { start: { line: 1, column: 2 }, end: { line: 3, column: 4 } }, - mutatedLines: 'mutated line', - mutatorName: 'Math', - originalLines: 'original line', - range: [0, 0], - replacement: '', - sourceFilePath: 'sourceFile.ts', - status, - testsRan: ['a test', 'a second test', 'a third test'], - }); - return result; - }); - } }); diff --git a/packages/core/test/unit/reporters/DotsReporter.spec.ts b/packages/core/test/unit/reporters/DotsReporter.spec.ts index ca884f18c1..b31c61bee1 100644 --- a/packages/core/test/unit/reporters/DotsReporter.spec.ts +++ b/packages/core/test/unit/reporters/DotsReporter.spec.ts @@ -1,15 +1,14 @@ import * as os from 'os'; -import { MutantResult, MutantStatus } from '@stryker-mutator/api/report'; +import { MutantStatus } from '@stryker-mutator/api/report'; import { factory } from '@stryker-mutator/test-helpers'; import { expect } from 'chai'; import * as sinon from 'sinon'; - import chalk = require('chalk'); import DotsReporter from '../../../src/reporters/DotsReporter'; -describe('DotsReporter', () => { +describe(DotsReporter.name, () => { let sut: DotsReporter; let sandbox: sinon.SinonSandbox; @@ -20,34 +19,19 @@ describe('DotsReporter', () => { }); describe('onMutantTested()', () => { - describe('when status is Killed', () => { - beforeEach(() => { - sut.onMutantTested(mutantResult(MutantStatus.Killed)); - }); - - it('should log "."', () => { - expect(process.stdout.write).to.have.been.calledWith('.'); - }); + it('should log "." when status is Killed', () => { + sut.onMutantTested(factory.killedMutantResult()); + expect(process.stdout.write).to.have.been.calledWith('.'); }); - describe('when status is TimedOut', () => { - beforeEach(() => { - sut.onMutantTested(mutantResult(MutantStatus.TimedOut)); - }); - - it('should log "T"', () => { - expect(process.stdout.write).to.have.been.calledWith(chalk.yellow('T')); - }); + it('should log "T" when status is TimedOut', () => { + sut.onMutantTested(factory.timeoutMutantResult()); + expect(process.stdout.write).to.have.been.calledWith(chalk.yellow('T')); }); - describe('when status is Survived', () => { - beforeEach(() => { - sut.onMutantTested(mutantResult(MutantStatus.Survived)); - }); - - it('should log "S"', () => { - expect(process.stdout.write).to.have.been.calledWith(chalk.bold.red('S')); - }); + it('should log "S" when status is Survived', () => { + sut.onMutantTested(factory.undetectedMutantResult({ status: MutantStatus.Survived })); + expect(process.stdout.write).to.have.been.calledWith(chalk.bold.red('S')); }); }); @@ -61,18 +45,4 @@ describe('DotsReporter', () => { afterEach(() => { sandbox.restore(); }); - - function mutantResult(status: MutantStatus): MutantResult { - return factory.mutantResult({ - location: { start: { line: 0, column: 0 }, end: { line: 0, column: 0 } }, - mutatedLines: '', - mutatorName: '', - originalLines: '', - range: [0, 0], - replacement: '', - sourceFilePath: '', - status, - testsRan: [''], - }); - } }); diff --git a/packages/core/test/unit/reporters/EventRecorderReporter.spec.ts b/packages/core/test/unit/reporters/EventRecorderReporter.spec.ts index 48ccb5adf3..9194be93da 100644 --- a/packages/core/test/unit/reporters/EventRecorderReporter.spec.ts +++ b/packages/core/test/unit/reporters/EventRecorderReporter.spec.ts @@ -34,7 +34,7 @@ describe(EventRecorderReporter.name, () => { const arrangeActAssertEvent = (eventName: keyof Reporter) => { describe(`${eventName} event`, () => { let writeFileRejection: undefined | Error; - const expected: any = { some: 'eventData' }; + const expected = { some: 'eventData' }; const arrange = () => beforeEach(() => { diff --git a/packages/core/test/unit/reporters/MutationTestReportCalculator.spec.ts b/packages/core/test/unit/reporters/MutationTestReportCalculator.spec.ts deleted file mode 100644 index 03013d50cc..0000000000 --- a/packages/core/test/unit/reporters/MutationTestReportCalculator.spec.ts +++ /dev/null @@ -1,194 +0,0 @@ -import sinon = require('sinon'); -import { File } from '@stryker-mutator/api/core'; -import { MutantResult, MutantStatus, mutationTestReportSchema, Reporter } from '@stryker-mutator/api/report'; -import { factory, testInjector } from '@stryker-mutator/test-helpers'; -import { expect } from 'chai'; -import { mutantResult } from '@stryker-mutator/test-helpers/src/factory'; - -import { coreTokens } from '../../../src/di'; -import InputFileCollection from '../../../src/input/InputFileCollection'; -import { MutationTestReportCalculator } from '../../../src/reporters/MutationTestReportCalculator'; -import * as objectUtils from '../../../src/utils/objectUtils'; - -describe(MutationTestReportCalculator.name, () => { - let reporterMock: sinon.SinonStubbedInstance>; - let sut: MutationTestReportCalculator; - let inputFiles: InputFileCollection; - let files: File[]; - let setExitCodeStub: sinon.SinonStub; - - beforeEach(() => { - reporterMock = factory.reporter(); - setExitCodeStub = sinon.stub(objectUtils, 'setExitCode'); - files = []; - inputFiles = { - files, - filesToMutate: [], - logFiles: () => {}, - }; - sut = testInjector.injector - .provideValue(coreTokens.reporter, reporterMock as Required) - .provideValue(coreTokens.inputFiles, inputFiles) - .injectClass(MutationTestReportCalculator); - }); - - describe(MutationTestReportCalculator.prototype.report.name, () => { - it('should report "mutationTestReportReady"', () => { - sut.report([]); - expect(reporterMock.onMutationTestReportReady).calledOnce; - }); - - it('should copy thresholds', () => { - const actualReport = actReport(); - expect(actualReport.thresholds).eq(testInjector.options.thresholds); - }); - - it('should set correct schema version', () => { - const actualReport = actReport(); - expect(actualReport.schemaVersion).eq('1.0'); - }); - - it('should correctly map file properties', () => { - // Arrange - files.push(new File('foo.js', 'foo content')); - files.push(new File('bar.html', 'bar content')); - files.push(new File('baz.vue', 'baz content')); - files.push(new File('qux.ts', 'qux content')); - files.push(new File('corge.tsx', 'corge content')); - const inputMutants = files.map((file) => factory.mutantResult({ sourceFilePath: file.name })); - - // Act - const actualReport = actReport(inputMutants); - - // Assert - expect(Object.keys(actualReport.files)).lengthOf(5); - expect(actualReport.files['foo.js']).include({ language: 'javascript', source: 'foo content' }); - expect(actualReport.files['bar.html']).include({ language: 'html', source: 'bar content' }); - expect(actualReport.files['baz.vue']).include({ language: 'html', source: 'baz content' }); - expect(actualReport.files['qux.ts']).include({ language: 'typescript', source: 'qux content' }); - expect(actualReport.files['corge.tsx']).include({ language: 'typescript', source: 'corge content' }); - }); - - it('should correctly map basic MutantResult properties', () => { - // Arrange - const inputMutants = [ - factory.mutantResult({ - id: '1', - mutatorName: 'Foo', - replacement: 'foo replacement', - sourceFilePath: 'foo.js', - status: MutantStatus.Killed, - }), - factory.mutantResult({ - sourceFilePath: 'bar.js', - status: MutantStatus.NoCoverage, - }), - factory.mutantResult({ - sourceFilePath: 'baz.js', - status: MutantStatus.RuntimeError, - }), - factory.mutantResult({ - sourceFilePath: 'qux.js', - status: MutantStatus.Survived, - }), - factory.mutantResult({ - sourceFilePath: '5.js', - status: MutantStatus.TimedOut, - }), - factory.mutantResult({ - sourceFilePath: '6.js', - status: MutantStatus.TranspileError, - }), - ]; - files.push(...inputMutants.map((m) => new File(m.sourceFilePath, ''))); - - // Act - const actualReport = actReport(inputMutants); - - // Assert - expect(Object.keys(actualReport.files)).lengthOf(6); - expect(actualReport.files['foo.js'].mutants[0]).include({ - id: '1', - mutatorName: 'Foo', - replacement: 'foo replacement', - status: mutationTestReportSchema.MutantStatus.Killed, - }); - expect(actualReport.files['bar.js'].mutants[0]).include({ status: mutationTestReportSchema.MutantStatus.NoCoverage }); - expect(actualReport.files['baz.js'].mutants[0]).include({ status: mutationTestReportSchema.MutantStatus.RuntimeError }); - expect(actualReport.files['qux.js'].mutants[0]).include({ status: mutationTestReportSchema.MutantStatus.Survived }); - expect(actualReport.files['5.js'].mutants[0]).include({ status: mutationTestReportSchema.MutantStatus.Timeout }); - expect(actualReport.files['6.js'].mutants[0]).include({ status: mutationTestReportSchema.MutantStatus.CompileError }); - }); - - it('should offset location correctly', () => { - const inputMutants = [factory.mutantResult({ location: { end: { line: 3, column: 4 }, start: { line: 1, column: 2 } } })]; - files.push(...inputMutants.map((m) => new File(m.sourceFilePath, ''))); - const actualReport = actReport(inputMutants); - expect(actualReport.files['file.js'].mutants[0].location).deep.eq({ end: { line: 4, column: 5 }, start: { line: 2, column: 3 } }); - }); - - it('should group mutants by file name', () => { - // Arrange - const inputMutants = [ - factory.mutantResult({ - mutatorName: 'Foo', - sourceFilePath: 'foo.js', - }), - factory.mutantResult({ - mutatorName: 'Bar', - sourceFilePath: 'foo.js', - }), - ]; - files.push(new File('foo.js', '')); - - // Act - const actualReport = actReport(inputMutants); - - // Assert - expect(Object.keys(actualReport.files)).lengthOf(1); - expect(actualReport.files['foo.js'].mutants).lengthOf(2); - }); - - it('should log a warning if source file could not be found', () => { - const inputMutants = [factory.mutantResult({ sourceFilePath: 'not-found.js' })]; - const actualReport = actReport(inputMutants); - expect(Object.keys(actualReport.files)).lengthOf(0); - expect(testInjector.logger.warn).calledWithMatch('File "not-found.js" not found'); - }); - - describe('determineExitCode', () => { - beforeEach(() => { - files.push(new File('file.js', '')); - }); - - it('should not set exit code = 1 if `threshold.break` is not configured', () => { - actReport([mutantResult({ status: MutantStatus.Survived })]); - - expect(setExitCodeStub).not.called; - expect(testInjector.logger.debug).calledWith( - "No breaking threshold configured. Won't fail the build no matter how low your mutation score is. Set `thresholds.break` to change this behavior." - ); - }); - - it('should not set exit code = 1 if `threshold.break` === score', () => { - testInjector.options.thresholds.break = 50; - actReport([mutantResult({ status: MutantStatus.Survived }), mutantResult({ status: MutantStatus.Killed })]); // 50 % - expect(setExitCodeStub).not.called; - expect(testInjector.logger.info).calledWith('Final mutation score of 50.00 is greater than or equal to break threshold 50'); - }); - - it('should set exit code = 1 if `threshold.break` > score', () => { - testInjector.options.thresholds.break = 50.01; - actReport([mutantResult({ status: MutantStatus.Survived }), mutantResult({ status: MutantStatus.Killed })]); // 50 % - expect(setExitCodeStub).calledWith(1); - expect(testInjector.logger.error).calledWith('Final mutation score 50.00 under breaking threshold 50.01, setting exit code to 1 (failure).'); - expect(testInjector.logger.info).calledWith('(improve mutation score or set `thresholds.break = null` to prevent this error in the future)'); - }); - }); - }); - - function actReport(input: readonly MutantResult[] = []): mutationTestReportSchema.MutationTestResult { - sut.report(input); - return reporterMock.onMutationTestReportReady.firstCall.args[0]; - } -}); diff --git a/packages/core/test/unit/reporters/MutationTestReportHelper.spec.ts b/packages/core/test/unit/reporters/MutationTestReportHelper.spec.ts new file mode 100644 index 0000000000..f8d1d1be5c --- /dev/null +++ b/packages/core/test/unit/reporters/MutationTestReportHelper.spec.ts @@ -0,0 +1,436 @@ +import sinon = require('sinon'); +import { File, Location, Range } from '@stryker-mutator/api/core'; +import { + MutantResult, + MutantStatus, + mutationTestReportSchema, + Reporter, + InvalidMutantResult, + UndetectedMutantResult, + KilledMutantResult, + TimeoutMutantResult, + IgnoredMutantResult, +} from '@stryker-mutator/api/report'; +import { factory, testInjector } from '@stryker-mutator/test-helpers'; +import { expect } from 'chai'; +import { CompleteDryRunResult } from '@stryker-mutator/api/test_runner'; +import { CheckStatus } from '@stryker-mutator/api/check'; + +import { coreTokens } from '../../../src/di'; +import InputFileCollection from '../../../src/input/InputFileCollection'; +import { MutationTestReportHelper } from '../../../src/reporters/MutationTestReportHelper'; +import * as objectUtils from '../../../src/utils/objectUtils'; +import { createMutantTestCoverage } from '../../helpers/producers'; + +describe(MutationTestReportHelper.name, () => { + let reporterMock: sinon.SinonStubbedInstance>; + let inputFiles: InputFileCollection; + let files: File[]; + let setExitCodeStub: sinon.SinonStub; + let dryRunResult: CompleteDryRunResult; + + beforeEach(() => { + reporterMock = factory.reporter(); + setExitCodeStub = sinon.stub(objectUtils, 'setExitCode'); + files = []; + inputFiles = { + files, + filesToMutate: [], + logFiles: () => {}, + }; + dryRunResult = factory.completeDryRunResult(); + }); + + function createSut() { + return testInjector.injector + .provideValue(coreTokens.reporter, reporterMock) + .provideValue(coreTokens.inputFiles, inputFiles) + .provideValue(coreTokens.dryRunResult, dryRunResult) + .injectClass(MutationTestReportHelper); + } + + describe(MutationTestReportHelper.prototype.reportAll.name, () => { + let sut: MutationTestReportHelper; + + beforeEach(() => { + sut = createSut(); + }); + + it('should report "mutationTestReportReady"', () => { + sut.reportAll([]); + expect(reporterMock.onMutationTestReportReady).calledOnce; + }); + + it('should report "onAllMutantsTested"', () => { + sut.reportAll([]); + expect(reporterMock.onAllMutantsTested).calledOnce; + }); + + it('should report "onAllMutantsTested" before mutationTestReportReady', () => { + sut.reportAll([]); + expect(reporterMock.onAllMutantsTested).calledBefore(reporterMock.onMutationTestReportReady); + }); + + it('should copy thresholds', () => { + const actualReport = actReportAll(); + expect(actualReport.thresholds).eq(testInjector.options.thresholds); + }); + + it('should set correct schema version', () => { + const actualReport = actReportAll(); + expect(actualReport.schemaVersion).eq('1.0'); + }); + + it('should correctly map file properties', () => { + // Arrange + files.push(new File('foo.js', 'foo content')); + files.push(new File('bar.html', 'bar content')); + files.push(new File('baz.vue', 'baz content')); + files.push(new File('qux.ts', 'qux content')); + files.push(new File('corge.tsx', 'corge content')); + const inputMutants = files.map((file) => factory.killedMutantResult({ fileName: file.name })); + + // Act + const actualReport = actReportAll(inputMutants); + + // Assert + expect(Object.keys(actualReport.files)).lengthOf(5); + expect(actualReport.files['foo.js']).include({ language: 'javascript', source: 'foo content' }); + expect(actualReport.files['bar.html']).include({ language: 'html', source: 'bar content' }); + expect(actualReport.files['baz.vue']).include({ language: 'html', source: 'baz content' }); + expect(actualReport.files['qux.ts']).include({ language: 'typescript', source: 'qux content' }); + expect(actualReport.files['corge.tsx']).include({ language: 'typescript', source: 'corge content' }); + }); + + it('should correctly map basic MutantResult properties', () => { + // Arrange + const inputMutants = [ + factory.killedMutantResult({ + id: '1', + mutatorName: 'Foo', + replacement: 'foo replacement', + fileName: 'foo.js', + status: MutantStatus.Killed, + }), + factory.undetectedMutantResult({ + fileName: 'bar.js', + status: MutantStatus.NoCoverage, + }), + factory.invalidMutantResult({ + fileName: 'baz.js', + status: MutantStatus.RuntimeError, + }), + factory.undetectedMutantResult({ + fileName: 'qux.js', + status: MutantStatus.Survived, + }), + factory.timeoutMutantResult({ + fileName: '5.js', + status: MutantStatus.TimedOut, + }), + factory.invalidMutantResult({ + fileName: '6.js', + status: MutantStatus.CompileError, + }), + ]; + files.push(...inputMutants.map((m) => new File(m.fileName, ''))); + + // Act + const actualReport = actReportAll(inputMutants); + + // Assert + expect(Object.keys(actualReport.files)).lengthOf(6); + expect(actualReport.files['foo.js'].mutants[0]).include({ + id: '1', + mutatorName: 'Foo', + replacement: 'foo replacement', + status: mutationTestReportSchema.MutantStatus.Killed, + }); + expect(actualReport.files['bar.js'].mutants[0]).include({ status: mutationTestReportSchema.MutantStatus.NoCoverage }); + expect(actualReport.files['baz.js'].mutants[0]).include({ status: mutationTestReportSchema.MutantStatus.RuntimeError }); + expect(actualReport.files['qux.js'].mutants[0]).include({ status: mutationTestReportSchema.MutantStatus.Survived }); + expect(actualReport.files['5.js'].mutants[0]).include({ status: mutationTestReportSchema.MutantStatus.Timeout }); + expect(actualReport.files['6.js'].mutants[0]).include({ status: mutationTestReportSchema.MutantStatus.CompileError }); + }); + + it('should offset location correctly', () => { + const inputMutants = [factory.killedMutantResult({ location: { end: { line: 3, column: 4 }, start: { line: 1, column: 2 } } })]; + files.push(...inputMutants.map((m) => new File(m.fileName, ''))); + const actualReport = actReportAll(inputMutants); + expect(actualReport.files['file.js'].mutants[0].location).deep.eq({ end: { line: 4, column: 5 }, start: { line: 2, column: 3 } }); + }); + + it('should group mutants by file name', () => { + // Arrange + const inputMutants = [ + factory.killedMutantResult({ + mutatorName: 'Foo', + fileName: 'foo.js', + }), + factory.undetectedMutantResult({ + mutatorName: 'Bar', + fileName: 'foo.js', + }), + ]; + files.push(new File('foo.js', '')); + + // Act + const actualReport = actReportAll(inputMutants); + + // Assert + expect(Object.keys(actualReport.files)).lengthOf(1); + expect(actualReport.files['foo.js'].mutants).lengthOf(2); + }); + + it('should log a warning if source file could not be found', () => { + const inputMutants = [factory.killedMutantResult({ fileName: 'not-found.js' })]; + const actualReport = actReportAll(inputMutants); + expect(Object.keys(actualReport.files)).lengthOf(0); + expect(testInjector.logger.warn).calledWithMatch('File "not-found.js" not found'); + }); + + describe('determineExitCode', () => { + beforeEach(() => { + files.push(new File('file.js', '')); + }); + + it('should not set exit code = 1 if `threshold.break` is not configured', () => { + actReportAll([factory.undetectedMutantResult({ status: MutantStatus.Survived })]); + + expect(setExitCodeStub).not.called; + expect(testInjector.logger.debug).calledWith( + "No breaking threshold configured. Won't fail the build no matter how low your mutation score is. Set `thresholds.break` to change this behavior." + ); + }); + + it('should not set exit code = 1 if `threshold.break` === score', () => { + testInjector.options.thresholds.break = 50; + actReportAll([ + factory.undetectedMutantResult({ status: MutantStatus.Survived }), + factory.killedMutantResult({ status: MutantStatus.Killed }), + ]); // 50 % + expect(setExitCodeStub).not.called; + expect(testInjector.logger.info).calledWith('Final mutation score of 50.00 is greater than or equal to break threshold 50'); + }); + + it('should set exit code = 1 if `threshold.break` > score', () => { + testInjector.options.thresholds.break = 50.01; + actReportAll([ + factory.undetectedMutantResult({ status: MutantStatus.Survived }), + factory.killedMutantResult({ status: MutantStatus.Killed }), + ]); // 50 % + expect(setExitCodeStub).calledWith(1); + expect(testInjector.logger.error).calledWith('Final mutation score 50.00 under breaking threshold 50.01, setting exit code to 1 (failure).'); + expect(testInjector.logger.info).calledWith('(improve mutation score or set `thresholds.break = null` to prevent this error in the future)'); + }); + }); + + describe('determine description', () => { + beforeEach(() => { + files.push(new File('file.js', '')); + }); + + it('should provide the error message as description', () => { + const mutantResult = factory.invalidMutantResult({ fileName: 'file.js', errorMessage: 'Cannot call "foo" of undefined' }); + const actualReport = actReportAll([mutantResult]); + expect(actualReport.files['file.js'].mutants[0].description).eq('Error message: Cannot call "foo" of undefined'); + }); + + it('should provide the "killedBy" as description', () => { + const mutantResult = factory.killedMutantResult({ fileName: 'file.js', killedBy: 'Foo should be bar' }); + const actualReport = actReportAll([mutantResult]); + expect(actualReport.files['file.js'].mutants[0].description).eq('Killed by: Foo should be bar'); + }); + + it('should provide the ignore reason as description', () => { + const mutantResult = factory.ignoredMutantResult({ fileName: 'file.js', ignoreReason: 'Ignored by "fooMutator" in excludedMutations' }); + const actualReport = actReportAll([mutantResult]); + expect(actualReport.files['file.js'].mutants[0].description).eq('Ignore reason: Ignored by "fooMutator" in excludedMutations'); + }); + }); + + function actReportAll(input: MutantResult[] = []): mutationTestReportSchema.MutationTestResult { + sut.reportAll(input); + return reporterMock.onMutationTestReportReady.firstCall.args[0]; + } + }); + + describe('reportOne', () => { + beforeEach(() => { + inputFiles = new InputFileCollection([new File('add.js', 'function add(a, b) {\n return a + b;\n}\n')], ['add.js']); + }); + + it('should map simple attributes to the mutant result', () => { + // Arrange + const sut = createSut(); + const location: Location = Object.freeze({ start: Object.freeze({ line: 1, column: 5 }), end: Object.freeze({ line: 3, column: 1 }) }); + const range: Range = [21, 35]; + + // Act + const actual = sut.reportCheckFailed( + factory.mutant({ + id: 32, + fileName: 'add.js', + location, + replacement: '{}', + mutatorName: 'fooMutator', + range, + }), + factory.failedCheckResult() + ); + + // Assert + const expected: Partial = { + id: '32', + location, + mutatorName: 'fooMutator', + range, + fileName: 'add.js', + replacement: '{}', + }; + expect(actual).include(expected); + }); + + it('should report failed message on reportCheckFailed', () => { + // Arrange + const sut = createSut(); + + // Act + const actual = sut.reportCheckFailed( + factory.mutant({ fileName: 'add.js' }), + factory.failedCheckResult({ status: CheckStatus.CompileError, reason: 'cannot call foo of undefined' }) + ); + + // Assert + const expected: Partial = { + status: MutantStatus.CompileError, + errorMessage: 'cannot call foo of undefined', + }; + expect(actual).include(expected); + }); + + it('should report an empty test filter on reportNoCoverage', () => { + // Arrange + const sut = createSut(); + + // Act + const actual = sut.reportNoCoverage(factory.mutant({ fileName: 'add.js' })); + + // Assert + const expected: Partial = { + status: MutantStatus.NoCoverage, + testFilter: [], + }; + expect(actual).deep.include(expected); + }); + + it('should report a killed mutant on reportMutantRunResult with a KilledMutantRunResult', () => { + // Arrange + dryRunResult.tests.push(factory.failedTestResult({ id: '1', name: 'foo should be bar' })); + const sut = createSut(); + + // Act + const actual = sut.reportMutantRunResult( + createMutantTestCoverage({ mutant: factory.mutant({ fileName: 'add.js' }) }), + factory.killedMutantRunResult({ killedBy: '1', nrOfTests: 42 }) + ); + + // Assert + const expected: Partial = { + status: MutantStatus.Killed, + killedBy: 'foo should be bar', + nrOfTestsRan: 42, + }; + expect(actual).deep.include(expected); + }); + + it('should report a runtime error mutant on reportMutantRunResult with a ErrorMutantRunResult', () => { + // Arrange + const sut = createSut(); + + // Act + const actual = sut.reportMutantRunResult( + createMutantTestCoverage({ mutant: factory.mutant({ fileName: 'add.js' }) }), + factory.errorMutantRunResult({ errorMessage: 'Cannot call foo of null' }) + ); + + // Assert + const expected: Partial = { + status: MutantStatus.RuntimeError, + errorMessage: 'Cannot call foo of null', + }; + expect(actual).deep.include(expected); + }); + + it('should report a timeout mutant on reportMutantRunResult with a TimeoutMutantRunResult', () => { + // Arrange + const sut = createSut(); + + // Act + const actual = sut.reportMutantRunResult( + createMutantTestCoverage({ mutant: factory.mutant({ fileName: 'add.js' }) }), + factory.timeoutMutantRunResult() + ); + + // Assert + const expected: Partial = { + status: MutantStatus.TimedOut, + }; + expect(actual).deep.include(expected); + }); + + it('should report an ignored mutant on reportMutantRunResult with a IgnoredMutantResult', () => { + // Arrange + const sut = createSut(); + + // Act + const actual = sut.reportMutantIgnored(factory.mutant({ fileName: 'add.js', ignoreReason: 'foo is ignored' })); + + // Assert + const expected: Partial = { + status: MutantStatus.Ignored, + ignoreReason: 'foo is ignored', + }; + expect(actual).deep.include(expected); + }); + + it('should report a survived mutant on reportMutantRunResult with a SurvivedMutantRunResult', () => { + // Arrange + dryRunResult.tests.push(factory.failedTestResult({ id: '1', name: 'foo should be bar' })); + const sut = createSut(); + + // Act + const actual = sut.reportMutantRunResult( + createMutantTestCoverage({ mutant: factory.mutant({ fileName: 'add.js' }), testFilter: ['1'] }), + factory.survivedMutantRunResult({ nrOfTests: 4 }) + ); + + // Assert + const expected: Partial = { + status: MutantStatus.Survived, + testFilter: ['foo should be bar'], + nrOfTestsRan: 4, + }; + expect(actual).deep.include(expected); + }); + + it('should be able to report testFilter as `undefined` for a survived mutant', () => { + // Arrange + dryRunResult.tests.push(factory.failedTestResult({ id: '1', name: 'foo should be bar' })); + const sut = createSut(); + + // Act + const actual = sut.reportMutantRunResult( + createMutantTestCoverage({ mutant: factory.mutant({ fileName: 'add.js' }), testFilter: undefined }), + factory.survivedMutantRunResult() + ); + + // Assert + const expected: Partial = { + status: MutantStatus.Survived, + testFilter: undefined, + }; + expect(actual).deep.include(expected); + }); + }); +}); diff --git a/packages/core/test/unit/reporters/ProgressAppendOnlyReporter.spec.ts b/packages/core/test/unit/reporters/ProgressAppendOnlyReporter.spec.ts index 007e3ef4c9..6d9383c873 100644 --- a/packages/core/test/unit/reporters/ProgressAppendOnlyReporter.spec.ts +++ b/packages/core/test/unit/reporters/ProgressAppendOnlyReporter.spec.ts @@ -1,10 +1,11 @@ import * as os from 'os'; -import { MutantStatus } from '@stryker-mutator/api/report'; -import { matchedMutant, mutantResult } from '@stryker-mutator/test-helpers/src/factory'; +import { matchedMutant } from '@stryker-mutator/test-helpers/src/factory'; import { expect } from 'chai'; import * as sinon from 'sinon'; +import { factory } from '@stryker-mutator/test-helpers'; + import ProgressAppendOnlyReporter from '../../../src/reporters/ProgressAppendOnlyReporter'; const SECOND = 1000; @@ -13,7 +14,7 @@ const HUNDRED_SECONDS = SECOND * 100; const THOUSAND_SECONDS = SECOND * 1000; const TEN_THOUSAND_SECONDS = SECOND * 10000; -describe('ProgressAppendOnlyReporter', () => { +describe(ProgressAppendOnlyReporter.name, () => { let sut: ProgressAppendOnlyReporter; beforeEach(() => { @@ -24,7 +25,11 @@ describe('ProgressAppendOnlyReporter', () => { describe('onAllMutantsMatchedWithTests() with 3 mutants to test', () => { beforeEach(() => { - sut.onAllMutantsMatchedWithTests([matchedMutant(1), matchedMutant(1), matchedMutant(1)]); + sut.onAllMutantsMatchedWithTests([ + matchedMutant({ runAllTests: true }), + matchedMutant({ runAllTests: true }), + matchedMutant({ runAllTests: true }), + ]); }); it('should not show show progress directly', () => { @@ -39,7 +44,7 @@ describe('ProgressAppendOnlyReporter', () => { }); it('should log correct info after ten seconds with 1 completed test', () => { - sut.onMutantTested(mutantResult({ status: MutantStatus.Killed })); + sut.onMutantTested(factory.killedMutantResult()); expect(process.stdout.write).to.not.have.been.called; sinon.clock.tick(TEN_SECONDS); expect(process.stdout.write).to.have.been.calledWith( @@ -48,7 +53,7 @@ describe('ProgressAppendOnlyReporter', () => { }); it('should log correct info after a hundred seconds with 1 completed test', () => { - sut.onMutantTested(mutantResult({ status: MutantStatus.Killed })); + sut.onMutantTested(factory.killedMutantResult()); expect(process.stdout.write).to.not.have.been.called; sinon.clock.tick(HUNDRED_SECONDS); expect(process.stdout.write).to.have.been.calledWith( @@ -57,7 +62,7 @@ describe('ProgressAppendOnlyReporter', () => { }); it('should log correct info after a thousand seconds with 1 completed test', () => { - sut.onMutantTested(mutantResult({ status: MutantStatus.Killed })); + sut.onMutantTested(factory.killedMutantResult()); expect(process.stdout.write).to.not.have.been.called; sinon.clock.tick(THOUSAND_SECONDS); expect(process.stdout.write).to.have.been.calledWith( @@ -66,7 +71,7 @@ describe('ProgressAppendOnlyReporter', () => { }); it('should log correct info after ten thousand seconds with 1 completed test', () => { - sut.onMutantTested(mutantResult({ status: MutantStatus.TimedOut })); + sut.onMutantTested(factory.timeoutMutantResult()); expect(process.stdout.write).to.not.have.been.called; sinon.clock.tick(TEN_THOUSAND_SECONDS); expect(process.stdout.write).to.have.been.calledWith( diff --git a/packages/core/test/unit/reporters/ProgressReporter.spec.ts b/packages/core/test/unit/reporters/ProgressReporter.spec.ts index b0ecdc7196..f8ffaf62f7 100644 --- a/packages/core/test/unit/reporters/ProgressReporter.spec.ts +++ b/packages/core/test/unit/reporters/ProgressReporter.spec.ts @@ -1,9 +1,9 @@ import { MatchedMutant, MutantStatus } from '@stryker-mutator/api/report'; -import { matchedMutant, mutantResult } from '@stryker-mutator/test-helpers/src/factory'; +import { matchedMutant } from '@stryker-mutator/test-helpers/src/factory'; import { expect } from 'chai'; import * as sinon from 'sinon'; - import ProgressBar = require('progress'); +import { factory } from '@stryker-mutator/test-helpers'; import * as progressBarModule from '../../../src/reporters/ProgressBar'; import ProgressReporter from '../../../src/reporters/ProgressReporter'; @@ -34,7 +34,7 @@ describe('ProgressReporter', () => { describe('onAllMutantsMatchedWithTests()', () => { describe('when there are 3 MatchedMutants that all contain Tests', () => { beforeEach(() => { - matchedMutants = [matchedMutant(1), matchedMutant(4), matchedMutant(2)]; + matchedMutants = [matchedMutant({ runAllTests: true }), matchedMutant({ runAllTests: true }), matchedMutant({ runAllTests: true })]; sut.onAllMutantsMatchedWithTests(matchedMutants); }); @@ -45,7 +45,11 @@ describe('ProgressReporter', () => { }); describe("when there are 2 MatchedMutants that all contain Tests and 1 MatchMutant that doesn't have tests", () => { beforeEach(() => { - matchedMutants = [matchedMutant(1), matchedMutant(0), matchedMutant(2)]; + matchedMutants = [ + matchedMutant({ testFilter: undefined }), + matchedMutant({ testFilter: ['spec1'] }), + matchedMutant({ testFilter: ['spec2'] }), + ]; sut.onAllMutantsMatchedWithTests(matchedMutants); }); @@ -56,7 +60,7 @@ describe('ProgressReporter', () => { }); describe('when mutants match to all tests', () => { beforeEach(() => { - matchedMutants = [matchedMutant(0, '0', true), matchedMutant(0, '1', true)]; + matchedMutants = [matchedMutant({ runAllTests: true }), matchedMutant({ runAllTests: true })]; sut.onAllMutantsMatchedWithTests(matchedMutants); }); @@ -71,25 +75,30 @@ describe('ProgressReporter', () => { let progressBarTickTokens: any; beforeEach(() => { - matchedMutants = [matchedMutant(0), matchedMutant(1), matchedMutant(4), matchedMutant(2)]; + matchedMutants = [ + matchedMutant({ id: '0' }), // NoCoverage + matchedMutant({ id: '1', testFilter: [''] }), + matchedMutant({ id: '2', runAllTests: true }), + matchedMutant({ id: '3', testFilter: [''] }), + ]; sut.onAllMutantsMatchedWithTests(matchedMutants); }); it('should tick the ProgressBar with 1 tested mutant, 0 survived when status is not "Survived"', () => { - sut.onMutantTested(mutantResult({ status: MutantStatus.Killed })); + sut.onMutantTested(factory.killedMutantResult()); progressBarTickTokens = { total: 3, tested: 1, survived: 0 }; expect(progressBar.tick).to.have.been.calledWithMatch(progressBarTickTokens); }); it("should not tick the ProgressBar if the result was for a mutant that wasn't matched to any tests", () => { // mutant 0 isn't matched to any tests - sut.onMutantTested(mutantResult({ id: '0', status: MutantStatus.TranspileError })); + sut.onMutantTested(factory.invalidMutantResult({ id: '0', status: MutantStatus.CompileError })); progressBarTickTokens = { total: 3, tested: 0, survived: 0 }; expect(progressBar.tick).to.not.have.been.called; }); it('should tick the ProgressBar with 1 survived mutant when status is "Survived"', () => { - sut.onMutantTested(mutantResult({ status: MutantStatus.Survived })); + sut.onMutantTested(factory.undetectedMutantResult({ status: MutantStatus.Survived })); progressBarTickTokens = { total: 3, tested: 1, survived: 1 }; expect(progressBar.tick).to.have.been.calledWithMatch(progressBarTickTokens); }); @@ -97,13 +106,17 @@ describe('ProgressReporter', () => { describe('ProgressBar estimated time for 3 mutants', () => { beforeEach(() => { - sut.onAllMutantsMatchedWithTests([matchedMutant(1), matchedMutant(1), matchedMutant(1)]); + sut.onAllMutantsMatchedWithTests([ + matchedMutant({ id: '1', runAllTests: true }), + matchedMutant({ id: '2', runAllTests: true }), + matchedMutant({ id: '3', runAllTests: true }), + ]); }); it('should show correct time info after ten seconds and 1 mutants tested', () => { sinon.clock.tick(TEN_SECONDS); - sut.onMutantTested(mutantResult({ status: MutantStatus.Killed })); + sut.onMutantTested(factory.killedMutantResult({ id: '1' })); expect(progressBar.tick).to.have.been.calledWithMatch({ et: '<1m', etc: '<1m' }); }); @@ -111,7 +124,7 @@ describe('ProgressReporter', () => { it('should show correct time info after a hundred seconds and 1 mutants tested', () => { sinon.clock.tick(HUNDRED_SECONDS); - sut.onMutantTested(mutantResult({ status: MutantStatus.Killed })); + sut.onMutantTested(factory.killedMutantResult({ id: '1' })); expect(progressBar.tick).to.have.been.calledWithMatch({ et: '~1m', etc: '~3m' }); }); @@ -119,7 +132,7 @@ describe('ProgressReporter', () => { it('should show correct time info after ten thousand seconds and 1 mutants tested', () => { sinon.clock.tick(TEN_THOUSAND_SECONDS); - sut.onMutantTested(mutantResult({ status: MutantStatus.Killed })); + sut.onMutantTested(factory.killedMutantResult({ id: '1' })); expect(progressBar.tick).to.have.been.calledWithMatch({ et: '~2h 46m', etc: '~5h 33m' }); }); @@ -127,7 +140,7 @@ describe('ProgressReporter', () => { it('should show correct time info after an hour and 1 mutants tested', () => { sinon.clock.tick(ONE_HOUR); - sut.onMutantTested(mutantResult({ status: MutantStatus.Killed })); + sut.onMutantTested(factory.killedMutantResult({ id: '1', status: MutantStatus.Killed })); expect(progressBar.tick).to.have.been.calledWithMatch({ et: '~1h 0m', etc: '~2h 0m' }); }); diff --git a/packages/core/test/unit/sandbox/create-preprocessor.spec.ts b/packages/core/test/unit/sandbox/create-preprocessor.spec.ts new file mode 100644 index 0000000000..2cd3b13a2d --- /dev/null +++ b/packages/core/test/unit/sandbox/create-preprocessor.spec.ts @@ -0,0 +1,29 @@ +import path = require('path'); + +import { testInjector, assertions } from '@stryker-mutator/test-helpers'; +import { File } from '@stryker-mutator/api/core'; + +import { FilePreprocessor, createPreprocessor } from '../../../src/sandbox'; + +describe(createPreprocessor.name, () => { + let sut: FilePreprocessor; + + beforeEach(() => { + sut = testInjector.injector.injectFunction(createPreprocessor); + }); + + it('should rewrite tsconfig files', async () => { + const output = await sut.preprocess([new File(path.resolve('tsconfig.json'), '{"extends": "../tsconfig.settings.json" }')]); + assertions.expectTextFilesEqual(output, [new File(path.resolve('tsconfig.json'), '{\n "extends": "../../../tsconfig.settings.json"\n}')]); + }); + + it('should disable type checking for .ts files', async () => { + const output = await sut.preprocess([new File(path.resolve('src/app.ts'), 'foo.bar()')]); + assertions.expectTextFilesEqual(output, [new File(path.resolve('src/app.ts'), '// @ts-nocheck\nfoo.bar()')]); + }); + + it('should strip // @ts-expect-error (see https://github.com/stryker-mutator/stryker/issues/2364)', async () => { + const output = await sut.preprocess([new File(path.resolve('src/app.ts'), '// @ts-expect-error\nfoo.bar()')]); + assertions.expectTextFilesEqual(output, [new File(path.resolve('src/app.ts'), '// @ts-nocheck\n// \nfoo.bar()')]); + }); +}); diff --git a/packages/core/test/unit/sandbox/disable-type-checks-preprocessor.spec.ts b/packages/core/test/unit/sandbox/disable-type-checks-preprocessor.spec.ts new file mode 100644 index 0000000000..1124a5e649 --- /dev/null +++ b/packages/core/test/unit/sandbox/disable-type-checks-preprocessor.spec.ts @@ -0,0 +1,74 @@ +import path = require('path'); + +import { File } from '@stryker-mutator/api/core'; +import { assertions, testInjector } from '@stryker-mutator/test-helpers'; +import sinon = require('sinon'); + +import { expect } from 'chai'; + +import { coreTokens } from '../../../src/di'; +import { DisableTypeChecksPreprocessor } from '../../../src/sandbox/disable-type-checks-preprocessor'; + +describe(DisableTypeChecksPreprocessor.name, () => { + let sut: DisableTypeChecksPreprocessor; + let disableTypeCheckingStub: sinon.SinonStub; + + beforeEach(() => { + disableTypeCheckingStub = sinon.stub(); + sut = testInjector.injector.provideValue(coreTokens.disableTypeChecksHelper, disableTypeCheckingStub).injectClass(DisableTypeChecksPreprocessor); + }); + + ['.ts', '.tsx', '.js', '.jsx', '.html', '.vue'].forEach((extension) => { + it(`should disable type checking a ${extension} file by default`, async () => { + const fileName = `src/app${extension}`; + const expectedFile = new File(path.resolve(fileName), 'output'); + const inputFile = new File(path.resolve(fileName), 'input'); + const input = [inputFile]; + disableTypeCheckingStub.resolves(expectedFile); + const output = await sut.preprocess(input); + expect(disableTypeCheckingStub).calledWith(inputFile); + assertions.expectTextFilesEqual(output, [expectedFile]); + }); + }); + + it('should be able to override "disableTypeChecks" glob pattern', async () => { + testInjector.options.disableTypeChecks = 'src/**/*.ts'; + const expectedFile = new File(path.resolve('src/app.ts'), 'output'); + const input = [new File(path.resolve('src/app.ts'), 'input')]; + disableTypeCheckingStub.resolves(expectedFile); + const output = await sut.preprocess(input); + assertions.expectTextFilesEqual(output, [expectedFile]); + }); + + it('should not disable type checking when the "disableTypeChecks" glob pattern does not match', async () => { + testInjector.options.disableTypeChecks = 'src/**/*.ts'; + const expectedFiles = [new File(path.resolve('test/app.spec.ts'), 'input')]; + disableTypeCheckingStub.resolves(new File('', 'not expected')); + const output = await sut.preprocess(expectedFiles); + assertions.expectTextFilesEqual(output, expectedFiles); + }); + + it('should not disable type checking if "disableTypeChecks" is set to `false`', async () => { + const input = [ + new File(path.resolve('src/app.ts'), '// @ts-expect-error\nfoo.bar();'), + new File(path.resolve('test/app.spec.ts'), '/* @ts-expect-error */\nfoo.bar();'), + new File(path.resolve('testResources/project/app.ts'), '/* @ts-expect-error */\nfoo.bar();'), + ]; + testInjector.options.disableTypeChecks = false; + const output = await sut.preprocess(input); + assertions.expectTextFilesEqual(output, input); + }); + + it('should not crash on error, instead log a warning', async () => { + const input = [new File('src/app.ts', 'input')]; + const expectedError = new Error('Expected error for testing'); + disableTypeCheckingStub.rejects(expectedError); + const output = await sut.preprocess(input); + expect(testInjector.logger.warn).calledWithExactly( + 'Unable to disable type checking for file "src/app.ts". Shouldn\'t type checking be disabled for this file? Consider configuring a more restrictive "disableTypeChecks" settings (or turn it completely off with `false`)', + expectedError + ); + expect(testInjector.logger.warn).calledWithExactly('(disable "warnings.preprocessorErrors" to ignore this warning'); + assertions.expectTextFilesEqual(output, input); + }); +}); diff --git a/packages/core/test/unit/sandbox/multi-preprocessor.spec.ts b/packages/core/test/unit/sandbox/multi-preprocessor.spec.ts new file mode 100644 index 0000000000..2fce332aa6 --- /dev/null +++ b/packages/core/test/unit/sandbox/multi-preprocessor.spec.ts @@ -0,0 +1,36 @@ +import sinon = require('sinon'); +import { File } from '@stryker-mutator/api/core'; +import { expect } from 'chai'; + +import { MultiPreprocessor } from '../../../src/sandbox/multi-preprocessor'; +import { FilePreprocessor } from '../../../src/sandbox'; + +describe(MultiPreprocessor.name, () => { + describe(MultiPreprocessor.prototype.preprocess.name, () => { + it('should call preprocess on each preprocessor in order', async () => { + // Arrange + const input = [new File('foo.js', 'input')]; + const firstResult = [new File('foo.js', 'first')]; + const secondResult = [new File('foo.js', 'second')]; + const first = createFilePreprocessorMock(); + const second = createFilePreprocessorMock(); + first.preprocess.resolves(firstResult); + second.preprocess.resolves(secondResult); + const sut = new MultiPreprocessor([first, second]); + + // Act + const actual = await sut.preprocess(input); + + // Assert + expect(actual).eq(secondResult); + expect(first.preprocess).calledWith(input); + expect(second.preprocess).calledWith(firstResult); + }); + }); + + function createFilePreprocessorMock(): sinon.SinonStubbedInstance { + return { + preprocess: sinon.stub(), + }; + } +}); diff --git a/packages/core/test/unit/sandbox/sandbox.spec.ts b/packages/core/test/unit/sandbox/sandbox.spec.ts new file mode 100644 index 0000000000..04aed65de5 --- /dev/null +++ b/packages/core/test/unit/sandbox/sandbox.spec.ts @@ -0,0 +1,189 @@ +import path = require('path'); + +import execa = require('execa'); +import npmRunPath = require('npm-run-path'); +import { expect } from 'chai'; +import sinon = require('sinon'); +import * as mkdirp from 'mkdirp'; +import { testInjector, tick } from '@stryker-mutator/test-helpers'; +import { File } from '@stryker-mutator/api/core'; +import { fileAlreadyExistsError } from '@stryker-mutator/test-helpers/src/factory'; +import { normalizeWhitespaces, Task } from '@stryker-mutator/util'; + +import { Sandbox } from '../../../src/sandbox/sandbox'; +import { coreTokens } from '../../../src/di'; +import { TemporaryDirectory } from '../../../src/utils/TemporaryDirectory'; +import * as fileUtils from '../../../src/utils/fileUtils'; + +describe(Sandbox.name, () => { + let temporaryDirectoryMock: sinon.SinonStubbedInstance; + let files: File[]; + let mkdirpSyncStub: sinon.SinonStub; + let writeFileStub: sinon.SinonStub; + let symlinkJunctionStub: sinon.SinonStub; + let findNodeModulesStub: sinon.SinonStub; + let execaMock: sinon.SinonStubbedInstance; + const SANDBOX_WORKING_DIR = 'sandbox-123'; + + beforeEach(() => { + temporaryDirectoryMock = sinon.createStubInstance(TemporaryDirectory); + temporaryDirectoryMock.createRandomDirectory.returns(SANDBOX_WORKING_DIR); + mkdirpSyncStub = sinon.stub(mkdirp, 'sync'); + writeFileStub = sinon.stub(fileUtils, 'writeFile'); + symlinkJunctionStub = sinon.stub(fileUtils, 'symlinkJunction'); + findNodeModulesStub = sinon.stub(fileUtils, 'findNodeModules'); + execaMock = { + command: sinon.stub(), + commandSync: sinon.stub(), + node: sinon.stub(), + sync: sinon.stub(), + }; + symlinkJunctionStub.resolves(); + findNodeModulesStub.resolves('node_modules'); + files = []; + }); + + function createSut(): Promise { + return testInjector.injector + .provideValue(coreTokens.files, files) + .provideValue(coreTokens.temporaryDirectory, temporaryDirectoryMock) + .provideValue(coreTokens.execa, (execaMock as unknown) as typeof execa) + .injectFunction(Sandbox.create); + } + + describe('create()', () => { + it('should have created a sandbox folder', async () => { + await createSut(); + expect(temporaryDirectoryMock.createRandomDirectory).calledWith('sandbox'); + }); + + it('should copy regular input files', async () => { + const fileB = new File(path.resolve('a', 'b.txt'), 'b content'); + const fileE = new File(path.resolve('c', 'd', 'e.log'), 'e content'); + files.push(fileB); + files.push(fileE); + await createSut(); + expect(writeFileStub).calledWith(path.join(SANDBOX_WORKING_DIR, 'a', 'b.txt'), fileB.content); + expect(writeFileStub).calledWith(path.join(SANDBOX_WORKING_DIR, 'c', 'd', 'e.log'), fileE.content); + }); + + it('should make the dir before copying the file', async () => { + files.push(new File(path.resolve('a', 'b.js'), 'b content')); + files.push(new File(path.resolve('c', 'd', 'e.js'), 'e content')); + await createSut(); + expect(mkdirpSyncStub).calledTwice; + expect(mkdirpSyncStub).calledWithExactly(path.join(SANDBOX_WORKING_DIR, 'a')); + expect(mkdirpSyncStub).calledWithExactly(path.join(SANDBOX_WORKING_DIR, 'c', 'd')); + }); + + it('should be able to copy a local file', async () => { + files.push(new File('localFile.txt', 'foobar')); + await createSut(); + expect(writeFileStub).calledWith(path.join(SANDBOX_WORKING_DIR, 'localFile.txt'), Buffer.from('foobar')); + }); + + it('should not open too many file handles', async () => { + const maxFileIO = 256; + const fileHandles: Array<{ fileName: string; task: Task }> = []; + for (let i = 0; i < maxFileIO + 1; i++) { + const fileName = `file_${i}.js`; + const task = new Task(); + fileHandles.push({ fileName, task }); + writeFileStub.withArgs(sinon.match(fileName)).returns(task.promise); + files.push(new File(fileName, '')); + } + + // Act + const onGoingWork = createSut(); + await tick(); + expect(writeFileStub).callCount(maxFileIO); + fileHandles[0].task.resolve(); + await tick(); + + // Assert + expect(writeFileStub).callCount(maxFileIO + 1); + fileHandles.forEach(({ task }) => task.resolve()); + await onGoingWork; + }); + + it('should symlink node modules in sandbox directory if exists', async () => { + await createSut(); + expect(findNodeModulesStub).calledWith(process.cwd()); + expect(symlinkJunctionStub).calledWith('node_modules', path.join(SANDBOX_WORKING_DIR, 'node_modules')); + }); + + it('should not symlink node modules in sandbox directory if no node_modules exist', async () => { + findNodeModulesStub.resolves(null); + await createSut(); + expect(testInjector.logger.warn).calledWithMatch('Could not find a node_modules'); + expect(testInjector.logger.warn).calledWithMatch(process.cwd()); + expect(symlinkJunctionStub).not.called; + }); + + it('should log a warning if "node_modules" already exists in the working folder', async () => { + findNodeModulesStub.resolves('node_modules'); + symlinkJunctionStub.rejects(fileAlreadyExistsError()); + await createSut(); + expect(testInjector.logger.warn).calledWithMatch( + normalizeWhitespaces( + `Could not symlink "node_modules" in sandbox directory, it is already created in the sandbox. + Please remove the node_modules from your sandbox files. Alternatively, set \`symlinkNodeModules\` + to \`false\` to disable this warning.` + ) + ); + }); + + it('should log a warning if linking "node_modules" results in an unknown error', async () => { + findNodeModulesStub.resolves('basePath/node_modules'); + const error = new Error('unknown'); + symlinkJunctionStub.rejects(error); + await createSut(); + expect(testInjector.logger.warn).calledWithMatch( + normalizeWhitespaces('Unexpected error while trying to symlink "basePath/node_modules" in sandbox directory.'), + error + ); + }); + + it('should symlink node modules in sandbox directory if `symlinkNodeModules` is `false`', async () => { + testInjector.options.symlinkNodeModules = false; + await createSut(); + expect(symlinkJunctionStub).not.called; + expect(findNodeModulesStub).not.called; + }); + + it('should execute the buildCommand in the sandbox', async () => { + testInjector.options.buildCommand = 'npm run build'; + await createSut(); + expect(execaMock.command).calledWith('npm run build', { cwd: SANDBOX_WORKING_DIR, env: npmRunPath.env() }); + expect(testInjector.logger.info).calledWith('Running build command "%s" in the sandbox at "%s".', 'npm run build', SANDBOX_WORKING_DIR); + }); + + it('should not execute a build command when non is configured', async () => { + testInjector.options.buildCommand = undefined; + await createSut(); + expect(execaMock.command).not.called; + }); + + it('should execute the buildCommand before the node_modules are symlinked', async () => { + // It is important to first run the buildCommand, otherwise the build dependencies are not correctly resolved + testInjector.options.buildCommand = 'npm run build'; + await createSut(); + expect(execaMock.command).calledBefore(symlinkJunctionStub); + }); + }); + + describe('get sandboxFileNames()', () => { + it('should retrieve all files', async () => { + files.push(new File('a.js', '')); + files.push(new File(path.resolve('b', 'c', 'e.js'), '')); + const sut = await createSut(); + expect(sut.sandboxFileNames).deep.eq([path.join(SANDBOX_WORKING_DIR, 'a.js'), path.join(SANDBOX_WORKING_DIR, 'b', 'c', 'e.js')]); + }); + }); + describe('workingDirectory', () => { + it('should retrieve the sandbox directory', async () => { + const sut = await createSut(); + expect(sut.workingDirectory).eq(SANDBOX_WORKING_DIR); + }); + }); +}); diff --git a/packages/core/test/unit/sandbox/ts-config-preprocessor.it.spec.ts b/packages/core/test/unit/sandbox/ts-config-preprocessor.it.spec.ts new file mode 100644 index 0000000000..df116235ed --- /dev/null +++ b/packages/core/test/unit/sandbox/ts-config-preprocessor.it.spec.ts @@ -0,0 +1,116 @@ +import path = require('path'); + +import { expect } from 'chai'; +import { File } from '@stryker-mutator/api/core'; +import { testInjector } from '@stryker-mutator/test-helpers'; + +import { TSConfigPreprocessor } from '../../../src/sandbox/ts-config-preprocessor'; + +describe(TSConfigPreprocessor.name, () => { + let files: File[]; + let sut: TSConfigPreprocessor; + + beforeEach(() => { + files = []; + sut = testInjector.injector.injectClass(TSConfigPreprocessor); + }); + + it('should not do anything if the tsconfig file does not exist', async () => { + files.push(new File('foo.js', 'console.log("foo");')); + const output = await sut.preprocess(files); + expect(output).eq(files); + }); + + it('should ignore missing "extends"', async () => { + files.push(tsconfigFile('tsconfig.json', { references: [{ path: './tsconfig.src.json' }] })); + const output = await sut.preprocess(files); + expect(output).deep.eq(files); + }); + + it('should ignore missing "references"', async () => { + files.push(tsconfigFile('tsconfig.json', { extends: './tsconfig.settings.json' })); + const output = await sut.preprocess(files); + expect(output).deep.eq(files); + }); + + it('should rewrite "extends" if it falls outside of sandbox', async () => { + files.push(tsconfigFile('tsconfig.json', { extends: '../tsconfig.settings.json' })); + const output = await sut.preprocess(files); + expect(output).deep.eq([tsconfigFile('tsconfig.json', { extends: '../../../tsconfig.settings.json' })]); + }); + + it('should support comments and other settings', async () => { + files.push( + new File( + path.resolve(process.cwd(), 'tsconfig.json'), + `{ + "extends": "../tsconfig.settings.json", + "compilerOptions": { + // Here are the options + "target": "es5", // and a trailing comma + } + }` + ) + ); + const output = await sut.preprocess(files); + expect(output).deep.eq([tsconfigFile('tsconfig.json', { extends: '../../../tsconfig.settings.json', compilerOptions: { target: 'es5' } })]); + }); + + it('should rewrite "references" if it falls outside of sandbox', async () => { + files.push(tsconfigFile('tsconfig.json', { references: [{ path: '../model' }] })); + const output = await sut.preprocess(files); + expect(output).deep.eq([tsconfigFile('tsconfig.json', { references: [{ path: '../../../model/tsconfig.json' }] })]); + }); + + it('should rewrite referenced tsconfig files that are also located in the sandbox', async () => { + files.push(tsconfigFile('tsconfig.json', { extends: './tsconfig.settings.json', references: [{ path: './src' }] })); + files.push(tsconfigFile('tsconfig.settings.json', { extends: '../../tsconfig.root-settings.json' })); + files.push(tsconfigFile('src/tsconfig.json', { references: [{ path: '../../model' }] })); + const output = await sut.preprocess(files); + expect(output).deep.eq([ + tsconfigFile('tsconfig.json', { extends: './tsconfig.settings.json', references: [{ path: './src' }] }), + tsconfigFile('tsconfig.settings.json', { extends: '../../../../tsconfig.root-settings.json' }), + tsconfigFile('src/tsconfig.json', { references: [{ path: '../../../../model/tsconfig.json' }] }), + ]); + }); + + it('should be able to rewrite a monorepo style project', async () => { + // Arrange + files.push( + tsconfigFile('tsconfig.root.json', { + extends: '../../tsconfig.settings.json', + references: [{ path: 'src' }, { path: 'test/tsconfig.test.json' }], + }) + ); + files.push(tsconfigFile('src/tsconfig.json', { extends: '../../../tsconfig.settings.json', references: [{ path: '../../model' }] })); + files.push(tsconfigFile('test/tsconfig.test.json', { extends: '../tsconfig.root.json', references: [{ path: '../src' }] })); + testInjector.options.tsconfigFile = 'tsconfig.root.json'; + + // Act + const actual = await sut.preprocess(files); + + // Assert + const expected = [ + tsconfigFile('tsconfig.root.json', { + extends: '../../../../tsconfig.settings.json', + references: [{ path: 'src' }, { path: 'test/tsconfig.test.json' }], + }), + tsconfigFile('src/tsconfig.json', { + extends: '../../../../../tsconfig.settings.json', + references: [{ path: '../../../../model/tsconfig.json' }], + }), + tsconfigFile('test/tsconfig.test.json', { extends: '../tsconfig.root.json', references: [{ path: '../src' }] }), + ]; + expect(actual).deep.eq(expected); + }); + + function tsconfigFile(fileName: string, content: TSConfig) { + return new File(path.resolve(fileName), JSON.stringify(content, null, 2)); + } + + interface TSConfig { + extends?: string; + references?: Array<{ path: string }>; + [key: string]: unknown; + } +}); diff --git a/packages/core/test/unit/test-runner/ChildProcessTestRunnerDecorator.spec.ts b/packages/core/test/unit/test-runner/ChildProcessTestRunnerDecorator.spec.ts index fe39b8a9f1..f1055703d3 100644 --- a/packages/core/test/unit/test-runner/ChildProcessTestRunnerDecorator.spec.ts +++ b/packages/core/test/unit/test-runner/ChildProcessTestRunnerDecorator.spec.ts @@ -1,23 +1,24 @@ import { LogLevel, StrykerOptions } from '@stryker-mutator/api/core'; -import { RunOptions } from '@stryker-mutator/api/test_runner'; import { strykerOptions } from '@stryker-mutator/test-helpers/src/factory'; import { expect } from 'chai'; import * as sinon from 'sinon'; +import { Task } from '@stryker-mutator/util'; + +import { TestRunner } from '@stryker-mutator/api/test_runner'; + +import { factory } from '@stryker-mutator/test-helpers'; import ChildProcessCrashedError from '../../../src/child-proxy/ChildProcessCrashedError'; import ChildProcessProxy from '../../../src/child-proxy/ChildProcessProxy'; -import LoggingClientContext from '../../../src/logging/LoggingClientContext'; +import { LoggingClientContext } from '../../../src/logging'; import ChildProcessTestRunnerDecorator from '../../../src/test-runner/ChildProcessTestRunnerDecorator'; import { ChildProcessTestRunnerWorker } from '../../../src/test-runner/ChildProcessTestRunnerWorker'; -import TestRunnerDecorator from '../../../src/test-runner/TestRunnerDecorator'; -import { Task } from '../../../src/utils/Task'; -import { Mock, mock } from '../../helpers/producers'; describe(ChildProcessTestRunnerDecorator.name, () => { let sut: ChildProcessTestRunnerDecorator; let options: StrykerOptions; let childProcessProxyMock: { - proxy: Mock; + proxy: sinon.SinonStubbedInstance>; dispose: sinon.SinonStub; }; let childProcessProxyCreateStub: sinon.SinonStub; @@ -28,7 +29,7 @@ describe(ChildProcessTestRunnerDecorator.name, () => { clock = sinon.useFakeTimers(); childProcessProxyMock = { dispose: sinon.stub(), - proxy: mock(TestRunnerDecorator), + proxy: factory.testRunner(), }; childProcessProxyCreateStub = sinon.stub(ChildProcessProxy, 'create'); childProcessProxyCreateStub.returns(childProcessProxyMock); @@ -36,7 +37,7 @@ describe(ChildProcessTestRunnerDecorator.name, () => { plugins: ['foo-plugin', 'bar-plugin'], }); loggingContext = { port: 4200, level: LogLevel.Fatal }; - sut = new ChildProcessTestRunnerDecorator(options, [], 'a working directory', loggingContext); + sut = new ChildProcessTestRunnerDecorator(options, 'a working directory', loggingContext); }); it('should create the child process proxy', () => { @@ -44,7 +45,7 @@ describe(ChildProcessTestRunnerDecorator.name, () => { require.resolve('../../../src/test-runner/ChildProcessTestRunnerWorker.js'), loggingContext, options, - { sandboxFileNames: [] }, + {}, 'a working directory', ChildProcessTestRunnerWorker ); @@ -55,13 +56,26 @@ describe(ChildProcessTestRunnerDecorator.name, () => { return expect(sut.init()).eventually.eq(42); }); - it('should forward `run` calls', async () => { - childProcessProxyMock.proxy.run.resolves(42); - const runOptions: RunOptions = { + it('should forward `dryRun` calls', async () => { + const expectedResult = factory.completeDryRunResult({ mutantCoverage: factory.mutantCoverage() }); + childProcessProxyMock.proxy.dryRun.resolves(expectedResult); + const runOptions = factory.dryRunOptions({ timeout: 234, - }; - await expect(sut.run(runOptions)).eventually.eq(42); - expect(childProcessProxyMock.proxy.run).calledWith(runOptions); + }); + const actualResult = await sut.dryRun(runOptions); + expect(actualResult).eq(expectedResult); + expect(childProcessProxyMock.proxy.dryRun).calledWith(runOptions); + }); + + it('should forward `mutantRun` calls', async () => { + const expectedResult = factory.survivedMutantRunResult(); + childProcessProxyMock.proxy.mutantRun.resolves(expectedResult); + const runOptions = factory.mutantRunOptions({ + timeout: 234, + }); + const actualResult = await sut.mutantRun(runOptions); + expect(actualResult).eq(expectedResult); + expect(childProcessProxyMock.proxy.mutantRun).calledWith(runOptions); }); describe('dispose', () => { diff --git a/packages/core/test/unit/test-runner/CommandTestRunner.spec.ts b/packages/core/test/unit/test-runner/CommandTestRunner.spec.ts index 061363cbbf..04f5e33b11 100644 --- a/packages/core/test/unit/test-runner/CommandTestRunner.spec.ts +++ b/packages/core/test/unit/test-runner/CommandTestRunner.spec.ts @@ -1,11 +1,11 @@ import * as childProcess from 'child_process'; import * as os from 'os'; -import { RunResult, RunStatus, TestStatus } from '@stryker-mutator/api/test_runner'; -import { errorToString } from '@stryker-mutator/util'; +import { DryRunResult, DryRunStatus, TestStatus } from '@stryker-mutator/api/test_runner'; +import { errorToString, StrykerError } from '@stryker-mutator/util'; import { expect } from 'chai'; import * as sinon from 'sinon'; -import { factory } from '@stryker-mutator/test-helpers'; +import { factory, assertions } from '@stryker-mutator/test-helpers'; import { CommandRunnerOptions } from '@stryker-mutator/api/core'; import CommandTestRunner from '../../../src/test-runner/CommandTestRunner'; @@ -27,23 +27,23 @@ describe(CommandTestRunner.name, () => { sinon.stub(timerModule, 'default').returns(timerMock); }); - describe('run', () => { + describe(CommandTestRunner.prototype.dryRun.name, () => { it('should run `npm test` by default', async () => { - await actRun(createSut(undefined, 'foobarDir')); - expect(childProcess.exec).calledWith('npm test', { cwd: 'foobarDir' }); + await actDryRun(createSut(undefined, 'foobarDir')); + expect(childProcess.exec).calledWith('npm test', { cwd: 'foobarDir', env: process.env }); }); it('should allow other commands using configuration', async () => { - await actRun(createSut({ command: 'some other command' })); + await actDryRun(createSut({ command: 'some other command' })); expect(childProcess.exec).calledWith('some other command'); }); it('should report successful test when the exit code = 0', async () => { timerMock.elapsedMs.returns(42); - const result = await actRun(); - const expectedResult: RunResult = { - status: RunStatus.Complete, - tests: [{ name: 'All tests', status: TestStatus.Success, timeSpentMs: 42 }], + const result = await actDryRun(); + const expectedResult: DryRunResult = { + status: DryRunStatus.Complete, + tests: [{ id: 'all', name: 'All tests', status: TestStatus.Success, timeSpentMs: 42 }], }; expect(result).deep.eq(expectedResult); }); @@ -51,15 +51,15 @@ describe(CommandTestRunner.name, () => { it('should report failed test when the exit code != 0', async () => { timerMock.elapsedMs.returns(42); const sut = createSut(); - const resultPromise = sut.run(); + const resultPromise = sut.dryRun({ coverageAnalysis: 'off' }); await tick(); childProcessMock.stdout.emit('data', 'x Test 1 failed'); childProcessMock.stderr.emit('data', '1 != 2'); childProcessMock.emit('exit', 1); const result = await resultPromise; - const expectedResult: RunResult = { - status: RunStatus.Complete, - tests: [{ name: 'All tests', status: TestStatus.Failed, timeSpentMs: 42, failureMessages: [`x Test 1 failed${os.EOL}1 != 2`] }], + const expectedResult: DryRunResult = { + status: DryRunStatus.Complete, + tests: [{ id: 'all', name: 'All tests', status: TestStatus.Failed, timeSpentMs: 42, failureMessage: `x Test 1 failed${os.EOL}1 != 2` }], }; expect(result).deep.eq(expectedResult); }); @@ -68,56 +68,87 @@ describe(CommandTestRunner.name, () => { killStub.resolves(); const expectedError = new Error('foobar error'); const sut = createSut(); - const resultPromise = sut.run(); + const resultPromise = sut.dryRun({ coverageAnalysis: 'off' }); await tick(); childProcessMock.emit('error', expectedError); const result = await resultPromise; - const expectedResult: RunResult = { - errorMessages: [errorToString(expectedError)], - status: RunStatus.Error, - tests: [], + const expectedResult: DryRunResult = { + errorMessage: errorToString(expectedError), + status: DryRunStatus.Error, }; expect(result).deep.eq(expectedResult); }); it('should remove all listeners on exit', async () => { - await actRun(); + await actDryRun(); expect(childProcessMock.listenerCount('exit')).eq(0); expect(childProcessMock.listenerCount('error')).eq(0); expect(childProcessMock.stdout.listenerCount('data')).eq(0); expect(childProcessMock.stderr.listenerCount('data')).eq(0); }); + + it('should reject if coverageAnalysis !== "off"', async () => { + const sut = createSut(); + await expect(sut.dryRun({ coverageAnalysis: 'all' })).rejectedWith( + StrykerError, + 'The "command" test runner does not support coverageAnalysis "all".' + ); + }); + }); + + describe(CommandTestRunner.prototype.mutantRun.name, () => { + it('should run with __ACTIVE_MUTANT__ environment variable active', async () => { + const sut = createSut(undefined, 'foobarDir'); + await actMutantRun(sut, { activeMutantId: 0 }); + expect(childProcess.exec).calledWith('npm test', { cwd: 'foobarDir', env: { ...process.env, __STRYKER_ACTIVE_MUTANT__: '0' } }); + }); + + it('should convert exit code 0 to a survived mutant', async () => { + const result = await actMutantRun(createSut(), { exitCode: 0 }); + assertions.expectSurvived(result); + }); + + it('should convert exit code 1 to a killed mutant', async () => { + const result = await actMutantRun(createSut(), { exitCode: 1 }); + assertions.expectKilled(result); + expect(result.killedBy).eq('all'); + }); }); describe('dispose', () => { it('should kill any running process', async () => { killStub.resolves(); const sut = createSut(); - sut.run(); + sut.dryRun({ coverageAnalysis: 'off' }); await sut.dispose(); expect(killStub).calledWith(childProcessMock.pid); }); it('should resolve running processes in a timeout', async () => { const sut = createSut(); - const resultPromise = sut.run(); + const resultPromise = sut.dryRun({ coverageAnalysis: 'off' }); await sut.dispose(); const result = await resultPromise; - expect(RunStatus[result.status]).eq(RunStatus[RunStatus.Timeout]); + expect(result.status).eq(DryRunStatus.Timeout); }); it('should not kill anything if running process was already resolved', async () => { const sut = createSut(); - await actRun(sut); + await actDryRun(sut); sut.dispose(); expect(killStub).not.called; }); }); - async function actRun(sut: CommandTestRunner = createSut(), exitCode = 0) { - const resultPromise = sut.run(); - await tick(); - childProcessMock.emit('exit', exitCode); + async function actDryRun(sut: CommandTestRunner = createSut(), exitCode = 0) { + const resultPromise = sut.dryRun({ coverageAnalysis: 'off' }); + await actTestProcessEnds(exitCode); + return resultPromise; + } + + async function actMutantRun(sut: CommandTestRunner = createSut(), { exitCode = 0, activeMutantId = 0 }) { + const resultPromise = sut.mutantRun({ activeMutant: factory.mutant({ id: activeMutantId }) }); + await actTestProcessEnds(exitCode); return resultPromise; } @@ -132,4 +163,8 @@ describe(CommandTestRunner.name, () => { function tick(): Promise { return new Promise((res) => setTimeout(res, 0)); } + async function actTestProcessEnds(exitCode: number) { + await tick(); + childProcessMock.emit('exit', exitCode); + } }); diff --git a/packages/core/test/unit/test-runner/MaxTestRunnerReuseDecorator.spec.ts b/packages/core/test/unit/test-runner/MaxTestRunnerReuseDecorator.spec.ts new file mode 100644 index 0000000000..30f4236b4e --- /dev/null +++ b/packages/core/test/unit/test-runner/MaxTestRunnerReuseDecorator.spec.ts @@ -0,0 +1,88 @@ +import { TestRunner } from '@stryker-mutator/api/test_runner'; +import { expect } from 'chai'; +import * as sinon from 'sinon'; +import { factory } from '@stryker-mutator/test-helpers'; + +import TestRunnerDecorator from '../../../src/test-runner/TestRunnerDecorator'; +import MaxTestRunnerReuseDecorator from '../../../src/test-runner/MaxTestRunnerReuseDecorator'; + +describe(MaxTestRunnerReuseDecorator.name, () => { + let testRunner: sinon.SinonStubbedInstance>; + const runOptions = factory.mutantRunOptions({ timeout: 23 }); + + beforeEach(() => { + testRunner = factory.testRunner(); + }); + + const getSut = (maxTestRunnerReuse: number) => { + const sut = new MaxTestRunnerReuseDecorator(() => testRunner, { maxTestRunnerReuse: maxTestRunnerReuse }); + sinon.spy(sut, 'dispose'); + return sut; + }; + + it('should not override `init`', () => { + expect(getSut(1).init).to.be.eq(TestRunnerDecorator.prototype.init); + }); + + it('should override `dispose`', () => { + expect(getSut(1).dispose).to.not.be.eq(TestRunnerDecorator.prototype.dispose); + }); + + it('should not override `dryRun`', () => { + expect(getSut(1).dryRun).to.be.eq(TestRunnerDecorator.prototype.dryRun); + }); + + it('should pass through resolved values', async () => { + const sut = getSut(0); + const options = factory.mutantRunOptions({ timeout: 23 }); + const expectedResult = factory.completeDryRunResult(); + testRunner.mutantRun.resolves(expectedResult); + const result = await sut.mutantRun(options); + expect(testRunner.mutantRun).to.have.been.calledWith(options); + expect(result).to.eq(expectedResult); + }); + + it('should not dispose worker if restartAfterRuns is set to 0', async () => { + const sut = getSut(0); + const expectedResult = factory.completeDryRunResult(); + testRunner.mutantRun.resolves(expectedResult); + + await sut.mutantRun(runOptions); + const result = await sut.mutantRun(runOptions); + + expect(sut.dispose).to.have.been.callCount(0); + expect(result).to.eq(expectedResult); + }); + + it('should dispose worker on second run if restartAfterRuns is set to 1', async () => { + const sut = getSut(1); + const expectedResult = factory.completeDryRunResult(); + testRunner.mutantRun.resolves(expectedResult); + + await sut.mutantRun(runOptions); + const result = await sut.mutantRun(runOptions); + + expect(sut.dispose).to.have.been.callCount(1); + expect(result).to.eq(expectedResult); + }); + + it('should correctly reset runs after dispose', async () => { + const sut = getSut(2); + + await sut.mutantRun(runOptions); + expect(sut.runs).to.equal(1); + await sut.dispose(); + expect(sut.runs).to.equal(0); + }); + + it('should correctly reset runs after running more than maximum run', async () => { + const sut = getSut(2); + + await sut.mutantRun(runOptions); + expect(sut.runs).to.equal(1); + await sut.mutantRun(runOptions); + expect(sut.runs).to.equal(2); + await sut.mutantRun(runOptions); + expect(sut.runs).to.equal(1); + }); +}); diff --git a/packages/core/test/unit/test-runner/RetryDecorator.spec.ts b/packages/core/test/unit/test-runner/RetryDecorator.spec.ts index 51073bb60f..d79d2c2861 100644 --- a/packages/core/test/unit/test-runner/RetryDecorator.spec.ts +++ b/packages/core/test/unit/test-runner/RetryDecorator.spec.ts @@ -1,32 +1,32 @@ import { Logger } from '@stryker-mutator/api/logging'; -import { RunStatus } from '@stryker-mutator/api/test_runner'; import { errorToString } from '@stryker-mutator/util'; +import { TestRunner, DryRunOptions, MutantRunOptions, DryRunResult, MutantRunResult } from '@stryker-mutator/api/test_runner'; import { expect } from 'chai'; +import { factory } from '@stryker-mutator/test-helpers'; + +import { expectErrored } from '@stryker-mutator/test-helpers/src/assertions'; + import ChildProcessCrashedError from '../../../src/child-proxy/ChildProcessCrashedError'; import OutOfMemoryError from '../../../src/child-proxy/OutOfMemoryError'; import RetryDecorator from '../../../src/test-runner/RetryDecorator'; import TestRunnerDecorator from '../../../src/test-runner/TestRunnerDecorator'; import currentLogMock from '../../helpers/logMock'; -import { Mock } from '../../helpers/producers'; -import TestRunnerMock from '../../helpers/TestRunnerMock'; -describe('RetryDecorator', () => { +describe(RetryDecorator.name, () => { let sut: RetryDecorator; - let testRunner1: TestRunnerMock; - let testRunner2: TestRunnerMock; - let availableTestRunners: TestRunnerMock[]; - let logMock: Mock; - const options = { timeout: 2 }; - const expectedResult = 'something'; + let testRunner1: sinon.SinonStubbedInstance>; + let testRunner2: sinon.SinonStubbedInstance>; + let availableTestRunners: Array>>; + let logMock: sinon.SinonStubbedInstance; const crashedError = new ChildProcessCrashedError(42, ''); beforeEach(() => { - testRunner1 = new TestRunnerMock(); - testRunner2 = new TestRunnerMock(); + testRunner1 = factory.testRunner(); + testRunner2 = factory.testRunner(); logMock = currentLogMock(); availableTestRunners = [testRunner1, testRunner2]; - sut = new RetryDecorator(() => availableTestRunners.shift() || new TestRunnerMock()); + sut = new RetryDecorator(() => availableTestRunners.shift() || factory.testRunner()); }); it('should not override `init`', () => { @@ -37,55 +37,96 @@ describe('RetryDecorator', () => { expect(sut.dispose).to.be.eq(TestRunnerDecorator.prototype.dispose); }); - describe('run', () => { - it('should pass through resolved values', () => { - testRunner1.run.resolves(expectedResult); - const result = sut.run(options); - expect(testRunner1.run).to.have.been.calledWith(options); - return expect(result).to.eventually.eq(expectedResult); - }); + describeRun( + 'dryRun', + (sut, options) => sut.dryRun(options), + () => factory.dryRunOptions({ timeout: 23 }), + () => factory.completeDryRunResult() + ); + describeRun( + 'mutantRun', + (sut, options) => sut.mutantRun(options), + () => factory.mutantRunOptions({ timeout: 23 }), + () => factory.survivedMutantRunResult() + ); - it('should retry on a new test runner if a run is rejected', () => { - testRunner1.run.rejects(new Error('Error')); - testRunner2.run.resolves(expectedResult); - return expect(sut.run(options)).to.eventually.eq(expectedResult); - }); + interface RunOptionsByMethod { + dryRun: DryRunOptions; + mutantRun: MutantRunOptions; + } + interface RunResultByMethod { + dryRun: DryRunResult; + mutantRun: MutantRunResult; + } - it('should retry if a `ChildProcessCrashedError` occurred reject appears', () => { - testRunner1.run.rejects(crashedError); - testRunner2.run.resolves(expectedResult); - return expect(sut.run(options)).to.eventually.eq(expectedResult); - }); + function describeRun( + runMethod: T, + act: (sut: RetryDecorator, options: RunOptionsByMethod[T]) => Promise, + optionsFactory: () => RunOptionsByMethod[T], + resultFactory: () => RunResultByMethod[T] + ) { + describe(runMethod, () => { + let options: RunOptionsByMethod[T]; + let expectedRunResult: RunResultByMethod[T]; - it('should log and retry when an `OutOfMemoryError` occurred.', async () => { - testRunner1.run.rejects(new OutOfMemoryError(123, 123)); - testRunner2.run.resolves(expectedResult); - await expect(sut.run(options)).to.eventually.eq(expectedResult); - expect(logMock.info).calledWith( - "Test runner process [%s] ran out of memory. You probably have a memory leak in your tests. Don't worry, Stryker will restart the process, but you might want to investigate this later, because this decreases performance.", - 123 - ); - }); + beforeEach(() => { + options = optionsFactory(); + expectedRunResult = resultFactory(); + }); - it('should dispose a test runner when it rejected, before creating a new one', async () => { - testRunner1.run.rejects(crashedError); - testRunner2.run.resolves(expectedResult); - await sut.run(options); - expect(testRunner1.dispose).calledBefore(testRunner2.init); - }); + it('should pass through resolved values', async () => { + const expectedResult = factory.completeDryRunResult(); + testRunner1[runMethod].resolves(expectedResult); + const result = await act(sut, options); + expect(testRunner1[runMethod]).to.have.been.calledWith(options); + expect(result).to.eq(expectedResult); + }); + + it('should retry on a new test runner if a run is rejected', async () => { + testRunner1[runMethod].rejects(new Error('Error')); + testRunner2[runMethod].resolves(expectedRunResult); + const result = await act(sut, options); + expect(result).to.eq(expectedRunResult); + }); + + it('should retry if a `ChildProcessCrashedError` occurred reject appears', async () => { + testRunner1[runMethod].rejects(crashedError); + testRunner2[runMethod].resolves(expectedRunResult); + const result = await act(sut, options); + expect(result).to.eq(expectedRunResult); + }); - it('should retry at most 1 times before rejecting', async () => { - const finalError = new Error('foo'); + it('should log and retry when an `OutOfMemoryError` occurred.', async () => { + testRunner1[runMethod].rejects(new OutOfMemoryError(123, 123)); + testRunner2[runMethod].resolves(expectedRunResult); + const result = await act(sut, options); + expect(result).to.eq(expectedRunResult); + expect(logMock.info).calledWith( + "Test runner process [%s] ran out of memory. You probably have a memory leak in your tests. Don't worry, Stryker will restart the process, but you might want to investigate this later, because this decreases performance.", + 123 + ); + }); - testRunner1.run.rejects(new Error('bar')); - testRunner2.run.rejects(finalError); + it('should dispose a test runner when it rejected, before creating a new one', async () => { + testRunner1[runMethod].rejects(crashedError); + testRunner2[runMethod].resolves(expectedRunResult); + await act(sut, options); + expect(testRunner1.dispose).calledBefore(testRunner2.init); + }); - const runResult = await sut.run(options); - expect(runResult.status).to.be.eq(RunStatus.Error); - expect(runResult.errorMessages).to.be.deep.eq([ - `Test runner crashed. Tried twice to restart it without any luck. Last time the error message was: ${errorToString(finalError)}`, - ]); - expect(availableTestRunners).to.have.lengthOf(0); + it('should retry at most 1 times before rejecting', async () => { + const finalError = new Error('foo'); + + testRunner1[runMethod].rejects(new Error('bar')); + testRunner2[runMethod].rejects(finalError); + + const result = await act(sut, options); + expectErrored(result); + expect((result as any).errorMessage).to.be.deep.eq( + `Test runner crashed. Tried twice to restart it without any luck. Last time the error message was: ${errorToString(finalError)}` + ); + expect(availableTestRunners).to.have.lengthOf(0); + }); }); - }); + } }); diff --git a/packages/core/test/unit/test-runner/TestRunnerDecorator.spec.ts b/packages/core/test/unit/test-runner/TestRunnerDecorator.spec.ts index 809409d30e..34b441a7e4 100644 --- a/packages/core/test/unit/test-runner/TestRunnerDecorator.spec.ts +++ b/packages/core/test/unit/test-runner/TestRunnerDecorator.spec.ts @@ -1,18 +1,20 @@ import { expect } from 'chai'; +import { TestRunner } from '@stryker-mutator/api/test_runner'; +import { factory } from '@stryker-mutator/test-helpers'; + import TestRunnerDecorator from '../../../src/test-runner/TestRunnerDecorator'; -import TestRunnerMock from '../../helpers/TestRunnerMock'; describe('TestRunnerDecorator', () => { let sut: TestRunnerDecorator; - let testRunner: TestRunnerMock; + let testRunner: sinon.SinonStubbedInstance>; beforeEach(() => { - testRunner = new TestRunnerMock(); - sut = new TestRunnerDecorator(() => testRunner as any); + testRunner = factory.testRunner(); + sut = new TestRunnerDecorator(() => testRunner); }); - function actArrangeAssert(methodName: 'init' | 'dispose' | 'run') { + function actArrangeAssert(methodName: 'init' | 'dispose' | 'dryRun' | 'mutantRun') { describe(methodName, () => { it('should pass through resolved results', () => { testRunner[methodName].resolves('some value'); @@ -28,5 +30,6 @@ describe('TestRunnerDecorator', () => { actArrangeAssert('init'); actArrangeAssert('dispose'); - actArrangeAssert('run'); + actArrangeAssert('dryRun'); + actArrangeAssert('mutantRun'); }); diff --git a/packages/core/test/unit/test-runner/TimeoutDecorator.spec.ts b/packages/core/test/unit/test-runner/TimeoutDecorator.spec.ts index 8e64385663..ad7acb26b0 100644 --- a/packages/core/test/unit/test-runner/TimeoutDecorator.spec.ts +++ b/packages/core/test/unit/test-runner/TimeoutDecorator.spec.ts @@ -1,32 +1,31 @@ -import { RunStatus } from '@stryker-mutator/api/test_runner'; +import { DryRunStatus, TimeoutDryRunResult, TestRunner, MutantRunStatus, TimeoutMutantRunResult } from '@stryker-mutator/api/test_runner'; import { expect } from 'chai'; import * as sinon from 'sinon'; +import { factory } from '@stryker-mutator/test-helpers'; + import TimeoutDecorator from '../../../src/test-runner/TimeoutDecorator'; -import TestRunnerMock from '../../helpers/TestRunnerMock'; describe('TimeoutDecorator', () => { let sut: TimeoutDecorator; let sandbox: sinon.SinonSandbox; let clock: sinon.SinonFakeTimers; - let testRunner1: TestRunnerMock; - let testRunner2: TestRunnerMock; - let availableTestRunners: TestRunnerMock[]; + let testRunner1: sinon.SinonStubbedInstance>; + let testRunner2: sinon.SinonStubbedInstance>; + let availableTestRunners: Array>>; beforeEach(() => { sandbox = sinon.createSandbox(); clock = sinon.useFakeTimers(); - testRunner1 = new TestRunnerMock(); - testRunner2 = new TestRunnerMock(); + testRunner1 = factory.testRunner(); + testRunner2 = factory.testRunner(); availableTestRunners = [testRunner1, testRunner2]; - sut = new TimeoutDecorator(() => { - return availableTestRunners.shift() as any; - }); + sut = new TimeoutDecorator(() => availableTestRunners.shift() || expect.fail('test runners are empty')); }); afterEach(() => sandbox.restore()); - function itShouldProxyRequests(action: () => Promise, methodName: 'init' | 'dispose' | 'run') { + function itShouldProxyRequests(action: () => Promise, methodName: 'init' | 'dispose' | 'dryRun' | 'mutantRun') { it('should proxy the request', () => { testRunner1[methodName].resolves('str'); const promise = action(); @@ -59,32 +58,57 @@ describe('TimeoutDecorator', () => { itShouldProxyRequestsForMethod('dispose'); }); - describe('run', () => { - itShouldProxyRequests(() => sut.run({ timeout: 20 }), 'run'); + describe('dryRun', () => { + itShouldProxyRequests(() => sut.dryRun({ coverageAnalysis: 'all', timeout: 20 }), 'dryRun'); + + it('should not handle timeouts premature', () => { + let resolve: (result: string) => void = () => {}; + testRunner1.dryRun.returns(new Promise((res) => (resolve = res))); + const runPromise = sut.dryRun(factory.dryRunOptions({ timeout: 20 })); + clock.tick(19); + resolve('expectedResult'); + return expect(runPromise).to.eventually.be.eq('expectedResult'); + }); + + it('should handle timeouts', async () => { + testRunner1.dryRun.returns( + new Promise(() => {}) + ); + const runPromise = sut.dryRun(factory.dryRunOptions({ timeout: 20 })); + clock.tick(20); + const result = await runPromise; + const expectedTimeoutResult: TimeoutDryRunResult = { status: DryRunStatus.Timeout }; + expect(result).deep.eq(expectedTimeoutResult); + expect(availableTestRunners).to.have.lengthOf(0); + expect(testRunner1.dispose).to.have.been.called; + expect(testRunner2.init).to.have.been.called; + }); + }); + + describe('mutantRun', () => { + itShouldProxyRequests(() => sut.mutantRun(factory.mutantRunOptions({ timeout: 20 })), 'mutantRun'); it('should not handle timeouts premature', () => { let resolve: (result: string) => void = () => {}; - testRunner1.run.returns(new Promise((res) => (resolve = res))); - const runPromise = sut.run({ timeout: 20 }); + testRunner1.mutantRun.returns(new Promise((res) => (resolve = res))); + const runPromise = sut.mutantRun(factory.mutantRunOptions({ timeout: 20 })); clock.tick(19); resolve('expectedResult'); return expect(runPromise).to.eventually.be.eq('expectedResult'); }); - it('should handle timeouts', () => { - testRunner1.run.returns( + it('should handle timeouts', async () => { + testRunner1.mutantRun.returns( new Promise(() => {}) ); - const runPromise = sut.run({ timeout: 20 }); + const runPromise = sut.mutantRun(factory.mutantRunOptions({ timeout: 20 })); clock.tick(20); - return expect( - runPromise.then((result) => { - expect(availableTestRunners).to.have.lengthOf(0); - expect(testRunner1.dispose).to.have.been.called; - expect(testRunner2.init).to.have.been.called; - return result; - }) - ).to.eventually.be.deep.equal({ status: RunStatus.Timeout, tests: [] }); + const result = await runPromise; + const expectedTimeoutResult: TimeoutMutantRunResult = { status: MutantRunStatus.Timeout }; + expect(result).deep.eq(expectedTimeoutResult); + expect(availableTestRunners).to.have.lengthOf(0); + expect(testRunner1.dispose).to.have.been.called; + expect(testRunner2.init).to.have.been.called; }); }); }); diff --git a/packages/core/test/unit/transpiler/CoverageInstrumenterTranspiler.spec.ts b/packages/core/test/unit/transpiler/CoverageInstrumenterTranspiler.spec.ts deleted file mode 100644 index 4c1cbc4346..0000000000 --- a/packages/core/test/unit/transpiler/CoverageInstrumenterTranspiler.spec.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { File, StrykerOptions } from '@stryker-mutator/api/core'; -import { expect } from 'chai'; -import { factory } from '@stryker-mutator/test-helpers'; - -import CoverageInstrumenterTranspiler from '../../../src/transpiler/CoverageInstrumenterTranspiler'; - -describe('CoverageInstrumenterTranspiler', () => { - let sut: CoverageInstrumenterTranspiler; - let options: StrykerOptions; - - beforeEach(() => { - options = factory.strykerOptions(); - }); - - it('should not instrument any code when coverage analysis is off', async () => { - sut = new CoverageInstrumenterTranspiler(options, ['foobar.js']); - options.coverageAnalysis = 'off'; - const input = [new File('foobar.js', '')]; - const outputFiles = await sut.transpile(input); - expect(outputFiles).deep.eq(input); - }); - - describe('when coverage analysis is "all"', () => { - beforeEach(() => { - options.coverageAnalysis = 'all'; - sut = new CoverageInstrumenterTranspiler(options, ['mutate.js']); - }); - - it('should instrument code of mutated files', async () => { - const input = [new File('mutate.js', 'function something() {}'), new File('spec.js', '')]; - const outputFiles = await sut.transpile(input); - const instrumentedContent = outputFiles[0].textContent; - expect(instrumentedContent).to.contain('function something(){cov_').and.contain('.f[0]++'); - }); - - it('should preserve source map comments', async () => { - const input = [new File('mutate.js', 'function something() {} // # sourceMappingUrl="something.map.js"')]; - const outputFiles = await sut.transpile(input); - const instrumentedContent = outputFiles[0].textContent; - expect(instrumentedContent).to.contain('sourceMappingUrl="something.map.js"'); - }); - - it('should create a statement map for mutated files', () => { - const input = [new File('mutate.js', 'function something () {}'), new File('foobar.js', 'console.log("foobar");')]; - sut.transpile(input); - expect(sut.fileCoverageMaps['mutate.js'].statementMap).deep.eq({}); - expect(sut.fileCoverageMaps['mutate.js'].fnMap[0]).deep.eq({ start: { line: 0, column: 22 }, end: { line: 0, column: 24 } }); - expect(sut.fileCoverageMaps['mutate.js'].fnMap[1]).undefined; - expect(sut.fileCoverageMaps['foobar.js']).undefined; - }); - - it('should fill error message and not transpile input when the file contains a parse error', async () => { - const invalidJavascriptFile = new File('mutate.js', 'function something {}'); - return expect(sut.transpile([invalidJavascriptFile])).rejectedWith( - 'Could not instrument "mutate.js" for code coverage. Inner error: SyntaxError: Unexpected token' - ); - }); - }); -}); diff --git a/packages/core/test/unit/transpiler/MutantTranspileScheduler.spec.ts b/packages/core/test/unit/transpiler/MutantTranspileScheduler.spec.ts deleted file mode 100644 index c8c350b719..0000000000 --- a/packages/core/test/unit/transpiler/MutantTranspileScheduler.spec.ts +++ /dev/null @@ -1,141 +0,0 @@ -import { File } from '@stryker-mutator/api/core'; -import { Disposable } from '@stryker-mutator/api/plugin'; -import { Transpiler } from '@stryker-mutator/api/transpile'; -import { testInjector } from '@stryker-mutator/test-helpers'; -import { errorToString } from '@stryker-mutator/util'; -import { expect } from 'chai'; -import { range } from 'rxjs'; -import { map, toArray } from 'rxjs/operators'; -import * as sinon from 'sinon'; - -import { coreTokens } from '../../../src/di'; -import TranspiledMutant from '../../../src/TranspiledMutant'; -import { MutantTranspileScheduler } from '../../../src/transpiler/MutantTranspileScheduler'; -import TranspileResult from '../../../src/transpiler/TranspileResult'; -import { testableMutant } from '../../helpers/producers'; -import { sleep } from '../../helpers/testUtils'; - -describe(MutantTranspileScheduler.name, () => { - let sut: MutantTranspileScheduler; - let transpilerMock: sinon.SinonStubbedInstance; - let initialTranspiledFiles: File[]; - let transpiledFilesOne: File[]; - let transpiledFilesTwo: File[]; - - beforeEach(() => { - initialTranspiledFiles = [new File('firstResult.js', 'initial result')]; - transpilerMock = { - dispose: sinon.stub(), - transpile: sinon.stub(), - }; - transpiledFilesOne = [new File('firstResult.js', 'first result')]; - transpiledFilesTwo = [new File('secondResult.js', 'second result')]; - sut = testInjector.injector - .provideValue(coreTokens.transpiledFiles, initialTranspiledFiles) - .provideValue(coreTokens.transpiler, (transpilerMock as unknown) as Transpiler & Disposable) - .injectClass(MutantTranspileScheduler); - }); - - it('should transpile mutants', async () => { - // Arrange - const mutants = [testableMutant(), testableMutant()]; - transpilerMock.transpile.onFirstCall().resolves(transpiledFilesOne).onSecondCall().resolves(transpiledFilesTwo); - const expected: TranspiledMutant[] = [ - { mutant: mutants[0], transpileResult: { error: null, outputFiles: transpiledFilesOne }, changedAnyTranspiledFiles: true }, - { mutant: mutants[1], transpileResult: { error: null, outputFiles: transpiledFilesTwo }, changedAnyTranspiledFiles: true }, - ]; - - // Act - const actualResult = await sut.scheduleTranspileMutants(mutants).pipe(toArray()).toPromise(); - - // Assert - expect(actualResult).deep.eq(expected); - }); - - it('should report rejected transpile attempts as errors', async () => { - // Arrange - const error = new Error('expected transpile error'); - transpilerMock.transpile.rejects(error); - const mutant = testableMutant(); - - // Act - const actualResult = await sut.scheduleTranspileMutants([mutant]).pipe(toArray()).toPromise(); - - // Assert - const expected: TranspiledMutant[] = [ - { mutant, transpileResult: { error: errorToString(error), outputFiles: [] }, changedAnyTranspiledFiles: false }, - ]; - expect(actualResult).deep.eq(expected); - }); - - it('should set set the changedAnyTranspiledFiles boolean to false if transpiled output did not change', async () => { - // Arrange - transpilerMock.transpile.resolves(initialTranspiledFiles); - const mutants = [testableMutant()]; - - // Act - const actual = await sut.scheduleTranspileMutants(mutants).pipe(toArray()).toPromise(); - - // Assert - const expected: TranspiledMutant[] = [ - { mutant: mutants[0], transpileResult: { error: null, outputFiles: initialTranspiledFiles }, changedAnyTranspiledFiles: false }, - ]; - expect(actual).deep.eq(expected); - }); - - it('should transpile mutants one by one in sequence', async () => { - // Arrange - let resolveFirst: (files: readonly File[]) => void = () => {}; - let resolveSecond: (files: readonly File[]) => void = () => {}; - transpilerMock.transpile - .onFirstCall() - .returns(new Promise((res) => (resolveFirst = res))) - .onSecondCall() - .returns(new Promise((res) => (resolveSecond = res))); - const actualResults: TranspileResult[] = []; - - // Act - sut - .scheduleTranspileMutants([testableMutant('one'), testableMutant('two')]) - .subscribe((transpiledMutant) => actualResults.push(transpiledMutant.transpileResult)); - - // Assert: only first time called - expect(transpilerMock.transpile).calledOnce; - expect(actualResults).lengthOf(0); - resolveFirst(transpiledFilesOne); - await sleep(); - // Assert: second one is called, first one is received - expect(transpilerMock.transpile).calledTwice; - expect(actualResults).lengthOf(1); - resolveSecond(transpiledFilesTwo); - // Assert: all results are in - await sleep(); - const expectedResults: TranspileResult[] = [ - { error: null, outputFiles: transpiledFilesOne }, - { error: null, outputFiles: transpiledFilesTwo }, - ]; - expect(actualResults).deep.eq(expectedResults); - }); - - const MAX_CONCURRENCY = 100; - it(`should transpile ${MAX_CONCURRENCY} mutants at a time and not transpile more until \`scheduleNext\` is called`, async () => { - // Arrange - transpilerMock.transpile.resolves(initialTranspiledFiles); - const input = await range(0, MAX_CONCURRENCY + 1) - .pipe( - map((i) => testableMutant(i.toString())), - toArray() - ) - .toPromise(); - const actualResult: TranspiledMutant[] = []; - const subscription = sut.scheduleTranspileMutants(input).subscribe((mutant) => actualResult.push(mutant)); - - // Act & assert - await sleep(); - expect(actualResult).lengthOf(MAX_CONCURRENCY); - sut.scheduleNext(); - await sleep(); - expect(actualResult).lengthOf(MAX_CONCURRENCY + 1); - subscription.unsubscribe(); - }); -}); diff --git a/packages/core/test/unit/transpiler/SourceMapper.spec.ts b/packages/core/test/unit/transpiler/SourceMapper.spec.ts deleted file mode 100644 index 00e13e5654..0000000000 --- a/packages/core/test/unit/transpiler/SourceMapper.spec.ts +++ /dev/null @@ -1,182 +0,0 @@ -import { File, StrykerOptions } from '@stryker-mutator/api/core'; -import { factory } from '@stryker-mutator/test-helpers'; -import { expect } from 'chai'; -import * as sinon from 'sinon'; -import * as sourceMapModule from 'source-map'; - -import SourceMapper, { MappedLocation, PassThroughSourceMapper, SourceMapError, TranspiledSourceMapper } from '../../../src/transpiler/SourceMapper'; -import { mappedLocation, Mock, mock } from '../../helpers/producers'; - -const GREATEST_LOWER_BOUND = sourceMapModule.SourceMapConsumer.GREATEST_LOWER_BOUND; -const LEAST_UPPER_BOUND = sourceMapModule.SourceMapConsumer.LEAST_UPPER_BOUND; - -function base64Encode(input: string) { - return Buffer.from(input).toString('base64'); -} - -const ERROR_POSTFIX = - '. Cannot analyse code coverage. Setting `coverageAnalysis: "off"` in your config will prevent this error, but forces Stryker to run each test for each mutant.'; - -describe('SourceMapper', () => { - let sut: SourceMapper; - let sourceMapConsumerMock: Mock; - let options: StrykerOptions; - - beforeEach(() => { - options = factory.strykerOptions(); - sourceMapConsumerMock = mock(sourceMapModule.SourceMapConsumer); - - // For some reason, `generatedPositionFor` is not defined on the `SourceMapConsumer` prototype - // Define it here by hand - sourceMapConsumerMock.generatedPositionFor = sinon.stub(); - sourceMapConsumerMock.generatedPositionFor.returns( - Promise.resolve({ - column: 2, - line: 1, - }) - ); - sinon.stub(sourceMapModule, 'SourceMapConsumer').returns(sourceMapConsumerMock); - - // Restore the static values, removed by the stub - sourceMapModule.SourceMapConsumer.LEAST_UPPER_BOUND = LEAST_UPPER_BOUND; - sourceMapModule.SourceMapConsumer.GREATEST_LOWER_BOUND = GREATEST_LOWER_BOUND; - }); - - describe('create', () => { - it('should create a PassThrough source mapper when no transpiler was configured', () => { - options.transpilers = []; - expect(SourceMapper.create([], options)).instanceOf(PassThroughSourceMapper); - }); - it('should create a Transpiled source mapper when a transpiler was configured', () => { - options.transpilers = ['a transpiler']; - options.coverageAnalysis = 'perTest'; - expect(SourceMapper.create([], options)).instanceOf(TranspiledSourceMapper); - }); - }); - - describe('PassThrough', () => { - beforeEach(() => { - sut = new PassThroughSourceMapper(); - }); - - it('should pass through the input on transpiledLocationFor', async () => { - const input: MappedLocation = { - fileName: 'foo/bar.js', - location: factory.location(), - }; - expect(await sut.transpiledLocationFor(input)).eq(input); - }); - }); - - describe('Transpiled', () => { - let transpiledFiles: File[]; - - beforeEach(() => { - transpiledFiles = []; - sut = new TranspiledSourceMapper(transpiledFiles); - }); - - it('should create SourceMapConsumer for a file when transpiledLocationFor is called', async () => { - // Arrange - const expectedMapFile1 = { sources: ['file1.ts'] }; - const expectedMapFile2 = { sources: ['file2.ts'] }; - transpiledFiles.push(new File('file1.js', '// # sourceMappingURL=file1.js.map')); - transpiledFiles.push(new File('file1.js.map', JSON.stringify(expectedMapFile1))); - transpiledFiles.push( - new File('file2.js', `// # sourceMappingURL=data:application/json;base64,${base64Encode(JSON.stringify(expectedMapFile2))}`) - ); - - // Act - await sut.transpiledLocationFor(mappedLocation({ fileName: 'file1.ts' })); - - // Assert - expect(sourceMapModule.SourceMapConsumer).calledWithNew; - expect(sourceMapModule.SourceMapConsumer).calledWith(expectedMapFile1); - expect(sourceMapModule.SourceMapConsumer).not.calledWith(expectedMapFile2); - }); - - it('should cache source maps for future use when `transpiledLocationFor` is called', async () => { - // Arrange - const expectedMapFile1 = { sources: ['file1.ts'] }; - transpiledFiles.push( - new File('file1.js', `// # sourceMappingURL=data:application/json;base64,${base64Encode(JSON.stringify(expectedMapFile1))}`) - ); - - // Act - await sut.transpiledLocationFor(mappedLocation({ fileName: 'file1.ts' })); - await sut.transpiledLocationFor(mappedLocation({ fileName: 'file1.ts' })); - - // Assert - expect(sourceMapModule.SourceMapConsumer).calledOnce; - }); - - it('should throw an error when the requested source map could not be found', async () => { - await expect(sut.transpiledLocationFor(mappedLocation({ fileName: 'foobar' }))).to.be.rejectedWith( - SourceMapError, - 'Source map not found for "foobar"' + ERROR_POSTFIX - ); - }); - - it('should throw an error if source map file is a binary file', async () => { - transpiledFiles.push(new File('file.js', '// # sourceMappingURL=file1.js.map')); - transpiledFiles.push(new File('file1.js.map', Buffer.from(factory.PNG_BASE64_ENCODED, 'base64'))); - - await expect(sut.transpiledLocationFor(mappedLocation({ fileName: 'foobar' }))).to.be.rejectedWith( - SourceMapError, - /^Source map file "file1.js.map" could not be parsed as json. Cannot analyse code coverage. Setting `coverageAnalysis: "off"` in your config will prevent this error/ - ); - }); - - it('should throw an error if source map data url is not supported', async () => { - const expectedMapFile1 = { sources: ['file1.ts'] }; - transpiledFiles.push( - new File('file1.js', `// # sourceMappingURL=data:application/xml;base64,${base64Encode(JSON.stringify(expectedMapFile1))}`) - ); - - await expect(sut.transpiledLocationFor(mappedLocation({ fileName: 'foobar' }))).to.be.rejectedWith( - SourceMapError, - `Source map file for "file1.js" cannot be read. Data url "data:application/xml;base64" found, where "data:application/json;base64" was expected${ERROR_POSTFIX}` - ); - }); - - it('should throw an error if source map file cannot be found', async () => { - transpiledFiles.push(new File('file1.js', '// # sourceMappingURL=file1.js.map')); - - await expect(sut.transpiledLocationFor(mappedLocation({ fileName: 'foobar' }))).to.be.rejectedWith( - SourceMapError, - `Source map file "file1.js.map" (referenced by "file1.js") cannot be found in list of transpiled files${ERROR_POSTFIX}` - ); - }); - - it('should throw an error if source map file url is not declared in a transpiled file', async () => { - transpiledFiles.push(new File('file1.js', '// # sourceMapping%%%=file1.js.map')); - - await expect(sut.transpiledLocationFor(mappedLocation({ fileName: 'foobar' }))).to.be.rejectedWith( - SourceMapError, - `Source map not found for "foobar"${ERROR_POSTFIX}` - ); - }); - - it('should not throw an error if one of the files is a binary file', async () => { - const expectedMapFile1 = { sources: ['file1.ts'] }; - transpiledFiles.push( - new File('file1.js', `// # sourceMappingURL=data:application/json;base64,${base64Encode(JSON.stringify(expectedMapFile1))}`) - ); - transpiledFiles.push(new File('foo.png', Buffer.from(factory.PNG_BASE64_ENCODED, 'base64'))); - - await expect(sut.transpiledLocationFor(mappedLocation({ fileName: 'file1.ts' }))).to.eventually.deep.eq({ - fileName: 'file1.js', - location: { - end: { - column: 2, - line: 0, - }, - start: { - column: 2, - line: 0, - }, - }, - }); - }); - }); -}); diff --git a/packages/core/test/unit/transpiler/TranspilerFacade.spec.ts b/packages/core/test/unit/transpiler/TranspilerFacade.spec.ts deleted file mode 100644 index 3b9ac940b1..0000000000 --- a/packages/core/test/unit/transpiler/TranspilerFacade.spec.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { File } from '@stryker-mutator/api/core'; -import { PluginKind } from '@stryker-mutator/api/plugin'; -import { Transpiler } from '@stryker-mutator/api/transpile'; -import { testInjector } from '@stryker-mutator/test-helpers'; -import { expect } from 'chai'; -import * as sinon from 'sinon'; - -import { coreTokens } from '../../../src/di'; -import { PluginCreator } from '../../../src/di/PluginCreator'; -import { TranspilerFacade } from '../../../src/transpiler/TranspilerFacade'; -import { mock, Mock } from '../../helpers/producers'; - -describe(TranspilerFacade.name, () => { - let sut: TranspilerFacade; - let pluginCreatorMock: sinon.SinonStubbedInstance>; - - describe('when there are no transpilers', () => { - beforeEach(() => { - pluginCreatorMock = sinon.createStubInstance(PluginCreator); - sut = createSut(); - }); - - it('should return input when `transpile` is called', async () => { - const input = [new File('input', '')]; - const outputFiles = await sut.transpile(input); - expect(pluginCreatorMock.create).not.called; - expect(outputFiles).eq(input); - }); - }); - - describe('with 2 transpilers', () => { - let transpilerOne: Mock; - let transpilerTwo: Mock; - let resultFilesOne: readonly File[]; - let resultFilesTwo: readonly File[]; - beforeEach(() => { - testInjector.options.transpilers = ['transpiler-one', 'transpiler-two']; - transpilerOne = mock(TranspilerFacade); - transpilerTwo = mock(TranspilerFacade); - resultFilesOne = [new File('result-1', '')]; - resultFilesTwo = [new File('result-2', '')]; - pluginCreatorMock = sinon.createStubInstance(PluginCreator); - pluginCreatorMock.create.withArgs('transpiler-one').returns(transpilerOne).withArgs('transpiler-two').returns(transpilerTwo); - transpilerOne.transpile.resolves(resultFilesOne); - transpilerTwo.transpile.resolves(resultFilesTwo); - sut = createSut(); - }); - - it('should create two transpilers', () => { - expect(pluginCreatorMock.create).calledTwice; - expect(pluginCreatorMock.create).calledWith('transpiler-one'); - expect(pluginCreatorMock.create).calledWith('transpiler-two'); - }); - - it('should chain the transpilers when `transpile` is called', async () => { - const input = [new File('input', '')]; - const outputFiles = await sut.transpile(input); - expect(outputFiles).eq(resultFilesTwo); - expect(transpilerOne.transpile).calledWith(input); - expect(transpilerTwo.transpile).calledWith(resultFilesOne); - }); - - it('should stop chaining if an error occurs during `transpile`', async () => { - // Arrange - transpilerOne.transpile.reset(); - const expectedError = new Error('an error'); - transpilerOne.transpile.rejects(expectedError); - const input = [new File('input', '')]; - - // Act - const transpilePromise = sut.transpile(input); - - // Assert - await expect(transpilePromise).rejectedWith('An error occurred in transpiler "transpiler-one". Inner error: Error: an error'); - - // Assert - expect(transpilerOne.transpile).calledWith(input); - expect(transpilerTwo.transpile).not.called; - }); - }); - function createSut() { - return testInjector.injector - .provideValue(coreTokens.pluginCreatorTranspiler, (pluginCreatorMock as unknown) as PluginCreator) - .injectClass(TranspilerFacade); - } -}); diff --git a/packages/core/test/unit/transpiler/coverageHooks.spec.ts b/packages/core/test/unit/transpiler/coverageHooks.spec.ts deleted file mode 100644 index 447019c652..0000000000 --- a/packages/core/test/unit/transpiler/coverageHooks.spec.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { testFramework } from '@stryker-mutator/test-helpers/src/factory'; -import { expect } from 'chai'; - -import * as coverageHooks from '../../../src/transpiler/coverageHooks'; - -describe('coveragePerTestHooks', () => { - it('should use the coverage variable "__strykerCoverageCurrentTest__"', () => { - const actual = coverageHooks.coveragePerTestHooks(testFramework()); - expect(actual).to.contain('__strykerCoverageCurrentTest__'); - }); - - it('should use beforeEach and afterEach (test framework hooks)', () => { - const actual = coverageHooks.coveragePerTestHooks(testFramework()); - expect(actual).to.contain('beforeEach()'); - expect(actual).to.contain('afterEach()'); - }); - - it('should wrap all in a closure', () => { - const actual = coverageHooks.coveragePerTestHooks(testFramework()); - expect(actual).to.contain('(function (window) {'); - expect(actual).to.contain("})((Function('return this'))());"); - }); -}); diff --git a/packages/core/test/unit/transpiler/transpiler.spec.ts b/packages/core/test/unit/transpiler/transpiler.spec.ts deleted file mode 100644 index 982fcbdc74..0000000000 --- a/packages/core/test/unit/transpiler/transpiler.spec.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { File } from '@stryker-mutator/api/core'; -import { Injector } from '@stryker-mutator/api/plugin'; -import { Transpiler } from '@stryker-mutator/api/transpile'; -import { factory, testInjector } from '@stryker-mutator/test-helpers'; -import { expect } from 'chai'; -import * as sinon from 'sinon'; - -import { transpilerFactory } from '../../../src/transpiler'; -import { ChildProcessTranspiler } from '../../../src/transpiler/ChildProcessTranspiler'; - -describe(transpilerFactory.name, () => { - let injectorMock: sinon.SinonStubbedInstance>; - let childProcessTranspiler: sinon.SinonStubbedInstance; - - beforeEach(() => { - childProcessTranspiler = sinon.createStubInstance(ChildProcessTranspiler); - injectorMock = factory.injector(); - injectorMock.injectClass.withArgs(ChildProcessTranspiler).returns(childProcessTranspiler); - }); - - function act(): Transpiler { - return transpilerFactory(testInjector.options, injectorMock); - } - - it('should construct the transpiler in a child process if a transpiler is configured', () => { - testInjector.options.transpilers.push('fooTranspiler'); - - const actual = act(); - expect(actual).eq(childProcessTranspiler); - }); - - it('should construct a pass through transpiler if no transpiler is configured', () => { - const actual = act(); - const input = [new File('foo.js', 'bar')]; - expect(actual).not.eq(childProcessTranspiler); - expect(actual.transpile(input)).eventually.eq(input); - }); -}); diff --git a/packages/core/test/unit/utils/TemporaryDirectory.spec.ts b/packages/core/test/unit/utils/TemporaryDirectory.spec.ts index b588abe773..b7b204c92c 100644 --- a/packages/core/test/unit/utils/TemporaryDirectory.spec.ts +++ b/packages/core/test/unit/utils/TemporaryDirectory.spec.ts @@ -7,6 +7,8 @@ import { expect } from 'chai'; import * as mkdirp from 'mkdirp'; import * as sinon from 'sinon'; +import { StrykerOptions } from '@stryker-mutator/api/core'; + import * as fileUtils from '../../../src/utils/fileUtils'; import { TemporaryDirectory } from '../../../src/utils/TemporaryDirectory'; @@ -27,10 +29,10 @@ describe(TemporaryDirectory.name, () => { randomStub.returns('rand'); }); - function createSut(): TemporaryDirectory { + function createSut(options?: Partial): TemporaryDirectory { return testInjector.injector .provideValue(commonTokens.logger, factory.logger()) - .provideValue(commonTokens.options, factory.strykerOptions()) + .provideValue(commonTokens.options, factory.strykerOptions(options)) .injectClass(TemporaryDirectory); } @@ -57,14 +59,34 @@ describe(TemporaryDirectory.name, () => { describe('dispose', () => { describe('when temp directory is initialized', () => { beforeEach(() => sut.initialize()); - it('should call deleteDir fileApi', async () => { + it('should remove the dir if cleanTempDir option is enabled', async () => { const expectedPath = path.resolve(tempDirName); deleteDirStub.resolves(); + const sut = createSut({ cleanTempDir: true }); + sut.initialize(); + await sut.dispose(); + expect(fileUtils.deleteDir).calledWith(expectedPath); + }); + + it('should not remove the dir if cleanTempDir option is enabled', async () => { + const sut = createSut({ cleanTempDir: false }); + sut.initialize(); + await sut.dispose(); + expect(fileUtils.deleteDir).not.called; + }); - const temporaryDirectoryInstance = sut; - await temporaryDirectoryInstance.dispose(); + it('should not remove the dir if `removeDuringDisposal` is set to false', async () => { + const sut = createSut({ cleanTempDir: true }); + sut.initialize(); + sut.removeDuringDisposal = false; + await sut.dispose(); + expect(fileUtils.deleteDir).not.called; + }); - expect(fileUtils.deleteDir).calledWith(expectedPath); + it('should remove the dir by default', async () => { + deleteDirStub.resolves(); + await sut.dispose(); + expect(fileUtils.deleteDir).calledOnce; }); }); diff --git a/packages/core/test/unit/utils/Timer.spec.ts b/packages/core/test/unit/utils/Timer.spec.ts index a80b92944b..19e4c302ca 100644 --- a/packages/core/test/unit/utils/Timer.spec.ts +++ b/packages/core/test/unit/utils/Timer.spec.ts @@ -3,7 +3,7 @@ import * as sinon from 'sinon'; import Timer from '../../../src/utils/Timer'; -describe('Timer', () => { +describe(Timer.name, () => { let clock: sinon.SinonFakeTimers; let sut: Timer; @@ -14,19 +14,27 @@ describe('Timer', () => { afterEach(() => clock.restore()); - const arrangeActAssert = (elapsedMs: number, expectedTimeLabel: string) => { - describe(`after ${expectedTimeLabel}`, () => { - beforeEach(() => clock.tick(elapsedMs)); - - it(`should show "${expectedTimeLabel}" when humanReadableElapsed()`, () => expect(sut.humanReadableElapsed()).to.be.eq(expectedTimeLabel)); + describe(Timer.prototype.humanReadableElapsed.name, () => { + const arrangeActAssert = (elapsedMs: number, expectedTimeLabel: string) => { + it(`should show "${expectedTimeLabel}" after ${elapsedMs} ms`, () => { + clock.tick(elapsedMs); + expect(sut.humanReadableElapsed()).to.be.eq(expectedTimeLabel); + }); + }; + + arrangeActAssert(59999, '59 seconds'); + arrangeActAssert(119999, '1 minute 59 seconds'); + arrangeActAssert(120000, '2 minutes 0 seconds'); + arrangeActAssert(121999, '2 minutes 1 second'); + arrangeActAssert(61000, '1 minute 1 second'); + + it('should use the since marker when provided', () => { + clock.tick(1000); + sut.mark('foo'); + clock.tick(1000); + expect(sut.humanReadableElapsed('foo')).eq('1 second'); }); - }; - - arrangeActAssert(59999, '59 seconds'); - arrangeActAssert(119999, '1 minute 59 seconds'); - arrangeActAssert(120000, '2 minutes 0 seconds'); - arrangeActAssert(121999, '2 minutes 1 second'); - arrangeActAssert(61000, '1 minute 1 second'); + }); describe('mark and elapsedMS', () => { it('should result in expected elapsedMS', () => { diff --git a/packages/core/test/unit/utils/objectUtils.spec.ts b/packages/core/test/unit/utils/objectUtils.spec.ts deleted file mode 100644 index b19267f9a5..0000000000 --- a/packages/core/test/unit/utils/objectUtils.spec.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { expect } from 'chai'; -import { match } from 'sinon'; -import * as sinon from 'sinon'; - -import * as sut from '../../../src/utils/objectUtils'; -import { Task } from '../../../src/utils/Task'; - -describe('objectUtils', () => { - describe('timeout', () => { - it('should timeout a promise after a set period', async () => { - const task = new Task(); - const actual = await sut.timeout(task.promise, 0); - expect(actual).eq(sut.TimeoutExpired); - task.resolve(undefined); - }); - - it('should remove any nodejs timers when promise resolves', async () => { - // Arrange - const expectedTimer = 234; - const setTimeoutStub = sinon.stub(global, 'setTimeout'); - const clearTimeoutStub = sinon.stub(global, 'clearTimeout'); - setTimeoutStub.returns(expectedTimer); - const expectedResult = 'expectedResult'; - const p = Promise.resolve(expectedResult); - const delay = 10; - - // Act - const result = await sut.timeout(p, delay); - - // Assert - expect(result).eq(expectedResult); - expect(clearTimeoutStub).calledWith(expectedTimer); - expect(setTimeoutStub).calledWith(match.func, delay); - }); - }); -}); diff --git a/packages/core/testResources/command-runner/mutant.js b/packages/core/testResources/command-runner/mutant.js new file mode 100644 index 0000000000..2f59048326 --- /dev/null +++ b/packages/core/testResources/command-runner/mutant.js @@ -0,0 +1,4 @@ +console.log(`Current active mutant = ${process.env.__STRYKER_ACTIVE_MUTANT__}`); +if (process.env.__STRYKER_ACTIVE_MUTANT__ === '42') { + throw new Error('Expected error when process.env.__STRYKER_ACTIVE_MUTANT__ is 42'); +} diff --git a/packages/core/testResources/command-runner/package.json b/packages/core/testResources/command-runner/package.json index 8466361c60..c63bd6c464 100644 --- a/packages/core/testResources/command-runner/package.json +++ b/packages/core/testResources/command-runner/package.json @@ -2,6 +2,7 @@ "scripts": { "test": "node ok.js", "fail": "node nok.js", - "wait": "node wait.js" + "wait": "node wait.js", + "mutant": "node mutant.js" } -} \ No newline at end of file +} diff --git a/packages/core/testResources/config-reader/deprecated.conf.js b/packages/core/testResources/config-reader/deprecated.conf.js index e5d2c55397..c53586d478 100644 --- a/packages/core/testResources/config-reader/deprecated.conf.js +++ b/packages/core/testResources/config-reader/deprecated.conf.js @@ -1,23 +1,21 @@ -module.exports = function(config){ - config.set({ - mutator: { - name: 'javascript', - excludedMutations: [ - 'ArrayLiteral', - 'ArrayNewExpression', - 'BinaryExpression', - 'Block', - 'BooleanSubstitution', - 'DoStatement', - 'ForStatement', - 'IfStatement', - 'PrefixUnaryExpression', - 'PostfixUnaryExpression', - 'SwitchCase', - 'WhileStatement', - 'ObjectLiteral', - 'ArrowFunctionMutator' - ] - } - }); -}; +module.exports = { + mutator: { + name: 'javascript', + excludedMutations: [ + 'ArrayLiteral', + 'ArrayNewExpression', + 'BinaryExpression', + 'Block', + 'BooleanSubstitution', + 'DoStatement', + 'ForStatement', + 'IfStatement', + 'PrefixUnaryExpression', + 'PostfixUnaryExpression', + 'SwitchCase', + 'WhileStatement', + 'ObjectLiteral', + 'ArrowFunctionMutator' + ] + } +} diff --git a/packages/core/testResources/config-reader/deprecatedFunction.conf.js b/packages/core/testResources/config-reader/deprecatedFunction.conf.js new file mode 100644 index 0000000000..f895b5d0e3 --- /dev/null +++ b/packages/core/testResources/config-reader/deprecatedFunction.conf.js @@ -0,0 +1,8 @@ +module.exports = function(config){ + config.set({ + 'valid': 'config', + 'should': 'be', + 'read': true, + 'type': 'js' + }); +}; diff --git a/packages/core/testResources/config-reader/empty-json/stryker.conf.json b/packages/core/testResources/config-reader/empty-json/stryker.conf.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/packages/core/testResources/config-reader/empty-json/stryker.conf.json @@ -0,0 +1 @@ +{} diff --git a/packages/core/testResources/config-reader/js/stryker.conf.js b/packages/core/testResources/config-reader/js/stryker.conf.js index 6f32162dd8..ef20b50a57 100644 --- a/packages/core/testResources/config-reader/js/stryker.conf.js +++ b/packages/core/testResources/config-reader/js/stryker.conf.js @@ -1,9 +1,7 @@ -module.exports = function(config){ - config.set({ - 'valid': 'config', - 'should': 'be', - 'read': true, - 'type': 'js' - }); -}; +module.exports = { + 'valid': 'config', + 'should': 'be', + 'read': true, + 'type': 'js' +} diff --git a/packages/core/testResources/config-reader/json-and-js/stryker.conf.js b/packages/core/testResources/config-reader/json-and-js/stryker.conf.js index 6f32162dd8..ef20b50a57 100644 --- a/packages/core/testResources/config-reader/json-and-js/stryker.conf.js +++ b/packages/core/testResources/config-reader/json-and-js/stryker.conf.js @@ -1,9 +1,7 @@ -module.exports = function(config){ - config.set({ - 'valid': 'config', - 'should': 'be', - 'read': true, - 'type': 'js' - }); -}; +module.exports = { + 'valid': 'config', + 'should': 'be', + 'read': true, + 'type': 'js' +} diff --git a/packages/babel-transpiler/src/helpers/keys.ts b/packages/core/testResources/config-reader/no-config/.gitkeep similarity index 100% rename from packages/babel-transpiler/src/helpers/keys.ts rename to packages/core/testResources/config-reader/no-config/.gitkeep diff --git a/packages/core/testResources/globTestFiles/sample/stryker.conf.js b/packages/core/testResources/globTestFiles/sample/stryker.conf.js index 8629480922..022cb7e741 100644 --- a/packages/core/testResources/globTestFiles/sample/stryker.conf.js +++ b/packages/core/testResources/globTestFiles/sample/stryker.conf.js @@ -6,9 +6,8 @@ module.exports = function (config) { '!testResources/sampleProject/src/Error.js', '!testResources/sampleProject/src/InfiniteAdd.js', '!testResources/sampleProject/test/FailingAddSpec.js',], - testFramework: 'jasmine', testRunner: 'karma', coverageAnalysis: 'off', plugins: ['stryker-karma-runner'] }); -}; \ No newline at end of file +}; diff --git a/packages/babel-transpiler/testResources/differentExtensions/expectedResult/excluded.es6 b/packages/core/testResources/input-files/lib/string-utils.js similarity index 100% rename from packages/babel-transpiler/testResources/differentExtensions/expectedResult/excluded.es6 rename to packages/core/testResources/input-files/lib/string-utils.js diff --git a/packages/babel-transpiler/testResources/differentExtensions/source/excluded.es6 b/packages/core/testResources/input-files/src/.mocharc.js similarity index 100% rename from packages/babel-transpiler/testResources/differentExtensions/source/excluded.es6 rename to packages/core/testResources/input-files/src/.mocharc.js diff --git a/packages/typescript/testResources/allowJsonFiles/json.json b/packages/core/testResources/input-files/src/__tests__/app.js similarity index 100% rename from packages/typescript/testResources/allowJsonFiles/json.json rename to packages/core/testResources/input-files/src/__tests__/app.js diff --git a/packages/typescript/testResources/sampleProject/node_modules/excluded.ts b/packages/core/testResources/input-files/src/app.ts similarity index 100% rename from packages/typescript/testResources/sampleProject/node_modules/excluded.ts rename to packages/core/testResources/input-files/src/app.ts diff --git a/packages/webpack-transpiler/testResources/inputFileSystem/dir1/1.gitkeep b/packages/core/testResources/input-files/src/components/calculator/calculator.component.spec.tsx similarity index 100% rename from packages/webpack-transpiler/testResources/inputFileSystem/dir1/1.gitkeep rename to packages/core/testResources/input-files/src/components/calculator/calculator.component.spec.tsx diff --git a/packages/webpack-transpiler/testResources/inputFileSystem/dir2/2.gitkeep b/packages/core/testResources/input-files/src/components/calculator/calculator.component.test.tsx similarity index 100% rename from packages/webpack-transpiler/testResources/inputFileSystem/dir2/2.gitkeep rename to packages/core/testResources/input-files/src/components/calculator/calculator.component.test.tsx diff --git a/packages/webpack-transpiler/testResources/inputFileSystem/dir3/3.gitkeep b/packages/core/testResources/input-files/src/components/calculator/calculator.component.tsx similarity index 100% rename from packages/webpack-transpiler/testResources/inputFileSystem/dir3/3.gitkeep rename to packages/core/testResources/input-files/src/components/calculator/calculator.component.tsx diff --git a/packages/core/testResources/input-files/src/components/heading/heading.component.spec.vue b/packages/core/testResources/input-files/src/components/heading/heading.component.spec.vue new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/core/testResources/input-files/src/components/heading/heading.component.vue b/packages/core/testResources/input-files/src/components/heading/heading.component.vue new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/core/testResources/input-files/src/index.html b/packages/core/testResources/input-files/src/index.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/core/testResources/input-files/src/services/storage.Spec.tsx b/packages/core/testResources/input-files/src/services/storage.Spec.tsx new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/core/testResources/input-files/src/services/storage.Test.tsx b/packages/core/testResources/input-files/src/services/storage.Test.tsx new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/core/testResources/input-files/src/services/storage.ts b/packages/core/testResources/input-files/src/services/storage.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/core/testResources/input-files/src/services/test.ts b/packages/core/testResources/input-files/src/services/test.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/core/testResources/input-files/src/utils/__tests__/commonjs.cjs b/packages/core/testResources/input-files/src/utils/__tests__/commonjs.cjs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/core/testResources/input-files/src/utils/commonjs.cjs b/packages/core/testResources/input-files/src/utils/commonjs.cjs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/core/testResources/input-files/src/utils/esm.mjs b/packages/core/testResources/input-files/src/utils/esm.mjs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/core/testResources/input-files/src/utils/esm.spec.mjs b/packages/core/testResources/input-files/src/utils/esm.spec.mjs new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/core/testResources/input-files/test/setup.js b/packages/core/testResources/input-files/test/setup.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/core/testResources/sandbox-tsconfig-rewriter/mono-repo/src/tsconfig.json b/packages/core/testResources/sandbox-tsconfig-rewriter/mono-repo/src/tsconfig.json new file mode 100644 index 0000000000..be6b8218d6 --- /dev/null +++ b/packages/core/testResources/sandbox-tsconfig-rewriter/mono-repo/src/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../../tsconfig.settings.json", + "references": [ + { + "path": "../../model" + } + ] +} diff --git a/packages/core/testResources/sandbox-tsconfig-rewriter/mono-repo/test/tsconfig.test.json b/packages/core/testResources/sandbox-tsconfig-rewriter/mono-repo/test/tsconfig.test.json new file mode 100644 index 0000000000..58c868df9f --- /dev/null +++ b/packages/core/testResources/sandbox-tsconfig-rewriter/mono-repo/test/tsconfig.test.json @@ -0,0 +1,8 @@ +{ + "extends": "../tsconfig.root.json", + "references": [ + { + "path": "../src" + } + ] +} diff --git a/packages/core/testResources/sandbox-tsconfig-rewriter/mono-repo/tsconfig.root.json b/packages/core/testResources/sandbox-tsconfig-rewriter/mono-repo/tsconfig.root.json new file mode 100644 index 0000000000..c1a6b41ac5 --- /dev/null +++ b/packages/core/testResources/sandbox-tsconfig-rewriter/mono-repo/tsconfig.root.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.settings.json", + "files": [], + "references": [ + { + "path": "src" + }, + { + "path": "test/tsconfig.test.json" + } + ] +} diff --git a/packages/core/tsconfig.src.json b/packages/core/tsconfig.src.json index 79345d075c..4817489634 100644 --- a/packages/core/tsconfig.src.json +++ b/packages/core/tsconfig.src.json @@ -2,16 +2,20 @@ "extends": "../../tsconfig.settings.json", "compilerOptions": { "rootDir": ".", + "noImplicitThis": true, "resolveJsonModule": true, "types": [] // Exclude global mocha functions for the sources }, "include": [ - "src" + "src", "../util/src/Task.ts" ], "references": [ { "path": "../api/tsconfig.src.json" }, + { + "path": "../instrumenter/src" + }, { "path": "../util/tsconfig.src.json" } diff --git a/packages/core/tsconfig.stryker.json b/packages/core/tsconfig.stryker.json deleted file mode 100644 index 0f7ed99680..0000000000 --- a/packages/core/tsconfig.stryker.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": "./tsconfig.test.json", - "include": [ - "src", - "test" - ], -} diff --git a/packages/grunt-stryker/CHANGELOG.md b/packages/grunt-stryker/CHANGELOG.md index 3f20fd6727..b122a46f1e 100644 --- a/packages/grunt-stryker/CHANGELOG.md +++ b/packages/grunt-stryker/CHANGELOG.md @@ -3,6 +3,94 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [4.0.0-beta.10](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.9...v4.0.0-beta.10) (2020-10-05) + +**Note:** Version bump only for package grunt-stryker + + + + + +# [4.0.0-beta.9](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.8...v4.0.0-beta.9) (2020-09-30) + +**Note:** Version bump only for package grunt-stryker + + + + + +# [4.0.0-beta.8](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.7...v4.0.0-beta.8) (2020-09-22) + +**Note:** Version bump only for package grunt-stryker + + + + + +# [4.0.0-beta.7](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.6...v4.0.0-beta.7) (2020-09-17) + +**Note:** Version bump only for package grunt-stryker + + + + + +# [4.0.0-beta.6](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.5...v4.0.0-beta.6) (2020-09-10) + +**Note:** Version bump only for package grunt-stryker + + + + + +# [4.0.0-beta.5](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.4...v4.0.0-beta.5) (2020-09-09) + +**Note:** Version bump only for package grunt-stryker + + + + + +# [4.0.0-beta.4](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.3...v4.0.0-beta.4) (2020-08-29) + +**Note:** Version bump only for package grunt-stryker + + + + + +# [4.0.0-beta.3](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.2...v4.0.0-beta.3) (2020-08-19) + +**Note:** Version bump only for package grunt-stryker + + + + + +# [4.0.0-beta.2](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.1...v4.0.0-beta.2) (2020-08-07) + +**Note:** Version bump only for package grunt-stryker + + + + + +# [4.0.0-beta.1](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.0...v4.0.0-beta.1) (2020-07-17) + +**Note:** Version bump only for package grunt-stryker + + + + + +# [4.0.0-beta.0](https://github.com/stryker-mutator/stryker/compare/v3.3.1...v4.0.0-beta.0) (2020-07-10) + +**Note:** Version bump only for package grunt-stryker + + + + + ## [3.3.1](https://github.com/stryker-mutator/stryker/compare/v3.3.0...v3.3.1) (2020-07-04) **Note:** Version bump only for package grunt-stryker diff --git a/packages/grunt-stryker/package.json b/packages/grunt-stryker/package.json index 0246c5244c..213c181d3b 100644 --- a/packages/grunt-stryker/package.json +++ b/packages/grunt-stryker/package.json @@ -1,7 +1,7 @@ { "name": "grunt-stryker", "description": "Grunt plugin for the mutation testing framework 'stryker'", - "version": "3.3.1", + "version": "4.0.0-beta.10", "bugs": { "url": "https://github.com/stryker-mutator/stryker/issues" }, @@ -33,11 +33,11 @@ }, "main": "Gruntfile.js", "devDependencies": { - "@stryker-mutator/api": "^3.3.1", + "@stryker-mutator/api": "4.0.0-beta.10", "@types/node": "^14.0.1" }, "peerDependencies": { - "@stryker-mutator/core": "^3.0.0", + "@stryker-mutator/core": "4.0.0-beta.4", "grunt": ">=0.4.5" } } diff --git a/packages/mutator-specification/.eslintrc b/packages/instrumenter/.eslintrc similarity index 100% rename from packages/mutator-specification/.eslintrc rename to packages/instrumenter/.eslintrc diff --git a/packages/instrumenter/.gitattributes b/packages/instrumenter/.gitattributes new file mode 100644 index 0000000000..d8a5f3c8d1 --- /dev/null +++ b/packages/instrumenter/.gitattributes @@ -0,0 +1,4 @@ +* text eol=lf + +# Denote all files that are truly binary and should not be modified. +*.png binary \ No newline at end of file diff --git a/packages/instrumenter/.mocharc.jsonc b/packages/instrumenter/.mocharc.jsonc new file mode 100644 index 0000000000..9442947f8e --- /dev/null +++ b/packages/instrumenter/.mocharc.jsonc @@ -0,0 +1,7 @@ +{ + "require": ["dist/test/setup.js"], + "spec": [ + "dist/test/unit/**/*.js", + "dist/test/integration/**/*.js" + ] +} diff --git a/packages/instrumenter/.npmignore b/packages/instrumenter/.npmignore new file mode 100644 index 0000000000..026a43bb64 --- /dev/null +++ b/packages/instrumenter/.npmignore @@ -0,0 +1,6 @@ +* + +!dist/src/**/*.js +!dist/src/**/*.map +!dist/src/**/*.ts +!src/**/* diff --git a/packages/mutator-specification/.npmrc b/packages/instrumenter/.npmrc similarity index 100% rename from packages/mutator-specification/.npmrc rename to packages/instrumenter/.npmrc diff --git a/packages/instrumenter/.nycrc.json b/packages/instrumenter/.nycrc.json new file mode 100644 index 0000000000..9fd4757794 --- /dev/null +++ b/packages/instrumenter/.nycrc.json @@ -0,0 +1,11 @@ +{ + "include": [ + "dist/src/**/*.js" + ], + "excludeAfterRemap": false, + "checkCoverage": true, + "lines": 95, + "functions": 95, + "branches": 95, + "statements": 95 +} diff --git a/packages/instrumenter/.vscode/launch.json b/packages/instrumenter/.vscode/launch.json new file mode 100644 index 0000000000..7919d57ff5 --- /dev/null +++ b/packages/instrumenter/.vscode/launch.json @@ -0,0 +1,25 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Unit / Integration tests", + "program": "${workspaceRoot}/../../node_modules/mocha/bin/_mocha", + "internalConsoleOptions": "openOnSessionStart", + "outFiles": [ + "${workspaceRoot}/dist/**/*.js" + ], + "skipFiles": [ + "/**" + ], + "args": [ + "--no-timeout" + ], + "env": { + // Set CHAI_JEST_SNAPSHOT_UPDATE_ALL variable when you want to update the snapshot files + // "CHAI_JEST_SNAPSHOT_UPDATE_ALL": "true" + } + } + ] +} diff --git a/packages/instrumenter/CHANGELOG.md b/packages/instrumenter/CHANGELOG.md new file mode 100644 index 0000000000..01422e1cfc --- /dev/null +++ b/packages/instrumenter/CHANGELOG.md @@ -0,0 +1,164 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +# [4.0.0-beta.10](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.9...v4.0.0-beta.10) (2020-10-05) + + +### Bug Fixes + +* **instrumenter:** switch case mutant placer ([#2518](https://github.com/stryker-mutator/stryker/issues/2518)) ([a560711](https://github.com/stryker-mutator/stryker/commit/a560711023990dca950700da18269e78249b5c49)) + + +### Features + +* **instrumenter:** add excludedMutations support ([#2513](https://github.com/stryker-mutator/stryker/issues/2513)) ([bfd714f](https://github.com/stryker-mutator/stryker/commit/bfd714fe1b4f9c3b2468164a95d0c5bd0cbc8fcf)) + + + + + +# [4.0.0-beta.9](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.8...v4.0.0-beta.9) (2020-09-30) + + +### Bug Fixes + +* **instrumenter:** only add header when there are mutats ([#2503](https://github.com/stryker-mutator/stryker/issues/2503)) ([8f989cc](https://github.com/stryker-mutator/stryker/commit/8f989cceb8fea5e66e3055a623f238ce85ef1025)) +* **shebang:** support shebang in in files ([#2510](https://github.com/stryker-mutator/stryker/issues/2510)) ([7d2dd80](https://github.com/stryker-mutator/stryker/commit/7d2dd80f2c7a89f31c8f96c2e911a6f9beaf7cbc)) + + + + + +# [4.0.0-beta.8](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.7...v4.0.0-beta.8) (2020-09-22) + + +### Bug Fixes + +* **instrumenter:** ignore `declare` syntax ([b1faa16](https://github.com/stryker-mutator/stryker/commit/b1faa1603f68dded5d694cdb41b6e75b05ac9e1a)) + + +### Features + +* **instrumenter:** improve placement error ([12e097e](https://github.com/stryker-mutator/stryker/commit/12e097e287d24e41656d2b3897335b3f93654e5d)) + + + + + +# [4.0.0-beta.7](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.6...v4.0.0-beta.7) (2020-09-17) + + +### Bug Fixes + +* **instrumenter:** don't mutate constructor blocks with initialized class properties ([#2484](https://github.com/stryker-mutator/stryker/issues/2484)) ([ca464a3](https://github.com/stryker-mutator/stryker/commit/ca464a31e180aada677464591154c41295fbc50c)), closes [#2474](https://github.com/stryker-mutator/stryker/issues/2474) +* **instrumenter:** place mutants in if statements ([#2481](https://github.com/stryker-mutator/stryker/issues/2481)) ([4df4102](https://github.com/stryker-mutator/stryker/commit/4df410263be09468323d7f64d95a8a839432e52f)), closes [#2469](https://github.com/stryker-mutator/stryker/issues/2469) + + + + + +# [4.0.0-beta.6](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.5...v4.0.0-beta.6) (2020-09-10) + + +### Bug Fixes + +* **instrumenter:** skip `as` expressions ([#2471](https://github.com/stryker-mutator/stryker/issues/2471)) ([2432d84](https://github.com/stryker-mutator/stryker/commit/2432d8442bd783448568a92c57349ecab626def0)) + + + + + +# [4.0.0-beta.5](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.4...v4.0.0-beta.5) (2020-09-09) + + +### Bug Fixes + +* **mocha-runner:** don't allow custom timeout ([#2463](https://github.com/stryker-mutator/stryker/issues/2463)) ([e90b563](https://github.com/stryker-mutator/stryker/commit/e90b5635907dfcd36de98d73fa6c2da31f69fbed)) + + +### Features + +* **typescript:** Disable type checking ([#2446](https://github.com/stryker-mutator/stryker/issues/2446)) ([3ff996b](https://github.com/stryker-mutator/stryker/commit/3ff996b7516b7782434d86aa9aecbee334978a7f)), closes [#2438](https://github.com/stryker-mutator/stryker/issues/2438) + + + + + +# [4.0.0-beta.4](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.3...v4.0.0-beta.4) (2020-08-29) + +**Note:** Version bump only for package @stryker-mutator/instrumenter + + + + + +# [4.0.0-beta.3](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.2...v4.0.0-beta.3) (2020-08-19) + + +### Bug Fixes + +* **instrumenter:** support anonymous function names ([#2388](https://github.com/stryker-mutator/stryker/issues/2388)) ([c7d150a](https://github.com/stryker-mutator/stryker/commit/c7d150ab1af4341bb59381ef55fa54eff0113a11)), closes [#2362](https://github.com/stryker-mutator/stryker/issues/2362) + + +### Features + +* **core:** strip comments in sandbox ([#2365](https://github.com/stryker-mutator/stryker/issues/2365)) ([55f27f2](https://github.com/stryker-mutator/stryker/commit/55f27f29b6994096c9aad038958ee93e9fa0f035)), closes [#2364](https://github.com/stryker-mutator/stryker/issues/2364) +* **instrumenter:** add support for `.mjs` and `.cjs` file formats ([#2391](https://github.com/stryker-mutator/stryker/issues/2391)) ([5ba4c5c](https://github.com/stryker-mutator/stryker/commit/5ba4c5c93a721982019aa7e124e491decec2e9f0)) + + + + + +# [4.0.0-beta.2](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.1...v4.0.0-beta.2) (2020-08-07) + + +### Bug Fixes + +* **ArrowFunction mutator:** don't mutate () => undefined ([#2313](https://github.com/stryker-mutator/stryker/issues/2313)) ([310145e](https://github.com/stryker-mutator/stryker/commit/310145ec853a56b6520e0358861ba492b5dff0a6)) +* **instrumenter:** don't mutate string literals in object properties ([#2354](https://github.com/stryker-mutator/stryker/issues/2354)) ([cd43952](https://github.com/stryker-mutator/stryker/commit/cd439522650fe59c1607d00d58d331b5dc45fe39)) +* **mutator:** issue with block statement mutator ([#2342](https://github.com/stryker-mutator/stryker/issues/2342)) ([aaa4ff6](https://github.com/stryker-mutator/stryker/commit/aaa4ff6cd5bdfadef5047ec2c405ad0f385249ef)), closes [#2314](https://github.com/stryker-mutator/stryker/issues/2314) + + +### Features + +* **command:** Support command test runner with mutation switching ([#2345](https://github.com/stryker-mutator/stryker/issues/2345)) ([59b1cfc](https://github.com/stryker-mutator/stryker/commit/59b1cfc06c4f8f5ec1e55dce4823e0f9c384b16c)) +* **jest-runner:** support mutation switching ([#2350](https://github.com/stryker-mutator/stryker/issues/2350)) ([9e6e6e0](https://github.com/stryker-mutator/stryker/commit/9e6e6e077731344ed0588d64b5c8ba2f19c8492e)) + + + + + +# [4.0.0-beta.1](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.0...v4.0.0-beta.1) (2020-07-17) + +**Note:** Version bump only for package @stryker-mutator/instrumenter + + + + + +# [4.0.0-beta.0](https://github.com/stryker-mutator/stryker/compare/v3.3.1...v4.0.0-beta.0) (2020-07-10) + + +### Bug Fixes + +* **instrumenter:** don't mutate `require` ([963e289](https://github.com/stryker-mutator/stryker/commit/963e28921c48ec2d4113ded0eefde7049fff3263)) + + +### Features + +* **core:** add support for checker plugins ([#2285](https://github.com/stryker-mutator/stryker/issues/2285)) ([69358e1](https://github.com/stryker-mutator/stryker/commit/69358e1423701c730e29d303119a08d74081f340)) +* **html-parser:** add `// [@ts-nocheck](https://github.com/ts-nocheck)` to scripts ([8ceff31](https://github.com/stryker-mutator/stryker/commit/8ceff31aabda981551a5f5997e820fc9af76565d)) +* **instrumenter:** add mutant placers ([#2224](https://github.com/stryker-mutator/stryker/issues/2224)) ([0e05025](https://github.com/stryker-mutator/stryker/commit/0e0502523a32ffbe836e93da9ade479b01393c5a)) +* **instrumenter:** add parsers ([#2222](https://github.com/stryker-mutator/stryker/issues/2222)) ([3b57ef2](https://github.com/stryker-mutator/stryker/commit/3b57ef23dd5b348dcdff205600989aea2c7fbcf0)) +* **instrumenter:** add the mutation testing instrumenter ([#2212](https://github.com/stryker-mutator/stryker/issues/2212)) ([197e177](https://github.com/stryker-mutator/stryker/commit/197e177cb730952b22d3e5929f4799c2bae476d7)) +* **instrumenter:** add transformers ([#2234](https://github.com/stryker-mutator/stryker/issues/2234)) ([61c8fe6](https://github.com/stryker-mutator/stryker/commit/61c8fe65e35bb95b786a0e2bebbe57166ffbc480)) +* **instrumenter:** allow override of babel plugins ([8758cfd](https://github.com/stryker-mutator/stryker/commit/8758cfdda8ac2bfa761568f55ddee48c2a23f0e0)) +* **instrumenter:** implement `Instrumenter` class ([8df9172](https://github.com/stryker-mutator/stryker/commit/8df9172b95b6e277f44302469edb3c00324a02bd)) +* **mutators:** add mutators to instrumenter package ([#2266](https://github.com/stryker-mutator/stryker/issues/2266)) ([3b87743](https://github.com/stryker-mutator/stryker/commit/3b87743645db9923d4c85146ea861aa1b7265447)) + + +### BREAKING CHANGES + +* **core:** * `--maxConcurrentTestRunners` is now deprecated. Please use `--concurrency` instead. diff --git a/packages/instrumenter/LICENSE b/packages/instrumenter/LICENSE new file mode 100644 index 0000000000..8dada3edaf --- /dev/null +++ b/packages/instrumenter/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/packages/instrumenter/package.json b/packages/instrumenter/package.json new file mode 100644 index 0000000000..d3c7f21aa5 --- /dev/null +++ b/packages/instrumenter/package.json @@ -0,0 +1,52 @@ +{ + "name": "@stryker-mutator/instrumenter", + "version": "4.0.0-beta.10", + "description": "The code instrumenter used in Stryker, the JavaScript mutation testing framework", + "main": "dist/src/index.js", + "scripts": { + "test": "nyc npm run mocha", + "mocha": "mocha", + "stryker": "node ../core/bin/stryker run" + }, + "repository": { + "type": "git", + "url": "https://github.com/stryker-mutator/stryker", + "directory": "packages/instrumenter" + }, + "engines": { + "node": ">=10" + }, + "publishConfig": { + "access": "public" + }, + "author": "Nico Jansen ", + "contributors": [ + "Simon de Lang ", + "Nico Jansen " + ], + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/stryker-mutator/stryker/issues" + }, + "homepage": "https://stryker-mutator.io", + "dependencies": { + "@babel/core": "~7.11.4", + "@babel/generator": "~7.11.4", + "@babel/parser": "~7.11.4", + "@babel/plugin-proposal-decorators": "~7.10.5", + "@babel/preset-typescript": "~7.10.4", + "@stryker-mutator/api": "4.0.0-beta.10", + "@stryker-mutator/util": "4.0.0-beta.10", + "angular-html-parser": "~1.7.0" + }, + "devDependencies": { + "@babel/preset-react": "~7.10.4", + "@stryker-mutator/test-helpers": "4.0.0-beta.10", + "@types/babel__core": "~7.1.9", + "@types/babel__generator": "~7.6.1", + "@types/babel__parser": "~7.1.1", + "@types/chai-jest-snapshot": "~1.3.5", + "babel-plugin-transform-decorators-legacy": "~1.3.5", + "chai-jest-snapshot": "~2.0.0" + } +} diff --git a/packages/instrumenter/src/disable-type-checks.ts b/packages/instrumenter/src/disable-type-checks.ts new file mode 100644 index 0000000000..91a7fbf5b7 --- /dev/null +++ b/packages/instrumenter/src/disable-type-checks.ts @@ -0,0 +1,91 @@ +import { types } from '@babel/core'; +import { File, Range } from '@stryker-mutator/api/core'; +import { notEmpty } from '@stryker-mutator/util'; + +import { createParser, getFormat, ParserOptions } from './parsers'; +import { AstFormat, HtmlAst, JSAst, TSAst } from './syntax'; + +const commentDirectiveRegEx = /^(\s*)@(ts-[a-z-]+).*$/; +const tsDirectiveLikeRegEx = /@(ts-[a-z-]+)/; + +export async function disableTypeChecks(file: File, options: ParserOptions) { + if (isJSFileWithoutTSDirectives(file)) { + // Performance optimization. Only parse the file when it has a change of containing a `// @ts-` directive + return new File(file.name, prefixWithNoCheck(file.textContent)); + } + const parse = createParser(options); + const ast = await parse(file.textContent, file.name); + switch (ast.format) { + case AstFormat.JS: + case AstFormat.TS: + return new File(file.name, disableTypeCheckingInBabelAst(ast)); + case AstFormat.Html: + return new File(file.name, disableTypeCheckingInHtml(ast)); + } +} + +function isJSFileWithoutTSDirectives(file: File) { + const format = getFormat(file.name); + return (format === AstFormat.TS || format === AstFormat.JS) && !tsDirectiveLikeRegEx.test(file.textContent); +} + +function disableTypeCheckingInBabelAst(ast: JSAst | TSAst): string { + return prefixWithNoCheck(removeTSDirectives(ast.rawContent, ast.root.comments)); +} + +function prefixWithNoCheck(code: string): string { + if (code.startsWith('#')) { + // first line has a shebang (#!/usr/bin/env node) + const newLineIndex = code.indexOf('\n'); + if (newLineIndex > 0) { + return `${code.substr(0, newLineIndex)}\n// @ts-nocheck\n${code.substr(newLineIndex + 1)}`; + } else { + return code; + } + } else { + return `// @ts-nocheck\n${code}`; + } +} + +function disableTypeCheckingInHtml(ast: HtmlAst): string { + const sortedScripts = [...ast.root.scripts].sort((a, b) => a.root.start! - b.root.start!); + let currentIndex = 0; + let html = ''; + for (const script of sortedScripts) { + html += ast.rawContent.substring(currentIndex, script.root.start!); + html += '\n'; + html += prefixWithNoCheck(removeTSDirectives(script.rawContent, script.root.comments)); + html += '\n'; + currentIndex = script.root.end!; + } + html += ast.rawContent.substr(currentIndex); + return html; +} + +function removeTSDirectives(text: string, comments: Array | null): string { + const directiveRanges = comments + ?.map(tryParseTSDirective) + .filter(notEmpty) + .sort((a, b) => a[0] - b[0]); + if (directiveRanges) { + let currentIndex = 0; + let pruned = ''; + for (const directiveRange of directiveRanges) { + pruned += text.substring(currentIndex, directiveRange[0]); + currentIndex = directiveRange[1]; + } + pruned += text.substr(currentIndex); + return pruned; + } else { + return text; + } +} + +function tryParseTSDirective(comment: types.CommentBlock | types.CommentLine): Range | undefined { + const match = commentDirectiveRegEx.exec(comment.value); + if (match) { + const directiveStartPos = comment.start + match[1].length + 2; // +2 to account for the `//` or `/*` start character + return [directiveStartPos, directiveStartPos + match[2].length + 1]; + } + return undefined; +} diff --git a/packages/instrumenter/src/index.ts b/packages/instrumenter/src/index.ts new file mode 100644 index 0000000000..db6d4a5590 --- /dev/null +++ b/packages/instrumenter/src/index.ts @@ -0,0 +1,5 @@ +export * from './instrumenter'; +export * from './instrument-result'; +export * from './instrumenter-options'; +export * from './disable-type-checks'; +export type { ParserOptions } from './parsers'; diff --git a/packages/instrumenter/src/instrument-result.ts b/packages/instrumenter/src/instrument-result.ts new file mode 100644 index 0000000000..1ff558574b --- /dev/null +++ b/packages/instrumenter/src/instrument-result.ts @@ -0,0 +1,6 @@ +import { File, Mutant } from '@stryker-mutator/api/core'; + +export interface InstrumentResult { + files: readonly File[]; + mutants: readonly Mutant[]; +} diff --git a/packages/instrumenter/src/instrumenter-options.ts b/packages/instrumenter/src/instrumenter-options.ts new file mode 100644 index 0000000000..2b945399b9 --- /dev/null +++ b/packages/instrumenter/src/instrumenter-options.ts @@ -0,0 +1,4 @@ +import { ParserOptions } from './parsers'; +import { TransformerOptions } from './transformers'; + +export interface InstrumenterOptions extends ParserOptions, TransformerOptions {} diff --git a/packages/instrumenter/src/instrumenter.ts b/packages/instrumenter/src/instrumenter.ts new file mode 100644 index 0000000000..9df4198704 --- /dev/null +++ b/packages/instrumenter/src/instrumenter.ts @@ -0,0 +1,49 @@ +import path from 'path'; + +import { tokens, commonTokens } from '@stryker-mutator/api/plugin'; +import { Logger } from '@stryker-mutator/api/logging'; +import { File } from '@stryker-mutator/api/core'; + +import { createParser } from './parsers'; +import { transform, MutantCollector } from './transformers'; +import { print } from './printers'; +import { InstrumentResult } from './instrument-result'; +import { InstrumenterOptions } from './instrumenter-options'; + +/** + * The instrumenter is responsible for + * * Generating mutants based on source files + * * Instrumenting the source code with the mutants placed in `mutant switches`. + * * Adding mutant coverage expressions in the source code. + * @see https://github.com/stryker-mutator/stryker/issues/1514 + */ +export class Instrumenter { + public static inject = tokens(commonTokens.logger); + + constructor(private readonly logger: Logger) {} + + public async instrument(files: readonly File[], options: InstrumenterOptions): Promise { + this.logger.debug('Instrumenting %d source files with mutants', files.length); + const mutantCollector = new MutantCollector(); + const outFiles: File[] = []; + let mutantCount = 0; + const parse = createParser(options); + for await (const file of files) { + const ast = await parse(file.textContent, file.name); + transform(ast, mutantCollector, { options }); + const mutatedContent = print(ast); + outFiles.push(new File(file.name, mutatedContent)); + if (this.logger.isDebugEnabled()) { + const nrOfMutantsInFile = mutantCollector.mutants.length - mutantCount; + mutantCount = mutantCollector.mutants.length; + this.logger.debug(`Instrumented ${path.relative(process.cwd(), file.name)} (${nrOfMutantsInFile} mutant(s))`); + } + } + const mutants = mutantCollector.mutants.map((mutant) => mutant.toApiMutant()); + this.logger.info('Instrumented %d source file(s) with %d mutant(s)', files.length, mutants.length); + return { + files: outFiles, + mutants, + }; + } +} diff --git a/packages/instrumenter/src/mutant-placers/expression-mutant-placer.ts b/packages/instrumenter/src/mutant-placers/expression-mutant-placer.ts new file mode 100644 index 0000000000..101a3679ba --- /dev/null +++ b/packages/instrumenter/src/mutant-placers/expression-mutant-placer.ts @@ -0,0 +1,78 @@ +import { NodePath, types } from '@babel/core'; + +import { Mutant } from '../mutant'; +import { createMutatedAst, mutantTestExpression, mutationCoverageSequenceExpression } from '../util/syntax-helpers'; + +import { MutantPlacer } from './mutant-placer'; + +function nameAnonymousClassOrFunctionExpression(path: NodePath) { + if ((path.isFunctionExpression() || path.isClassExpression()) && !path.node.id) { + if (path.parentPath.isVariableDeclarator() && types.isIdentifier(path.parentPath.node.id)) { + path.node.id = path.parentPath.node.id; + } else if ( + path.parentPath.isObjectProperty() && + types.isIdentifier(path.parentPath.node.key) && + path.getStatementParent()?.isVariableDeclaration() + ) { + path.node.id = path.parentPath.node.key; + } + } +} + +function nameIfAnonymous(path: NodePath): NodePath { + nameAnonymousClassOrFunctionExpression(path); + if (path.isArrowFunctionExpression() && path.parentPath.isVariableDeclarator() && types.isIdentifier(path.parentPath.node.id)) { + path.replaceWith( + types.callExpression( + types.arrowFunctionExpression( + [], + types.blockStatement([ + types.variableDeclaration('const', [types.variableDeclarator(path.parentPath.node.id, path.node)]), + types.returnStatement(path.parentPath.node.id), + ]) + ), + [] + ) + ); + } + + return path; +} + +function isValidParent(child: NodePath) { + const parent = child.parentPath; + return !isObjectPropertyKey() && !parent.isTaggedTemplateExpression(); + function isObjectPropertyKey() { + return parent.isObjectProperty() && parent.node.key === child.node; + } +} + +/** + * Places the mutants with a conditional expression: `global.activeMutant === 1? mutatedCode : regularCode`; + */ +const expressionMutantPlacer: MutantPlacer = (path: NodePath, mutants: Mutant[]): boolean => { + if (path.isExpression() && isValidParent(path)) { + // First calculated the mutated ast before we start to apply mutants. + const appliedMutants = mutants.map((mutant) => ({ + mutant, + ast: createMutatedAst(path as NodePath, mutant), + })); + + // Make sure anonymous functions and classes keep their 'name' property + path.replaceWith(nameIfAnonymous(path)); + + // Add the mutation coverage expression + path.replaceWith(mutationCoverageSequenceExpression(mutants, path.node)); + + // Now apply the mutants + for (const appliedMutant of appliedMutants) { + path.replaceWith(types.conditionalExpression(mutantTestExpression(appliedMutant.mutant.id), appliedMutant.ast, path.node)); + } + return true; + } else { + return false; + } +}; + +// Export it after initializing so `fn.name` is properly set +export { expressionMutantPlacer }; diff --git a/packages/instrumenter/src/mutant-placers/index.ts b/packages/instrumenter/src/mutant-placers/index.ts new file mode 100644 index 0000000000..a6145d18df --- /dev/null +++ b/packages/instrumenter/src/mutant-placers/index.ts @@ -0,0 +1,42 @@ +import path from 'path'; + +export * from './mutant-placer'; +import { NodePath } from '@babel/core'; + +import { Mutant } from '../mutant'; + +import { MutantPlacer } from './mutant-placer'; +import { statementMutantPlacer } from './statement-mutant-placer'; +import { expressionMutantPlacer } from './expression-mutant-placer'; +import { switchCaseMutantPlacer } from './switch-case-mutant-placer'; + +export const MUTANT_PLACERS = Object.freeze([expressionMutantPlacer, statementMutantPlacer, switchCaseMutantPlacer]); + +/** + * Represents a mutant placer, tries to place a mutant in the AST with corresponding mutation switch and mutant covering expression + * @see https://github.com/stryker-mutator/stryker/issues/1514 + * @param node The ast node to try and replace with a mutated + * @param mutants The mutants to place in the AST node + * @param fileName The name of the file where the mutants are placed + * @param mutantPlacers The mutant placers to use (for unit testing purposes) + */ +export function placeMutants(node: NodePath, mutants: Mutant[], fileName: string, mutantPlacers: readonly MutantPlacer[] = MUTANT_PLACERS) { + if (mutants.length) { + for (const placer of mutantPlacers) { + try { + if (placer(node, mutants)) { + return true; + } + } catch (error) { + const location = `${path.relative(process.cwd(), fileName)}:${node.node.loc?.start.line}:${node.node.loc?.start.column}`; + const message = `${placer.name} could not place mutants with type(s): "${mutants.map((mutant) => mutant.mutatorName).join(', ')}"`; + throw node.buildCodeFrameError( + `${location} ${message}. Either remove this file from the list of files to be mutated, or ignore the mutators. Please report this issue at https://github.com/stryker-mutator/stryker/issues/new?assignees=&labels=%F0%9F%90%9B+Bug&template=bug_report.md&title=${encodeURIComponent( + message + )}.` + ); + } + } + } + return false; +} diff --git a/packages/instrumenter/src/mutant-placers/mutant-placer.ts b/packages/instrumenter/src/mutant-placers/mutant-placer.ts new file mode 100644 index 0000000000..b5a8f636b5 --- /dev/null +++ b/packages/instrumenter/src/mutant-placers/mutant-placer.ts @@ -0,0 +1,5 @@ +import { NodePath } from '@babel/core'; + +import { Mutant } from '../mutant'; + +export type MutantPlacer = (node: NodePath, mutants: Mutant[]) => boolean; diff --git a/packages/instrumenter/src/mutant-placers/statement-mutant-placer.ts b/packages/instrumenter/src/mutant-placers/statement-mutant-placer.ts new file mode 100644 index 0000000000..8dbaa5cc1e --- /dev/null +++ b/packages/instrumenter/src/mutant-placers/statement-mutant-placer.ts @@ -0,0 +1,39 @@ +import { types } from '@babel/core'; + +import { mutantTestExpression, createMutatedAst, mutationCoverageSequenceExpression } from '../util/syntax-helpers'; + +import { MutantPlacer } from './mutant-placer'; + +/** + * Mutant placer that places mutants in statements that allow it. + * It uses an `if` statement to do so + */ +const statementMutantPlacer: MutantPlacer = (path, mutants) => { + if (path.isStatement()) { + // First transform the mutated ast before we start to apply mutants. + const appliedMutants = mutants.map((mutant) => ({ + mutant, + ast: createMutatedAst(path, mutant), + })); + + const instrumentedAst = appliedMutants.reduce( + // Add if statements per mutant + (prev: types.Statement, { ast, mutant }) => types.ifStatement(mutantTestExpression(mutant.id), types.blockStatement([ast]), prev), + path.isBlockStatement() + ? types.blockStatement([types.expressionStatement(mutationCoverageSequenceExpression(mutants)), ...path.node.body]) + : types.blockStatement([types.expressionStatement(mutationCoverageSequenceExpression(mutants)), path.node]) + ); + if (path.isBlockStatement()) { + path.replaceWith(types.blockStatement([instrumentedAst])); + } else { + path.replaceWith(instrumentedAst); + } + + return true; + } else { + return false; + } +}; + +// Export it after initializing so `fn.name` is properly set +export { statementMutantPlacer }; diff --git a/packages/instrumenter/src/mutant-placers/switch-case-mutant-placer.ts b/packages/instrumenter/src/mutant-placers/switch-case-mutant-placer.ts new file mode 100644 index 0000000000..3642add683 --- /dev/null +++ b/packages/instrumenter/src/mutant-placers/switch-case-mutant-placer.ts @@ -0,0 +1,44 @@ +import { types } from '@babel/core'; + +import { createMutatedAst, mutantTestExpression, mutationCoverageSequenceExpression } from '../util'; + +import { MutantPlacer } from './mutant-placer'; + +/** + * Places the mutants with consequent of a SwitchCase node. Uses an if-statement to do so. + * @example + * case 'foo': + * if (stryMutAct_9fa48(0)) {} else { + * stryCov_9fa48(0); + * console.log('bar'); + * break; + * } + */ +const switchCaseMutantPlacer: MutantPlacer = (path, mutants): boolean => { + if (path.isSwitchCase()) { + // First transform the mutated ast before we start to apply mutants. + const appliedMutants = mutants.map((mutant) => { + const ast = createMutatedAst(path, mutant); + if (!types.isSwitchCase(ast)) { + throw new Error(`${switchCaseMutantPlacer.name} can only place SwitchCase syntax`); + } + return { + ast, + mutant, + }; + }); + + const instrumentedConsequent = appliedMutants.reduce( + // Add if statements per mutant + (prev: types.Statement, { ast, mutant }) => types.ifStatement(mutantTestExpression(mutant.id), types.blockStatement(ast.consequent), prev), + types.blockStatement([types.expressionStatement(mutationCoverageSequenceExpression(mutants)), ...path.node.consequent]) + ); + path.replaceWith(types.switchCase(path.node.test, [instrumentedConsequent])); + return true; + } + + return false; +}; + +// Export it after initializing so `fn.name` is properly set +export { switchCaseMutantPlacer }; diff --git a/packages/instrumenter/src/mutant.ts b/packages/instrumenter/src/mutant.ts new file mode 100644 index 0000000000..3900d153ac --- /dev/null +++ b/packages/instrumenter/src/mutant.ts @@ -0,0 +1,54 @@ +import { types } from '@babel/core'; +import generate from '@babel/generator'; +import { Mutant as ApiMutant, Location, Position } from '@stryker-mutator/api/core'; + +export interface NodeMutation { + replacement: types.Node; + original: types.Node; +} +export interface NamedNodeMutation extends NodeMutation { + mutatorName: string; + ignoreReason?: string; +} + +export class Mutant { + public readonly replacementCode: string; + public readonly original: types.Node; + public readonly replacement: types.Node; + public readonly mutatorName: string; + public readonly ignoreReason: string | undefined; + + constructor(public readonly id: number, public readonly fileName: string, specs: NamedNodeMutation) { + this.original = specs.original; + this.replacement = specs.replacement; + this.mutatorName = specs.mutatorName; + this.ignoreReason = specs.ignoreReason; + this.replacementCode = generate(this.replacement).code; + } + + public toApiMutant(): ApiMutant { + return { + fileName: this.fileName, + id: this.id, + location: toApiLocation(this.original.loc!), + mutatorName: this.mutatorName, + range: [this.original.start!, this.original.end!], + replacement: this.replacementCode, + ignoreReason: this.ignoreReason, + }; + } +} + +function toApiLocation(source: types.SourceLocation): Location { + return { + start: toPosition(source.start), + end: toPosition(source.end), + }; +} + +function toPosition(source: Position): Position { + return { + column: source.column, + line: source.line - 1, // Stryker works 0-based internally + }; +} diff --git a/packages/instrumenter/src/mutators/arithmetic-operator-mutator.ts b/packages/instrumenter/src/mutators/arithmetic-operator-mutator.ts new file mode 100644 index 0000000000..da2f4de222 --- /dev/null +++ b/packages/instrumenter/src/mutators/arithmetic-operator-mutator.ts @@ -0,0 +1,34 @@ +import { NodePath, types } from '@babel/core'; + +import { NodeMutation } from '../mutant'; + +import { NodeMutator } from './node-mutator'; + +enum ArithmeticOperators { + '+' = '-', + '-' = '+', + '*' = '/', + '/' = '*', + '%' = '*', +} + +export class ArithmeticOperatorMutator implements NodeMutator { + private readonly operators = ArithmeticOperators; + + public name = 'ArithmeticOperator'; + + public mutate(path: NodePath): NodeMutation[] { + if (path.isBinaryExpression() && this.isSupported(path.node.operator)) { + const mutatedOperator = this.operators[path.node.operator]; + const replacement = types.cloneNode(path.node, false); + replacement.operator = mutatedOperator; + return [{ original: path.node, replacement }]; + } + + return []; + } + + private isSupported(operator: string): operator is keyof typeof ArithmeticOperators { + return Object.keys(this.operators).includes(operator); + } +} diff --git a/packages/instrumenter/src/mutators/array-declaration-mutator.ts b/packages/instrumenter/src/mutators/array-declaration-mutator.ts new file mode 100644 index 0000000000..d91755df35 --- /dev/null +++ b/packages/instrumenter/src/mutators/array-declaration-mutator.ts @@ -0,0 +1,25 @@ +import { NodePath, types } from '@babel/core'; + +import { NodeMutation } from '../mutant'; + +import { NodeMutator } from './node-mutator'; + +export class ArrayDeclarationMutator implements NodeMutator { + public name = 'ArrayDeclaration'; + + public mutate(path: NodePath): NodeMutation[] { + if (path.isArrayExpression()) { + const replacement = path.node.elements.length ? types.arrayExpression() : types.arrayExpression([types.stringLiteral('Stryker was here')]); + return [{ original: path.node, replacement }]; + } + if ((path.isCallExpression() || path.isNewExpression()) && types.isIdentifier(path.node.callee) && path.node.callee.name === 'Array') { + const mutatedCallArgs = path.node.arguments.length ? [] : [types.arrayExpression()]; + const replacement = types.isNewExpression(path) + ? types.newExpression(path.node.callee, mutatedCallArgs) + : types.callExpression(path.node.callee, mutatedCallArgs); + return [{ original: path.node, replacement }]; + } + + return []; + } +} diff --git a/packages/instrumenter/src/mutators/arrow-function-mutator.ts b/packages/instrumenter/src/mutators/arrow-function-mutator.ts new file mode 100644 index 0000000000..f07f24117a --- /dev/null +++ b/packages/instrumenter/src/mutators/arrow-function-mutator.ts @@ -0,0 +1,20 @@ +import * as types from '@babel/types'; +import { NodePath } from '@babel/core'; + +import { NodeMutation } from '../mutant'; + +import { NodeMutator } from '.'; + +export class ArrowFunctionMutator implements NodeMutator { + public name = 'ArrowFunction'; + + private readonly undefinedIdentifierName = 'undefined'; + + public mutate(path: NodePath): NodeMutation[] { + return path.isArrowFunctionExpression() && + !types.isBlockStatement(path.node.body) && + !(types.isIdentifier(path.node.body) && path.node.body.name === this.undefinedIdentifierName) + ? [{ original: path.node, replacement: types.arrowFunctionExpression([], types.identifier(this.undefinedIdentifierName)) }] + : []; + } +} diff --git a/packages/instrumenter/src/mutators/block-statement-mutator.ts b/packages/instrumenter/src/mutators/block-statement-mutator.ts new file mode 100644 index 0000000000..7fcc627bcb --- /dev/null +++ b/packages/instrumenter/src/mutators/block-statement-mutator.ts @@ -0,0 +1,75 @@ +import { types, NodePath } from '@babel/core'; + +import { NodeMutation } from '../mutant'; + +import { NodeMutator } from './node-mutator'; + +export class BlockStatementMutator implements NodeMutator { + public name = 'BlockStatement'; + + public mutate(path: NodePath): NodeMutation[] { + if (path.isBlockStatement() && this.isValid(path)) { + const replacement = types.cloneNode(path.node, false); + replacement.body = []; + return [{ original: path.node, replacement }]; + } else { + return []; + } + } + + private isValid(path: NodePath) { + return !this.isEmpty(path) && !this.isInvalidConstructorBody(path); + } + + private isEmpty(path: NodePath) { + return !path.node.body.length; + } + + /** + * Checks to see if a statement is an invalid constructor body + * @example + * // Invalid! + * class Foo extends Bar { + * constructor(public baz: string) { + * super(42); + * } + * } + * @example + * // Invalid! + * class Foo extends Bar { + * public baz = 'string'; + * constructor() { + * super(42); + * } + * } + * @see https://github.com/stryker-mutator/stryker/issues/2314 + * @see https://github.com/stryker-mutator/stryker/issues/2474 + */ + private isInvalidConstructorBody(blockStatement: NodePath): boolean { + return !!( + blockStatement.parentPath.isClassMethod() && + blockStatement.parentPath.node.kind === 'constructor' && + (this.containsTSParameterProperties(blockStatement.parentPath) || this.containsInitializedClassProperties(blockStatement.parentPath)) && + this.hasSuperExpressionOnFirstLine(blockStatement) + ); + } + + private containsTSParameterProperties(constructor: NodePath): boolean { + return constructor.node.params.some((param) => types.isTSParameterProperty(param)); + } + + private containsInitializedClassProperties(constructor: NodePath): boolean { + return ( + constructor.parentPath.isClassBody() && + constructor.parentPath.node.body.some((classMember) => types.isClassProperty(classMember) && classMember.value) + ); + } + + private hasSuperExpressionOnFirstLine(constructor: NodePath): boolean { + return ( + types.isExpressionStatement(constructor.node.body[0]) && + types.isCallExpression(constructor.node.body[0].expression) && + types.isSuper(constructor.node.body[0].expression.callee) + ); + } +} diff --git a/packages/instrumenter/src/mutators/boolean-literal-mutator.ts b/packages/instrumenter/src/mutators/boolean-literal-mutator.ts new file mode 100644 index 0000000000..b7eede6e71 --- /dev/null +++ b/packages/instrumenter/src/mutators/boolean-literal-mutator.ts @@ -0,0 +1,23 @@ +import * as types from '@babel/types'; +import { NodePath } from '@babel/core'; + +import { NodeMutation } from '../mutant'; + +import { NodeMutator } from '.'; + +export class BooleanLiteralMutator implements NodeMutator { + public name = 'BooleanLiteral'; + + private readonly unaryBooleanPrefix = '!'; + + public mutate(path: NodePath): NodeMutation[] { + if (path.isBooleanLiteral()) { + return [{ original: path.node, replacement: types.booleanLiteral(!path.node.value) }]; + } + if (path.isUnaryExpression() && path.node.operator === this.unaryBooleanPrefix && path.node.prefix) { + return [{ original: path.node, replacement: types.cloneNode(path.node.argument, false) }]; + } + + return []; + } +} diff --git a/packages/instrumenter/src/mutators/conditional-expression-mutator.ts b/packages/instrumenter/src/mutators/conditional-expression-mutator.ts new file mode 100644 index 0000000000..6f4fdecbf5 --- /dev/null +++ b/packages/instrumenter/src/mutators/conditional-expression-mutator.ts @@ -0,0 +1,63 @@ +import { NodePath, types } from '@babel/core'; + +import { NodeMutation } from '../mutant'; + +import { NodeMutator } from './node-mutator'; + +export class ConditionalExpressionMutator implements NodeMutator { + private readonly validOperators: string[] = ['!=', '!==', '&&', '<', '<=', '==', '===', '>', '>=', '||']; + + public name = 'ConditionalExpression'; + + private hasValidParent(node: NodePath): boolean { + return !( + types.isForStatement(node.parent) || + types.isWhileStatement(node.parent) || + types.isIfStatement(node.parent) || + types.isDoWhileStatement(node.parent) + ); + } + + private isValidOperator(operator: string): boolean { + return this.validOperators.includes(operator); + } + + public mutate(path: NodePath): NodeMutation[] { + if ((path.isBinaryExpression() || path.isLogicalExpression()) && this.hasValidParent(path) && this.isValidOperator(path.node.operator)) { + return [ + { original: path.node, replacement: types.booleanLiteral(true) }, + { original: path.node, replacement: types.booleanLiteral(false) }, + ]; + } + if (path.isDoWhileStatement() || path.isWhileStatement()) { + return [{ original: path.node.test, replacement: types.booleanLiteral(false) }]; + } + if (path.isForStatement()) { + if (!path.node.test) { + const replacement = types.cloneNode(path.node, /* deep */ false); + replacement.test = types.booleanLiteral(false); + return [{ original: path.node, replacement }]; + } + + return [{ original: path.node.test, replacement: types.booleanLiteral(false) }]; + } + if (path.isIfStatement()) { + return [ + // raw string mutations in the `if` condition + { original: path.node.test, replacement: types.booleanLiteral(true) }, + { original: path.node.test, replacement: types.booleanLiteral(false) }, + ]; + } + if ( + path.isSwitchCase() && + // if not a fallthrough case + path.node.consequent.length > 0 + ) { + const replacement = types.cloneNode(path.node); + replacement.consequent = []; + return [{ original: path.node, replacement }]; + } + + return []; + } +} diff --git a/packages/instrumenter/src/mutators/equality-operator-mutator.ts b/packages/instrumenter/src/mutators/equality-operator-mutator.ts new file mode 100644 index 0000000000..b9deafdbcd --- /dev/null +++ b/packages/instrumenter/src/mutators/equality-operator-mutator.ts @@ -0,0 +1,54 @@ +import { types, NodePath } from '@babel/core'; + +import { NodeMutation } from '../mutant'; +import { BinaryOperator } from '../util'; + +import { NodeMutator } from './node-mutator'; + +const enum EqualityOperators { + '<', + '<=', + '>', + '>=', + '==', + '!=', + '===', + '!==', +} + +export class EqualityOperatorMutator implements NodeMutator { + private readonly operators = { + '<': ['<=', '>='], + '<=': ['<', '>'], + '>': ['>=', '<='], + '>=': ['>', '<'], + '==': ['!='], + '!=': ['=='], + '===': ['!=='], + '!==': ['==='], + }; + + public name = 'EqualityOperator'; + + public mutate(path: NodePath): NodeMutation[] { + if (path.isBinaryExpression() && this.isSupported(path.node.operator)) { + const mutatedOperators: BinaryOperator[] = this.operators[path.node.operator]; + + return mutatedOperators.map((mutatedOperator) => { + const replacement = types.cloneNode(path.node, false) as types.BinaryExpression; + replacement.operator = mutatedOperator; + + return { + original: path.node, + replacement, + }; + }); + } + + return []; + } + + private isSupported(operator: string): operator is keyof EqualityOperators { + return Object.keys(this.operators).includes(operator); + } +} diff --git a/packages/instrumenter/src/mutators/index.ts b/packages/instrumenter/src/mutators/index.ts new file mode 100644 index 0000000000..f62a043848 --- /dev/null +++ b/packages/instrumenter/src/mutators/index.ts @@ -0,0 +1,50 @@ +import { NodePath } from '@babel/core'; +import { flatMap } from '@stryker-mutator/util'; + +import { NamedNodeMutation } from '../mutant'; + +import { ArithmeticOperatorMutator } from './arithmetic-operator-mutator'; +import { NodeMutator } from './node-mutator'; +import { BlockStatementMutator } from './block-statement-mutator'; +import { ConditionalExpressionMutator } from './conditional-expression-mutator'; +import { StringLiteralMutator } from './string-literal-mutator'; +import { ArrayDeclarationMutator } from './array-declaration-mutator'; +import { ArrowFunctionMutator } from './arrow-function-mutator'; +import { BooleanLiteralMutator } from './boolean-literal-mutator'; +import { EqualityOperatorMutator } from './equality-operator-mutator'; +import { LogicalOperatorMutator } from './logical-operator-mutator'; +import { ObjectLiteralMutator } from './object-literal-mutator'; +import { UnaryOperatorMutator } from './unary-operator-mutator'; +import { UpdateOperatorMutator } from './update-operator-mutator'; +import { MutatorOptions } from './mutator-options'; + +export * from './node-mutator'; +export * from './mutator-options'; + +export const mutators: NodeMutator[] = [ + new ArithmeticOperatorMutator(), + new ArrayDeclarationMutator(), + new ArrowFunctionMutator(), + new BlockStatementMutator(), + new BooleanLiteralMutator(), + new ConditionalExpressionMutator(), + new EqualityOperatorMutator(), + new LogicalOperatorMutator(), + new ObjectLiteralMutator(), + new StringLiteralMutator(), + new UnaryOperatorMutator(), + new UpdateOperatorMutator(), +]; +export const mutate = (node: NodePath, { excludedMutations }: MutatorOptions): NamedNodeMutation[] => { + return flatMap(mutators, (mutator) => + mutator.mutate(node).map((nodeMutation) => ({ ...nodeMutation, mutatorName: mutator.name, ignoreReason: formatIgnoreReason(mutator.name) })) + ); + + function formatIgnoreReason(mutatorName: string): string | undefined { + if (excludedMutations.includes(mutatorName)) { + return `Ignored because of excluded mutation "${mutatorName}"`; + } else { + return undefined; + } + } +}; diff --git a/packages/instrumenter/src/mutators/logical-operator-mutator.ts b/packages/instrumenter/src/mutators/logical-operator-mutator.ts new file mode 100644 index 0000000000..6d9c24a2d5 --- /dev/null +++ b/packages/instrumenter/src/mutators/logical-operator-mutator.ts @@ -0,0 +1,33 @@ +import * as types from '@babel/types'; +import { NodePath } from '@babel/core'; + +import { NodeMutation } from '../mutant'; + +import { NodeMutator } from '.'; + +enum LogicalOperators { + '&&' = '||', + '||' = '&&', +} + +export class LogicalOperatorMutator implements NodeMutator { + public name = 'LogicalOperator'; + + private readonly operators = LogicalOperators; + + public mutate(path: NodePath): NodeMutation[] { + if (path.isLogicalExpression() && this.isSupported(path.node.operator)) { + const mutatedOperator = this.operators[path.node.operator]; + + const replacement = types.cloneNode(path.node, false); + replacement.operator = mutatedOperator; + return [{ original: path.node, replacement }]; + } + + return []; + } + + private isSupported(operator: string): operator is keyof typeof LogicalOperators { + return Object.keys(this.operators).includes(operator); + } +} diff --git a/packages/instrumenter/src/mutators/mutator-options.ts b/packages/instrumenter/src/mutators/mutator-options.ts new file mode 100644 index 0000000000..3d997666dc --- /dev/null +++ b/packages/instrumenter/src/mutators/mutator-options.ts @@ -0,0 +1,3 @@ +export interface MutatorOptions { + excludedMutations: string[]; +} diff --git a/packages/instrumenter/src/mutators/node-mutator.ts b/packages/instrumenter/src/mutators/node-mutator.ts new file mode 100644 index 0000000000..55de675824 --- /dev/null +++ b/packages/instrumenter/src/mutators/node-mutator.ts @@ -0,0 +1,8 @@ +import { NodePath } from '@babel/core'; + +import { NodeMutation } from '../mutant'; + +export interface NodeMutator { + mutate(path: NodePath): NodeMutation[]; + readonly name: string; +} diff --git a/packages/instrumenter/src/mutators/object-literal-mutator.ts b/packages/instrumenter/src/mutators/object-literal-mutator.ts new file mode 100644 index 0000000000..44ba6f0bf2 --- /dev/null +++ b/packages/instrumenter/src/mutators/object-literal-mutator.ts @@ -0,0 +1,14 @@ +import * as types from '@babel/types'; +import { NodePath } from '@babel/core'; + +import { NodeMutation } from '../mutant'; + +import { NodeMutator } from '.'; + +export class ObjectLiteralMutator implements NodeMutator { + public name = 'ObjectLiteral'; + + public mutate(path: NodePath): NodeMutation[] { + return path.isObjectExpression() && path.node.properties.length > 0 ? [{ original: path.node, replacement: types.objectExpression([]) }] : []; + } +} diff --git a/packages/instrumenter/src/mutators/string-literal-mutator.ts b/packages/instrumenter/src/mutators/string-literal-mutator.ts new file mode 100644 index 0000000000..eed6d19cb3 --- /dev/null +++ b/packages/instrumenter/src/mutators/string-literal-mutator.ts @@ -0,0 +1,46 @@ +import { types, NodePath } from '@babel/core'; + +import { NodeMutation } from '../mutant'; + +import { NodeMutator } from './node-mutator'; + +export class StringLiteralMutator implements NodeMutator { + public name = 'StringLiteral'; + + public mutate(path: NodePath): NodeMutation[] { + if (path.isTemplateLiteral()) { + const replacement = path.node.quasis.length === 1 && path.node.quasis[0].value.raw.length === 0 ? 'Stryker was here!' : ''; + return [ + { + original: path.node, + replacement: types.templateLiteral([types.templateElement({ raw: replacement })], []), + }, + ]; + } + if (path.isStringLiteral() && this.isValidParent(path)) { + return [ + { + original: path.node, + replacement: types.stringLiteral(path.node.value.length === 0 ? 'Stryker was here!' : ''), + }, + ]; + } + + return []; + } + + private isValidParent(child: NodePath): boolean { + const parent = child.parent; + return !( + types.isImportDeclaration(parent) || + types.isExportDeclaration(parent) || + types.isModuleDeclaration(parent) || + types.isTSExternalModuleReference(parent) || + types.isJSXAttribute(parent) || + types.isExpressionStatement(parent) || + types.isTSLiteralType(parent) || + (types.isObjectProperty(parent) && parent.key === child.node) || + (types.isCallExpression(parent) && types.isIdentifier(parent.callee, { name: 'require' })) + ); + } +} diff --git a/packages/instrumenter/src/mutators/unary-operator-mutator.ts b/packages/instrumenter/src/mutators/unary-operator-mutator.ts new file mode 100644 index 0000000000..18e3079375 --- /dev/null +++ b/packages/instrumenter/src/mutators/unary-operator-mutator.ts @@ -0,0 +1,39 @@ +import * as types from '@babel/types'; +import { NodePath } from '@babel/core'; + +import { NodeMutation } from '../mutant'; + +import { NodeMutator } from '.'; + +enum UnaryOperators { + '+' = '-', + '-' = '+', + '~' = '', +} + +export class UnaryOperatorMutator implements NodeMutator { + public name = 'UnaryOperator'; + + private readonly operators = UnaryOperators; + + public mutate(path: NodePath): NodeMutation[] { + if (path.isUnaryExpression() && this.isSupported(path.node.operator) && path.node.prefix) { + const mutatedOperators = this.operators[path.node.operator]; + const replacement = + mutatedOperators.length > 0 ? types.unaryExpression(mutatedOperators as any, path.node.argument) : types.cloneNode(path.node.argument, false); + + return [ + { + original: path.node, + replacement, + }, + ]; + } + + return []; + } + + private isSupported(operator: string): operator is keyof typeof UnaryOperators { + return Object.keys(this.operators).includes(operator); + } +} diff --git a/packages/instrumenter/src/mutators/update-operator-mutator.ts b/packages/instrumenter/src/mutators/update-operator-mutator.ts new file mode 100644 index 0000000000..e74c1fb89e --- /dev/null +++ b/packages/instrumenter/src/mutators/update-operator-mutator.ts @@ -0,0 +1,28 @@ +import * as types from '@babel/types'; +import { NodePath } from '@babel/core'; + +import { NodeMutation } from '../mutant'; + +import { NodeMutator } from '.'; + +enum UpdateOperators { + '++' = '--', + '--' = '++', +} + +export class UpdateOperatorMutator implements NodeMutator { + public name = 'UpdateOperator'; + + private readonly operators = UpdateOperators; + + public mutate(path: NodePath): NodeMutation[] { + return path.isUpdateExpression() + ? [ + { + original: path.node, + replacement: types.updateExpression(this.operators[path.node.operator], path.node.argument, path.node.prefix), + }, + ] + : []; + } +} diff --git a/packages/instrumenter/src/parsers/html-parser.ts b/packages/instrumenter/src/parsers/html-parser.ts new file mode 100644 index 0000000000..b2d21ba0e0 --- /dev/null +++ b/packages/instrumenter/src/parsers/html-parser.ts @@ -0,0 +1,101 @@ +import type { Element } from 'angular-html-parser/lib/compiler/src/ml_parser/ast'; +import type { ParseLocation } from 'angular-html-parser/lib/compiler/src/parse_util'; + +import { offsetLocations } from '../util/syntax-helpers'; +import { HtmlAst, AstFormat, HtmlRootNode, TSAst, JSAst, ScriptFormat, AstByFormat } from '../syntax'; + +import { ParserContext } from './parser-context'; +import { ParseError } from './parse-error'; + +const TS_SCRIPT_TYPES = Object.freeze(['ts', 'text/typescript', 'typescript']); +const JS_SCRIPT_TYPES = Object.freeze(['js', 'text/javascript', 'javascript']); + +/* +The parser implementation in this file is heavily based on prettier's html parser +https://github.com/prettier/prettier/blob/5a7162d0636a82c5862b9101b845af40918d22d1/src/language-html/parser-html.js +*/ + +export async function parse(text: string, originFileName: string, context: ParserContext): Promise { + const root = await ngHtmlParser(text, originFileName, context); + + return { + originFileName, + rawContent: text, + format: AstFormat.Html, + root, + }; +} + +async function ngHtmlParser(text: string, fileName: string, parserContext: ParserContext): Promise { + const { parse } = await import('angular-html-parser'); + const { RecursiveVisitor, visitAll } = await import('angular-html-parser/lib/compiler/src/ml_parser/ast'); + + const { rootNodes, errors } = parse(text, { + canSelfClose: true, + allowHtmComponentClosingTags: true, + isTagNameCaseSensitive: true, + }); + + if (errors.length !== 0) { + throw new ParseError(errors[0].msg, fileName, toSourceLocation(errors[0].span.start)); + } + const scriptsAsPromised: Array> = []; + visitAll( + new (class extends RecursiveVisitor { + public visitElement(el: Element, context: unknown): void { + const scriptFormat = getScriptType(el); + if (scriptFormat) { + scriptsAsPromised.push(parseScript(el, scriptFormat)); + } + super.visitElement(el, context); + } + })(), + rootNodes + ); + const scripts = await Promise.all(scriptsAsPromised); + const root: HtmlRootNode = { + scripts, + }; + + return root; + + async function parseScript(el: Element, scriptFormat: T): Promise { + const content = text.substring(el.startSourceSpan!.end.offset, el.endSourceSpan!.start.offset); + const ast = await parserContext.parse(content, fileName, scriptFormat); + if (ast) { + const offset = el.startSourceSpan!.end; + offsetLocations(ast.root, { + position: offset.offset, + column: offset.col, + line: offset.line + 1, // need to add 1, since ngHtmlParser lines start with 0 + }); + } + return ast; + } +} + +function toSourceLocation({ line, col }: ParseLocation): { line: number; column: number } { + // Offset line with 1, since ngHtmlParser is 0-based + return { line: line + 1, column: col }; +} + +function getScriptType(element: Element): ScriptFormat | undefined { + if (element.name === 'script') { + const containsSrc = element.attrs.some((attr) => attr.name === 'src'); + if (!containsSrc) { + const type = element.attrs.find((attr) => attr.name === 'type') ?? element.attrs.find((attr) => attr.name === 'lang'); + if (type) { + const typeToLower = type.value.toLowerCase(); + if (TS_SCRIPT_TYPES.includes(typeToLower)) { + return AstFormat.TS; + } + if (JS_SCRIPT_TYPES.includes(typeToLower)) { + return AstFormat.JS; + } + } else { + return AstFormat.JS; + } + } + } + return undefined; +} diff --git a/packages/instrumenter/src/parsers/index.ts b/packages/instrumenter/src/parsers/index.ts new file mode 100644 index 0000000000..bd9f1dc8fd --- /dev/null +++ b/packages/instrumenter/src/parsers/index.ts @@ -0,0 +1,48 @@ +import path from 'path'; + +import { AstFormat, AstByFormat } from '../syntax'; + +import { createParser as createJSParser } from './js-parser'; +import { parse as tsParse } from './ts-parser'; +import { parse as htmlParse } from './html-parser'; +import { ParserOptions } from './parser-options'; + +export { ParserOptions }; + +export function createParser(parserOptions: ParserOptions) { + const jsParse = createJSParser(parserOptions); + return function parse(code: string, fileName: string, formatOverride?: T): Promise { + const format = getFormat(fileName, formatOverride); + switch (format) { + case AstFormat.JS: + return jsParse(code, fileName) as Promise; + case AstFormat.TS: + return tsParse(code, fileName) as Promise; + case AstFormat.Html: + return htmlParse(code, fileName, { parse }) as Promise; + } + }; +} + +export function getFormat(fileName: string, override?: AstFormat): AstFormat { + if (override) { + return override; + } else { + const ext = path.extname(fileName).toLowerCase(); + switch (ext) { + case '.js': + case '.mjs': + case '.cjs': + return AstFormat.JS; + case '.ts': + case '.tsx': + return AstFormat.TS; + case '.vue': + case '.html': + case '.htm': + return AstFormat.Html; + default: + throw new Error(`Unable to parse ${fileName}. No parser registered for ${ext}!`); + } + } +} diff --git a/packages/instrumenter/src/parsers/js-parser.ts b/packages/instrumenter/src/parsers/js-parser.ts new file mode 100644 index 0000000000..49095d8bf2 --- /dev/null +++ b/packages/instrumenter/src/parsers/js-parser.ts @@ -0,0 +1,53 @@ +import { ParserPlugin } from '@babel/parser'; +import { parseAsync, types } from '@babel/core'; + +import { AstFormat, JSAst } from '../syntax'; + +import { ParserOptions } from './parser-options'; + +const defaultPlugins: ParserPlugin[] = [ + 'doExpressions', + 'objectRestSpread', + 'classProperties', + 'exportDefaultFrom', + 'exportNamespaceFrom', + 'asyncGenerators', + 'functionBind', + 'functionSent', + 'dynamicImport', + 'numericSeparator', + 'importMeta', + 'optionalCatchBinding', + 'optionalChaining', + 'classPrivateProperties', + ['pipelineOperator', { proposal: 'minimal' }], + 'nullishCoalescingOperator', + 'bigInt', + 'throwExpressions', + 'logicalAssignment', + 'classPrivateMethods', + 'v8intrinsic', + 'partialApplication', + ['decorators', { decoratorsBeforeExport: false }], +]; + +export function createParser({ plugins: pluginsOverride }: ParserOptions) { + return async function parse(text: string, fileName: string): Promise { + const ast = await parseAsync(text, { + parserOpts: { + plugins: [...(pluginsOverride ?? defaultPlugins)] as ParserPlugin[], + }, + filename: fileName, + sourceType: 'module', + }); + if (types.isProgram(ast)) { + throw new Error(`Expected ${fileName} to contain a babel.types.file, but was a program`); + } + return { + originFileName: fileName, + rawContent: text, + format: AstFormat.JS, + root: ast!, + }; + }; +} diff --git a/packages/instrumenter/src/parsers/parse-error.ts b/packages/instrumenter/src/parsers/parse-error.ts new file mode 100644 index 0000000000..b09b97b0ce --- /dev/null +++ b/packages/instrumenter/src/parsers/parse-error.ts @@ -0,0 +1,7 @@ +import { types } from '@babel/core'; + +export class ParseError extends Error { + constructor(message: string, fileName: string, location: types.SourceLocation['start']) { + super(`Parse error in ${fileName} (${location.line}:${location.column}) ${message}`); + } +} diff --git a/packages/instrumenter/src/parsers/parser-context.ts b/packages/instrumenter/src/parsers/parser-context.ts new file mode 100644 index 0000000000..f4f156ecbb --- /dev/null +++ b/packages/instrumenter/src/parsers/parser-context.ts @@ -0,0 +1,7 @@ +import { Ast, AstFormat, AstByFormat } from '../syntax'; + +export interface ParserContext { + parse: (code: string, fileName: string, formatOverride?: T) => Promise; +} + +export type Parser = (text: string, fileName: string, context: ParserContext) => Promise; diff --git a/packages/instrumenter/src/parsers/parser-options.ts b/packages/instrumenter/src/parsers/parser-options.ts new file mode 100644 index 0000000000..7944a12469 --- /dev/null +++ b/packages/instrumenter/src/parsers/parser-options.ts @@ -0,0 +1,3 @@ +export interface ParserOptions { + plugins: Array | null; +} diff --git a/packages/instrumenter/src/parsers/ts-parser.ts b/packages/instrumenter/src/parsers/ts-parser.ts new file mode 100644 index 0000000000..e8ef350bc8 --- /dev/null +++ b/packages/instrumenter/src/parsers/ts-parser.ts @@ -0,0 +1,32 @@ +import { types } from '@babel/core'; +import { parseAsync } from '@babel/core'; + +import { AstFormat, TSAst } from '../syntax'; + +/** + * See https://babeljs.io/docs/en/babel-preset-typescript + * @param text The text to parse + * @param fileName The name of the file + */ +export async function parse(text: string, fileName: string): Promise { + const isTSX = fileName.endsWith('x'); + const ast = await parseAsync(text, { + filename: fileName, + parserOpts: { + ranges: true, + }, + configFile: false, + babelrc: false, + presets: [[require.resolve('@babel/preset-typescript'), { isTSX, allExtensions: true }]], + plugins: [[require.resolve('@babel/plugin-proposal-decorators'), { legacy: true }]], + }); + if (types.isProgram(ast)) { + throw new Error(`Expected ${fileName} to contain a babel.types.file, but was a program`); + } + return { + originFileName: fileName, + rawContent: text, + format: AstFormat.TS, + root: ast!, + }; +} diff --git a/packages/instrumenter/src/printers/html-printer.ts b/packages/instrumenter/src/printers/html-printer.ts new file mode 100644 index 0000000000..58230c97cc --- /dev/null +++ b/packages/instrumenter/src/printers/html-printer.ts @@ -0,0 +1,18 @@ +import { HtmlAst } from '../syntax'; + +import { Printer } from '.'; + +export const print: Printer = (ast, context) => { + const sortedScripts = [...ast.root.scripts].sort((a, b) => a.root.start! - b.root.start!); + let currentIndex = 0; + let html = ''; + for (const script of sortedScripts) { + html += ast.rawContent.substring(currentIndex, script.root.start!); + html += '\n'; + html += context.print(script, context); + html += '\n'; + currentIndex = script.root.end!; + } + html += ast.rawContent.substr(currentIndex); + return html; +}; diff --git a/packages/instrumenter/src/printers/index.ts b/packages/instrumenter/src/printers/index.ts new file mode 100644 index 0000000000..254dd08d7b --- /dev/null +++ b/packages/instrumenter/src/printers/index.ts @@ -0,0 +1,25 @@ +import { Ast, AstFormat } from '../syntax'; + +import { print as htmlPrint } from './html-printer'; +import { print as jsPrint } from './js-printer'; +import { print as tsPrint } from './ts-printer'; + +export type Printer = (file: T, context: PrinterContext) => string; + +export interface PrinterContext { + print: Printer; +} + +export function print(file: Ast): string { + const context: PrinterContext = { + print, + }; + switch (file.format) { + case AstFormat.JS: + return jsPrint(file, context); + case AstFormat.TS: + return tsPrint(file, context); + case AstFormat.Html: + return htmlPrint(file, context); + } +} diff --git a/packages/instrumenter/src/printers/js-printer.ts b/packages/instrumenter/src/printers/js-printer.ts new file mode 100644 index 0000000000..b1c99a3239 --- /dev/null +++ b/packages/instrumenter/src/printers/js-printer.ts @@ -0,0 +1,9 @@ +import generate from '@babel/generator'; + +import { JSAst } from '../syntax'; + +import { Printer } from '.'; + +export const print: Printer = (file) => { + return generate(file.root, { sourceMaps: false }).code; +}; diff --git a/packages/instrumenter/src/printers/ts-printer.ts b/packages/instrumenter/src/printers/ts-printer.ts new file mode 100644 index 0000000000..9399c63f21 --- /dev/null +++ b/packages/instrumenter/src/printers/ts-printer.ts @@ -0,0 +1,12 @@ +import generate from '@babel/generator'; + +import { TSAst } from '../syntax'; + +import { Printer } from '.'; + +export const print: Printer = (file) => { + return generate(file.root, { + decoratorsBeforeExport: true, + sourceMaps: false, + }).code; +}; diff --git a/packages/instrumenter/src/syntax/index.ts b/packages/instrumenter/src/syntax/index.ts new file mode 100644 index 0000000000..3517411975 --- /dev/null +++ b/packages/instrumenter/src/syntax/index.ts @@ -0,0 +1,56 @@ +import type { types as babelTypes } from '@babel/core'; + +export enum AstFormat { + Html = 'html', + JS = 'js', + TS = 'ts', +} + +export type ScriptFormat = AstFormat.JS | AstFormat.TS; + +export interface AstByFormat { + [AstFormat.Html]: HtmlAst; + [AstFormat.JS]: JSAst; + [AstFormat.TS]: TSAst; +} + +export interface BaseAst { + originFileName: string; + rawContent: string; + root: Ast['root']; +} + +/** + * Represents an Html AST. + */ +export interface HtmlAst extends BaseAst { + format: AstFormat.Html; + root: HtmlRootNode; +} + +/** + * Represents a TS AST + */ +export interface JSAst extends BaseAst { + format: AstFormat.JS; + root: babelTypes.File; +} + +/** + * Represents a TS AST + */ +export interface TSAst extends BaseAst { + format: AstFormat.TS; + root: babelTypes.File; +} + +/** + * Represents the root node of an HTML AST + * We've taken a shortcut here, instead of representing the entire AST, we're only representing the script tags. + * We might need to expand this in the future if we would ever want to support mutating the actual HTML (rather than only the JS/TS) + */ +export interface HtmlRootNode { + scripts: Array; +} + +export type Ast = HtmlAst | JSAst | TSAst; diff --git a/packages/instrumenter/src/transformers/babel-transformer.ts b/packages/instrumenter/src/transformers/babel-transformer.ts new file mode 100644 index 0000000000..7a2fe002c4 --- /dev/null +++ b/packages/instrumenter/src/transformers/babel-transformer.ts @@ -0,0 +1,39 @@ +import { traverse } from '@babel/core'; + +// @ts-expect-error The babel types don't define "File" yet +import { File } from '@babel/core'; + +import { placeMutants } from '../mutant-placers'; +import { mutate } from '../mutators'; +import { instrumentationBabelHeader, isTypeNode, isImportDeclaration } from '../util/syntax-helpers'; +import { AstFormat } from '../syntax'; + +import { AstTransformer } from '.'; + +export const transformBabel: AstTransformer = ({ root, originFileName, rawContent }, mutantCollector, { options }) => { + // Wrap the AST in a `new File`, so `nodePath.buildCodeFrameError` works + // https://github.com/babel/babel/issues/11889 + const file = new File({ filename: originFileName }, { code: rawContent, ast: root }); + traverse(file.ast, { + enter(path) { + if (isTypeNode(path) || isImportDeclaration(path) || path.isDecorator()) { + // Don't mutate type declarations or import statements + path.skip(); + } else { + mutate(path, options).forEach((mutant) => { + mutantCollector.add(originFileName, mutant); + }); + } + }, + exit(path) { + const mutants = mutantCollector.findUnplacedMutantsInScope(path.node); + if (placeMutants(path, mutants, originFileName)) { + path.skip(); + mutantCollector.markMutantsAsPlaced(mutants); + } + }, + }); + if (mutantCollector.hasPlacedMutants(originFileName)) { + root.program.body.unshift(...instrumentationBabelHeader); + } +}; diff --git a/packages/instrumenter/src/transformers/html-transformer.ts b/packages/instrumenter/src/transformers/html-transformer.ts new file mode 100644 index 0000000000..02d8c3a3df --- /dev/null +++ b/packages/instrumenter/src/transformers/html-transformer.ts @@ -0,0 +1,9 @@ +import { AstFormat } from '../syntax'; + +import { AstTransformer } from '.'; + +export const transformHtml: AstTransformer = ({ root }, mutantCollector, context) => { + root.scripts.forEach((ast) => { + context.transform(ast, mutantCollector, context); + }); +}; diff --git a/packages/instrumenter/src/transformers/index.ts b/packages/instrumenter/src/transformers/index.ts new file mode 100644 index 0000000000..535212327a --- /dev/null +++ b/packages/instrumenter/src/transformers/index.ts @@ -0,0 +1,5 @@ +import { MutantCollector } from './mutant-collector'; +import { TransformerOptions } from './transformer-options'; + +export { MutantCollector, TransformerOptions }; +export * from './transformer'; diff --git a/packages/instrumenter/src/transformers/mutant-collector.ts b/packages/instrumenter/src/transformers/mutant-collector.ts new file mode 100644 index 0000000000..ffb4f530ef --- /dev/null +++ b/packages/instrumenter/src/transformers/mutant-collector.ts @@ -0,0 +1,44 @@ +import { types } from '@babel/core'; + +import { Mutant, NamedNodeMutation } from '../mutant'; + +export class MutantCollector { + private readonly _mutants: Mutant[] = []; + private unplacedMutants: Mutant[] = []; + + public get mutants(): readonly Mutant[] { + return this._mutants; + } + + /** + * Adds a mutant to the internal mutant list. + * @param fileName file name that houses the mutant + * @param mutationSpecs the named node mutation to be added + * @returns The mutant (for testability) + */ + public add(fileName: string, mutationSpecs: NamedNodeMutation): Mutant { + mutationSpecs.replacement.end = mutationSpecs.original.end; + mutationSpecs.replacement.start = mutationSpecs.original.start; + mutationSpecs.replacement.loc = mutationSpecs.original.loc; + const mutant = new Mutant(this._mutants.length, fileName, mutationSpecs); + this._mutants.push(mutant); + if (mutant.ignoreReason === undefined) { + // Only place mutants that are not ignored + this.unplacedMutants.push(mutant); + } + return mutant; + } + + public findUnplacedMutantsInScope(scope: Pick): Mutant[] { + return this.unplacedMutants.filter((mutant) => scope.start! <= mutant.replacement.start! && scope.end! >= mutant.replacement.end!); + } + + public markMutantsAsPlaced(mutants: Mutant[]): void { + this.unplacedMutants = this.unplacedMutants.filter((unplaced) => !mutants.includes(unplaced)); + } + + public hasPlacedMutants(fileName: string) { + const unplacedMutants = this.unplacedMutants.filter((mutant) => mutant.fileName === fileName); + return this.mutants.some((mutant) => !unplacedMutants.includes(mutant) && mutant.fileName === fileName); + } +} diff --git a/packages/instrumenter/src/transformers/transformer-options.ts b/packages/instrumenter/src/transformers/transformer-options.ts new file mode 100644 index 0000000000..2df8054e17 --- /dev/null +++ b/packages/instrumenter/src/transformers/transformer-options.ts @@ -0,0 +1,3 @@ +import { MutatorOptions } from '../mutators'; + +export interface TransformerOptions extends MutatorOptions {} diff --git a/packages/instrumenter/src/transformers/transformer.ts b/packages/instrumenter/src/transformers/transformer.ts new file mode 100644 index 0000000000..d161bed12e --- /dev/null +++ b/packages/instrumenter/src/transformers/transformer.ts @@ -0,0 +1,38 @@ +import { I } from '@stryker-mutator/util'; + +import { Ast, AstByFormat, AstFormat } from '../syntax'; + +import { TransformerOptions } from './transformer-options'; +import { transformBabel } from './babel-transformer'; +import { transformHtml } from './html-transformer'; +import { MutantCollector } from './mutant-collector'; + +/** + * Transform the AST by generating mutants and placing them in the AST. + * Supports all AST formats supported by Stryker. + * @param ast The Abstract Syntax Tree + * @param mutantCollector the mutant collector that will be used to register and administer mutants + * @param transformerContext the options used during transforming + */ +export function transform(ast: Ast, mutantCollector: I, transformerContext: Pick): void { + const context: TransformerContext = { + transform, + options: transformerContext.options, + }; + switch (ast.format) { + case AstFormat.Html: + transformHtml(ast, mutantCollector, context); + break; + case AstFormat.JS: + case AstFormat.TS: + transformBabel(ast, mutantCollector, context); + break; + } +} + +export type AstTransformer = (ast: AstByFormat[T], mutantCollector: I, context: TransformerContext) => void; + +export interface TransformerContext { + transform: AstTransformer; + options: TransformerOptions; +} diff --git a/packages/instrumenter/src/tsconfig.json b/packages/instrumenter/src/tsconfig.json new file mode 100644 index 0000000000..4022aebfe2 --- /dev/null +++ b/packages/instrumenter/src/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "../../../tsconfig.settings.json", + "compilerOptions": { + "outDir": "../dist/src", + "rootDir": ".", + "esModuleInterop": true, + "resolveJsonModule": true, + "types": [ + "node" + ] + }, + "references": [ + { + "path": "../../api/tsconfig.src.json" + }, + { + "path": "../../util/tsconfig.src.json" + } + ] +} diff --git a/packages/instrumenter/src/util/binary-operator.ts b/packages/instrumenter/src/util/binary-operator.ts new file mode 100644 index 0000000000..18a5e9ad18 --- /dev/null +++ b/packages/instrumenter/src/util/binary-operator.ts @@ -0,0 +1,23 @@ +export type BinaryOperator = + | '+' + | '-' + | '/' + | '%' + | '*' + | '**' + | '&' + | '|' + | '>>' + | '>>>' + | '<<' + | '^' + | '==' + | '===' + | '!=' + | '!==' + | 'in' + | 'instanceof' + | '>' + | '<' + | '>=' + | '<='; diff --git a/packages/instrumenter/src/util/index.ts b/packages/instrumenter/src/util/index.ts new file mode 100644 index 0000000000..ab95bcd321 --- /dev/null +++ b/packages/instrumenter/src/util/index.ts @@ -0,0 +1,2 @@ +export * from './syntax-helpers'; +export * from './binary-operator'; diff --git a/packages/instrumenter/src/util/syntax-helpers.ts b/packages/instrumenter/src/util/syntax-helpers.ts new file mode 100644 index 0000000000..cc62c472fc --- /dev/null +++ b/packages/instrumenter/src/util/syntax-helpers.ts @@ -0,0 +1,200 @@ +import { INSTRUMENTER_CONSTANTS as ID } from '@stryker-mutator/api/core'; +import { types, NodePath } from '@babel/core'; +import traverse from '@babel/traverse'; +import { parse } from '@babel/parser'; + +import { Mutant } from '../mutant'; + +export { ID }; + +const STRYKER_NAMESPACE_HELPER = 'stryNS_9fa48'; +const COVER_MUTANT_HELPER = 'stryCov_9fa48'; +const IS_MUTANT_ACTIVE_HELPER = 'stryMutAct_9fa48'; + +/** + * Returns syntax for the header if JS/TS files + */ +export const instrumentationBabelHeader = parse(`function ${STRYKER_NAMESPACE_HELPER}(){ + var g = new Function("return this")(); + var ns = g.${ID.NAMESPACE} || (g.${ID.NAMESPACE} = {}); + if (ns.${ID.ACTIVE_MUTANT} === undefined && g.process && g.process.env && g.process.env.${ID.ACTIVE_MUTANT_ENV_VARIABLE}) { + ns.${ID.ACTIVE_MUTANT} = Number(g.process.env.${ID.ACTIVE_MUTANT_ENV_VARIABLE}); + } + function retrieveNS(){ + return ns; + } + ${STRYKER_NAMESPACE_HELPER} = retrieveNS; + return retrieveNS(); +} +${STRYKER_NAMESPACE_HELPER}(); + +function ${COVER_MUTANT_HELPER}() { + var ns = ${STRYKER_NAMESPACE_HELPER}(); + var cov = ns.${ID.MUTATION_COVERAGE_OBJECT} || (ns.${ID.MUTATION_COVERAGE_OBJECT} = { static: {}, perTest: {} }); + function cover() { + var c = cov.static; + if (ns.${ID.CURRENT_TEST_ID}) { + c = cov.perTest[ns.${ID.CURRENT_TEST_ID}] = cov.perTest[ns.${ID.CURRENT_TEST_ID}] || {}; + } + var a = arguments; + for(var i=0; i < a.length; i++){ + c[a[i]] = (c[a[i]] || 0) + 1; + } + } + ${COVER_MUTANT_HELPER} = cover; + cover.apply(null, arguments); +} +function ${IS_MUTANT_ACTIVE_HELPER}(id) { + var ns = ${STRYKER_NAMESPACE_HELPER}(); + function isActive(id) { + return ns.${ID.ACTIVE_MUTANT} === id; + } + ${IS_MUTANT_ACTIVE_HELPER} = isActive; + return isActive(id); +}`).program.body; + +/** + * returns syntax for `global.activeMutant === $mutantId` + * @param mutantId The id of the mutant to switch + */ +export function mutantTestExpression(mutantId: number): types.CallExpression { + return types.callExpression(types.identifier(IS_MUTANT_ACTIVE_HELPER), [types.numericLiteral(mutantId)]); +} + +interface Position { + line: number; + column: number; +} + +function eqLocation(a: types.SourceLocation, b: types.SourceLocation): boolean { + function eqPosition(a: Position, b: Position): boolean { + return a.column === b.column && a.line === b.line; + } + return eqPosition(a.start, b.start) && eqPosition(a.end, b.end); +} + +export function eqNode(a: T, b: types.Node): b is T { + return a.type === b.type && !!a.loc && !!b.loc && eqLocation(a.loc, b.loc); +} + +export function offsetLocations(file: types.File, { position, line, column }: { position: number; line: number; column: number }): void { + const offsetNode = (node: types.Node): void => { + node.start! += position; + node.end! += position; + // we need to subtract 1, as lines always start at 1 + node.loc!.start.line += line - 1; + node.loc!.end.line += line - 1; + if (node.loc!.start.line === line) { + node.loc!.start.column += column; + } + if (node.loc!.end.line === line) { + node.loc!.end.column += column; + } + }; + traverse(file, { + enter(path) { + offsetNode(path.node); + }, + }); + // Don't forget the file itself! + file.start! += position; + file.end! += position; +} + +export function createMutatedAst(contextPath: NodePath, mutant: Mutant): T { + if (eqNode(contextPath.node, mutant.original)) { + return mutant.replacement as T; + } else { + const mutatedAst = types.cloneNode(contextPath.node, /*deep*/ true); + let isAstMutated = false; + + traverse( + mutatedAst, + { + noScope: true, + enter(path) { + if (eqNode(path.node, mutant.original)) { + path.replaceWith(mutant.replacement); + path.stop(); + isAstMutated = true; + } + }, + }, + contextPath.scope + ); + if (!isAstMutated) { + throw new Error(`Could not apply mutant ${JSON.stringify(mutant.replacement)}.`); + } + return mutatedAst; + } +} + +/** + * Returns a sequence of mutation coverage counters with an optional last expression. + * + * @example (global.__coverMutant__(0, 1), 40 + 2) + * @param mutants The mutant ids for which covering syntax needs to be generated + * @param targetExpression The original expression + */ +export function mutationCoverageSequenceExpression(mutants: Mutant[], targetExpression?: types.Expression): types.Expression { + const sequence: types.Expression[] = [ + types.callExpression( + types.identifier(COVER_MUTANT_HELPER), + mutants.map((mutant) => types.numericLiteral(mutant.id)) + ), + ]; + if (targetExpression) { + sequence.push(targetExpression); + } + return types.sequenceExpression(sequence); +} + +export function isTypeNode(path: NodePath): boolean { + return ( + path.isTypeAnnotation() || + flowTypeAnnotationNodeTypes.includes(path.node.type) || + tsTypeAnnotationNodeTypes.includes(path.node.type) || + isDeclareVariableStatement(path) + ); +} + +/** + * Determines whether or not it is a declare variable statement node. + * @example + * declare const foo: 'foo'; + */ +function isDeclareVariableStatement(path: NodePath): boolean { + return path.isVariableDeclaration() && path.node.declare === true; +} + +const tsTypeAnnotationNodeTypes: ReadonlyArray = Object.freeze([ + 'TSAsExpression', + 'TSInterfaceDeclaration', + 'TSTypeAnnotation', + 'TSTypeAliasDeclaration', + 'TSModuleDeclaration', + 'TSEnumDeclaration', + 'TSDeclareFunction', + 'TSTypeParameterInstantiation', +]); + +const flowTypeAnnotationNodeTypes: ReadonlyArray = Object.freeze([ + 'DeclareClass', + 'DeclareFunction', + 'DeclareInterface', + 'DeclareModule', + 'DeclareModuleExports', + 'DeclareTypeAlias', + 'DeclareOpaqueType', + 'DeclareVariable', + 'DeclareExportDeclaration', + 'DeclareExportAllDeclaration', + 'InterfaceDeclaration', + 'OpaqueType', + 'TypeAlias', + 'InterfaceDeclaration', +]); + +export function isImportDeclaration(path: NodePath): boolean { + return types.isTSImportEqualsDeclaration(path.node) || path.isImportDeclaration(); +} diff --git a/packages/instrumenter/stryker.conf.js b/packages/instrumenter/stryker.conf.js new file mode 100644 index 0000000000..9023e9e712 --- /dev/null +++ b/packages/instrumenter/stryker.conf.js @@ -0,0 +1,8 @@ +const path = require('path'); +const settings = require('../../stryker.parent.conf'); +const moduleName = __dirname.split(path.sep).pop(); +delete settings.mochaOptions.spec; +delete settings.files; +settings.plugins = settings.plugins.map(p => path.resolve(p)); +settings.dashboard.module = moduleName; +module.exports = settings; diff --git a/packages/instrumenter/test/helpers/expect-mutation.ts b/packages/instrumenter/test/helpers/expect-mutation.ts new file mode 100644 index 0000000000..7fef942152 --- /dev/null +++ b/packages/instrumenter/test/helpers/expect-mutation.ts @@ -0,0 +1,61 @@ +import { traverse } from '@babel/core'; +import { parse, ParserPlugin } from '@babel/parser'; +import generate from '@babel/generator'; +import { expect } from 'chai'; + +import { NodeMutator } from '../../src/mutators/node-mutator'; +import { NodeMutation } from '../../src/mutant'; + +const plugins = [ + 'doExpressions', + 'objectRestSpread', + 'classProperties', + 'exportDefaultFrom', + 'exportNamespaceFrom', + 'asyncGenerators', + 'functionBind', + 'functionSent', + 'dynamicImport', + 'numericSeparator', + 'importMeta', + 'optionalCatchBinding', + 'optionalChaining', + 'classPrivateProperties', + ['pipelineOperator', { proposal: 'minimal' }], + 'nullishCoalescingOperator', + 'bigInt', + 'throwExpressions', + 'logicalAssignment', + 'classPrivateMethods', + 'v8intrinsic', + 'partialApplication', + ['decorators', { decoratorsBeforeExport: false }], + 'jsx', + 'typescript', +] as ParserPlugin[]; + +export function expectJSMutation(sut: NodeMutator, originalCode: string, ...expectedReplacements: string[]) { + const sourceFileName = 'source.js'; + const ast = parse(originalCode, { + sourceFilename: sourceFileName, + plugins, + sourceType: 'module', + }); + const mutants: NodeMutation[] = []; + traverse(ast, { + enter(nodePath) { + mutants.push(...sut.mutate(nodePath)); + }, + }); + expect(mutants).lengthOf(expectedReplacements.length); + const actualReplacements = mutants.map((mutant) => jsMutantToString(mutant, originalCode)); + expectedReplacements.forEach((expected) => expect(actualReplacements, `was: ${actualReplacements.join(',')}`).to.include(expected)); +} + +function jsMutantToString(mutant: NodeMutation, originalCode: string): string { + const mutatedCode = generate(mutant.replacement).code; + const beforeMutatedCode = originalCode.substring(0, mutant.original.start || 0); + const afterMutatedCode = originalCode.substring(mutant.original.end || 0); + + return `${beforeMutatedCode}${mutatedCode}${afterMutatedCode}`; +} diff --git a/packages/instrumenter/test/helpers/factories.ts b/packages/instrumenter/test/helpers/factories.ts new file mode 100644 index 0000000000..4e4f2c8ae7 --- /dev/null +++ b/packages/instrumenter/test/helpers/factories.ts @@ -0,0 +1,83 @@ +import { types } from '@babel/core'; + +import { JSAst, AstFormat, HtmlAst, TSAst } from '../../src/syntax'; +import { Mutant, NamedNodeMutation } from '../../src/mutant'; +import { ParserOptions } from '../../src/parsers'; +import { InstrumenterOptions } from '../../src'; +import { TransformerOptions } from '../../src/transformers'; + +import { parseTS, parseJS, findNodePath } from './syntax-test-helpers'; + +export function createParserOptions(overrides?: Partial): ParserOptions { + return { + plugins: null, + ...overrides, + }; +} + +export function createTransformerOptions(overrides?: Partial): TransformerOptions { + return { + excludedMutations: [], + ...overrides, + }; +} + +export function createInstrumenterOptions(overrides?: Partial): InstrumenterOptions { + return { + ...createParserOptions(), + ...createTransformerOptions(), + ...overrides, + }; +} + +export function createHtmlAst(overrides?: Partial): HtmlAst { + return { + format: AstFormat.Html, + originFileName: 'example.html', + rawContent: '', + root: { + scripts: [], + }, + ...overrides, + }; +} + +export function createJSAst(overrides?: Partial): JSAst { + const rawContent = overrides?.rawContent ?? 'foo.bar(41, 1)'; + return { + format: AstFormat.JS, + originFileName: 'example.js', + rawContent, + root: parseJS(rawContent), + ...overrides, + }; +} + +export function createTSAst(overrides?: Partial): TSAst { + const rawContent = overrides?.rawContent ?? 'foo.bar(41, 1)'; + const originFileName = overrides?.originFileName ?? 'example.ts'; + return { + format: AstFormat.TS, + originFileName, + rawContent, + root: parseTS(rawContent, originFileName), + ...overrides, + }; +} + +export function createMutant(overrides?: Partial): Mutant { + return new Mutant(overrides?.id ?? 1, overrides?.fileName ?? 'example.js', { + mutatorName: overrides?.mutatorName ?? 'fooMutator', + original: overrides?.original ?? types.identifier('foo'), + replacement: overrides?.replacement ?? types.identifier('bar'), + }); +} + +export function createNamedNodeMutation(overrides?: Partial): NamedNodeMutation { + return { + mutatorName: 'fooMutator', + original: findNodePath(parseJS('foo'), (t) => t.isIdentifier()).node, + replacement: findNodePath(parseJS('bar'), (t) => t.isIdentifier()).node, + ...overrides, + }; +} diff --git a/packages/instrumenter/test/helpers/stubs.ts b/packages/instrumenter/test/helpers/stubs.ts new file mode 100644 index 0000000000..35bf3de289 --- /dev/null +++ b/packages/instrumenter/test/helpers/stubs.ts @@ -0,0 +1,26 @@ +import sinon from 'sinon'; + +import { ParserContext } from '../../src/parsers/parser-context'; +import { PrinterContext } from '../../src/printers'; +import { TransformerContext } from '../../src/transformers'; + +import { createTransformerOptions } from './factories'; + +export function parserContextStub(): sinon.SinonStubbedInstance { + return { + parse: sinon.stub(), + }; +} + +export function printerContextStub(): sinon.SinonStubbedInstance { + return { + print: sinon.stub(), + }; +} + +export function transformerContextStub(): sinon.SinonStubbedInstance { + return { + transform: sinon.stub(), + options: createTransformerOptions(), + }; +} diff --git a/packages/instrumenter/test/helpers/syntax-test-helpers.ts b/packages/instrumenter/test/helpers/syntax-test-helpers.ts new file mode 100644 index 0000000000..70cee8fb82 --- /dev/null +++ b/packages/instrumenter/test/helpers/syntax-test-helpers.ts @@ -0,0 +1,69 @@ +import { types, traverse, NodePath, parseSync } from '@babel/core'; +import { expect } from 'chai'; +import generate from '@babel/generator'; + +// @ts-expect-error The babel types don't define "File" yet +import { File } from '@babel/core'; + +export type AstExpectation = (nodePath: NodePath) => boolean; + +/** + * This helper function loosely asserts an AST. During unit testing, we're not looking for exact AST comparison, + * that's more something for integration tests. + * @param actual the actual parsed file + * @param assertion the assertion which needs to deliver true for at least one node in the AST + */ +export function expectAst(actual: types.File, assertion: AstExpectation): void { + let found = false; + traverse(actual, { + enter(nodePath) { + if (assertion(nodePath)) { + found = true; + nodePath.stop(); + } + }, + }); + expect(found, `Expected to find ${assertion.toString()}`).true; +} + +export function parseJS(code: string) { + // Wrap the AST in a `new File`, so `nodePath.buildCodeFrameError` works + // https://github.com/babel/babel/issues/11889 + const { ast } = new File({ filename: 'foo.js' }, { code, ast: parseSync(code) }); + return ast as types.File; +} + +export function parseTS(code: string, fileName = 'example.ts') { + // Wrap the AST in a `new File`, so `nodePath.buildCodeFrameError` works + // https://github.com/babel/babel/issues/11889 + const { ast } = new File( + { filename: 'foo.js' }, + { + code, + ast: parseSync(code, { + presets: [require.resolve('@babel/preset-typescript')], + filename: fileName, + plugins: [[require.resolve('@babel/plugin-proposal-decorators'), { legacy: true }]], + }), + } + ); + return ast as types.File; +} + +export function findNodePath(ast: types.File, searchQuery: (nodePath: NodePath) => boolean): NodePath { + let theNode: undefined | NodePath; + traverse(ast, { + noScope: true, + enter(path) { + if (searchQuery(path)) { + theNode = (path as unknown) as NodePath; + path.stop(); + } + }, + }); + if (theNode) { + return theNode; + } else { + throw new Error(`Cannot find node ${searchQuery.toString()} in ${generate(ast)}`); + } +} diff --git a/packages/instrumenter/test/integration/disable-type-checks.it.spec.ts b/packages/instrumenter/test/integration/disable-type-checks.it.spec.ts new file mode 100644 index 0000000000..3bb4c19c28 --- /dev/null +++ b/packages/instrumenter/test/integration/disable-type-checks.it.spec.ts @@ -0,0 +1,40 @@ +import path from 'path'; +import { promises as fs } from 'fs'; + +import { expect } from 'chai'; +import chaiJestSnapshot from 'chai-jest-snapshot'; + +import { File } from '@stryker-mutator/api/core'; + +import { disableTypeChecks } from '../../src'; +import { createInstrumenterOptions } from '../helpers/factories'; + +const resolveTestResource = path.resolve.bind( + path, + __dirname, + '..' /* integration */, + '..' /* test */, + '..' /* dist */, + 'testResources', + 'disable-type-checks' +); + +describe(`${disableTypeChecks.name} integration`, () => { + it('should be able disable type checks of a typescript file', async () => { + await arrangeAndActAssert('app.component.ts'); + }); + it('should be able disable type checks of an html file', async () => { + await arrangeAndActAssert('html-sample.html'); + }); + it('should be able disable type checks of a vue file', async () => { + await arrangeAndActAssert('vue-sample.vue'); + }); + + async function arrangeAndActAssert(fileName: string, options = createInstrumenterOptions()) { + const fullFileName = resolveTestResource(fileName); + const file = new File(fullFileName, await fs.readFile(fullFileName)); + const result = await disableTypeChecks(file, options); + chaiJestSnapshot.setFilename(resolveTestResource(`${fileName}.out.snap`)); + expect(result.textContent).matchSnapshot(); + } +}); diff --git a/packages/instrumenter/test/integration/instrumenter.it.spec.ts b/packages/instrumenter/test/integration/instrumenter.it.spec.ts new file mode 100644 index 0000000000..f6a81db93a --- /dev/null +++ b/packages/instrumenter/test/integration/instrumenter.it.spec.ts @@ -0,0 +1,79 @@ +import { promises as fs } from 'fs'; +import path from 'path'; + +import { testInjector } from '@stryker-mutator/test-helpers'; +import { File } from '@stryker-mutator/api/core'; +import { expect } from 'chai'; +import chaiJestSnapshot from 'chai-jest-snapshot'; + +import { Instrumenter } from '../../src'; +import { createInstrumenterOptions } from '../helpers/factories'; + +const resolveTestResource = path.resolve.bind( + path, + __dirname, + '..' /* integration */, + '..' /* test */, + '..' /* dist */, + 'testResources', + 'instrumenter' +); + +describe('instrumenter integration', () => { + let sut: Instrumenter; + beforeEach(() => { + sut = testInjector.injector.injectClass(Instrumenter); + }); + + it('should be able to instrument html', async () => { + await arrangeAndActAssert('html-sample.html'); + }); + it('should be able to instrument a simple js file', async () => { + await arrangeAndActAssert('js-sample.js'); + }); + it('should be able to instrument a simple ts file', async () => { + await arrangeAndActAssert('ts-sample.ts'); + }); + it('should be able to instrument an angular component', async () => { + await arrangeAndActAssert('app.component.ts'); + }); + it('should be able to instrument a lit-html file', async () => { + await arrangeAndActAssert('lit-html-sample.ts'); + }); + it('should be able to instrument a vue sample', async () => { + await arrangeAndActAssert('vue-sample.vue'); + }); + it('should be able to instrument super calls', async () => { + await arrangeAndActAssert('super-call.ts'); + }); + it('should be able to instrument js files with a shebang in them', async () => { + await arrangeAndActAssert('shebang.js'); + }); + it('should not place ignored mutants', async () => { + await arrangeAndActAssert('ignore.js', createInstrumenterOptions({ excludedMutations: ['ArithmeticOperator'] })); + }); + it('should be able to instrument switch case statements (using the switchCaseMutantPlacer)', async () => { + await arrangeAndActAssert('switch-case.js'); + }); + + describe('type declarations', () => { + it('should not produce mutants for TS type definitions', async () => { + await arrangeAndActAssert('type-definitions.ts'); + }); + it('should not produce mutants for flow-types', async () => { + await arrangeAndActAssert('flow-typed.js', createInstrumenterOptions({ plugins: ['flow'] })); + }); + it('should not produce mutants for a TS declaration file', async () => { + await arrangeAndActAssert('ts-declarations.ts'); + }); + }); + + async function arrangeAndActAssert(fileName: string, options = createInstrumenterOptions()) { + const fullFileName = resolveTestResource(fileName); + const file = new File(fullFileName, await fs.readFile(fullFileName)); + const result = await sut.instrument([file], options); + expect(result.files).lengthOf(1); + chaiJestSnapshot.setFilename(resolveTestResource(`${fileName}.out.snap`)); + expect(result.files[0].textContent).matchSnapshot(); + } +}); diff --git a/packages/instrumenter/test/integration/parsers.it.spec.js.snap b/packages/instrumenter/test/integration/parsers.it.spec.js.snap new file mode 100644 index 0000000000..b2fef3651a --- /dev/null +++ b/packages/instrumenter/test/integration/parsers.it.spec.js.snap @@ -0,0 +1,13057 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`parser integration should allow to parse a *.vue file 1`] = ` +Object { + "format": "html", + "originFileName": "App.vue", + "rawContent": " + + + + +", + "root": Object { + "scripts": Array [ + Object { + "format": "js", + "originFileName": "App.vue", + "rawContent": " +import PokemonComponent from './Pokemon.vue' +import { pokemonService } from './pokemon.service'; + +export default { + components: { + PokemonComponent + }, + data() { + return { + pokemon: [] + } + }, + + created() { + pokemonService.getAll().then(pokemon => (this.pokemon = pokemon)); + } +} +", + "root": Node { + "comments": Array [], + "end": 490, + "errors": Array [], + "loc": SourceLocation { + "end": Position { + "column": 0, + "line": 26, + }, + "start": Position { + "column": 8, + "line": 8, + }, + }, + "program": Node { + "body": Array [ + Node { + "end": 232, + "loc": SourceLocation { + "end": Position { + "column": 44, + "line": 16, + }, + "start": Position { + "column": 0, + "line": 9, + }, + }, + "source": Node { + "end": 232, + "extra": Object { + "raw": "'./Pokemon.vue'", + "rawValue": "./Pokemon.vue", + }, + "loc": SourceLocation { + "end": Position { + "column": 44, + "line": 16, + }, + "start": Position { + "column": 29, + "line": 9, + }, + }, + "start": 217, + "type": "StringLiteral", + "value": "./Pokemon.vue", + }, + "specifiers": Array [ + Node { + "end": 211, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 16, + }, + "start": Position { + "column": 7, + "line": 16, + }, + }, + "local": Node { + "end": 211, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 16, + }, + "identifierName": "PokemonComponent", + "start": Position { + "column": 7, + "line": 16, + }, + }, + "name": "PokemonComponent", + "start": 195, + "type": "Identifier", + }, + "start": 195, + "type": "ImportDefaultSpecifier", + }, + ], + "start": 188, + "type": "ImportDeclaration", + }, + Node { + "end": 284, + "loc": SourceLocation { + "end": Position { + "column": 51, + "line": 10, + }, + "start": Position { + "column": 0, + "line": 10, + }, + }, + "source": Node { + "end": 283, + "extra": Object { + "raw": "'./pokemon.service'", + "rawValue": "./pokemon.service", + }, + "loc": SourceLocation { + "end": Position { + "column": 50, + "line": 10, + }, + "start": Position { + "column": 31, + "line": 10, + }, + }, + "start": 264, + "type": "StringLiteral", + "value": "./pokemon.service", + }, + "specifiers": Array [ + Node { + "end": 256, + "imported": Node { + "end": 256, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 24, + }, + "identifierName": "pokemonService", + "start": Position { + "column": 9, + "line": 24, + }, + }, + "name": "pokemonService", + "start": 242, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 24, + }, + "start": Position { + "column": 9, + "line": 24, + }, + }, + "local": Node { + "end": 256, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 24, + }, + "identifierName": "pokemonService", + "start": Position { + "column": 9, + "line": 24, + }, + }, + "name": "pokemonService", + "start": 242, + "type": "Identifier", + }, + "start": 242, + "type": "ImportSpecifier", + }, + ], + "start": 233, + "type": "ImportDeclaration", + }, + Node { + "declaration": Node { + "end": 489, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 32, + }, + "start": Position { + "column": 15, + "line": 12, + }, + }, + "properties": Array [ + Node { + "computed": false, + "end": 343, + "key": Node { + "end": 315, + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 13, + }, + "identifierName": "components", + "start": Position { + "column": 2, + "line": 20, + }, + }, + "name": "components", + "start": 305, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 22, + }, + "start": Position { + "column": 2, + "line": 20, + }, + }, + "method": false, + "shorthand": false, + "start": 305, + "type": "ObjectProperty", + "value": Node { + "end": 343, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 22, + }, + "start": Position { + "column": 14, + "line": 13, + }, + }, + "properties": Array [ + Node { + "computed": false, + "end": 339, + "extra": Object { + "shorthand": true, + }, + "key": Node { + "end": 339, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 28, + }, + "identifierName": "PokemonComponent", + "start": Position { + "column": 4, + "line": 28, + }, + }, + "name": "PokemonComponent", + "start": 323, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 28, + }, + "start": Position { + "column": 4, + "line": 28, + }, + }, + "method": false, + "shorthand": true, + "start": 323, + "type": "ObjectProperty", + "value": Node { + "end": 339, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 28, + }, + "identifierName": "PokemonComponent", + "start": Position { + "column": 4, + "line": 28, + }, + }, + "name": "PokemonComponent", + "start": 323, + "type": "Identifier", + }, + }, + ], + "start": 317, + "type": "ObjectExpression", + }, + }, + Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "argument": Node { + "end": 392, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 26, + }, + "start": Position { + "column": 11, + "line": 17, + }, + }, + "properties": Array [ + Node { + "computed": false, + "end": 386, + "key": Node { + "end": 382, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 18, + }, + "identifierName": "pokemon", + "start": Position { + "column": 6, + "line": 25, + }, + }, + "name": "pokemon", + "start": 375, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 17, + "line": 25, + }, + "start": Position { + "column": 6, + "line": 25, + }, + }, + "method": false, + "shorthand": false, + "start": 375, + "type": "ObjectProperty", + "value": Node { + "elements": Array [], + "end": 386, + "loc": SourceLocation { + "end": Position { + "column": 17, + "line": 25, + }, + "start": Position { + "column": 15, + "line": 18, + }, + }, + "start": 384, + "type": "ArrayExpression", + }, + }, + ], + "start": 367, + "type": "ObjectExpression", + }, + "end": 392, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 26, + }, + "start": Position { + "column": 4, + "line": 17, + }, + }, + "start": 360, + "type": "ReturnStatement", + }, + ], + "directives": Array [], + "end": 396, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 27, + }, + "start": Position { + "column": 9, + "line": 16, + }, + }, + "start": 354, + "type": "BlockStatement", + }, + "computed": false, + "end": 396, + "generator": false, + "id": null, + "key": Node { + "end": 351, + "loc": SourceLocation { + "end": Position { + "column": 6, + "line": 16, + }, + "identifierName": "data", + "start": Position { + "column": 2, + "line": 23, + }, + }, + "name": "data", + "start": 347, + "type": "Identifier", + }, + "kind": "method", + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 27, + }, + "start": Position { + "column": 2, + "line": 23, + }, + }, + "method": true, + "params": Array [], + "start": 347, + "type": "ObjectMethod", + }, + Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "end": 483, + "expression": Node { + "arguments": Array [ + Node { + "async": false, + "body": Node { + "end": 480, + "extra": Object { + "parenStart": 270, + "parenthesized": true, + }, + "left": Node { + "computed": false, + "end": 470, + "loc": SourceLocation { + "end": Position { + "column": 57, + "line": 30, + }, + "start": Position { + "column": 45, + "line": 37, + }, + }, + "object": Node { + "end": 462, + "loc": SourceLocation { + "end": Position { + "column": 49, + "line": 23, + }, + "start": Position { + "column": 45, + "line": 37, + }, + }, + "start": 458, + "type": "ThisExpression", + }, + "property": Node { + "end": 470, + "loc": SourceLocation { + "end": Position { + "column": 57, + "line": 30, + }, + "identifierName": "pokemon", + "start": Position { + "column": 50, + "line": 23, + }, + }, + "name": "pokemon", + "start": 463, + "type": "Identifier", + }, + "start": 458, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 67, + "line": 30, + }, + "start": Position { + "column": 45, + "line": 37, + }, + }, + "operator": "=", + "right": Node { + "end": 480, + "loc": SourceLocation { + "end": Position { + "column": 67, + "line": 30, + }, + "identifierName": "pokemon", + "start": Position { + "column": 60, + "line": 23, + }, + }, + "name": "pokemon", + "start": 473, + "type": "Identifier", + }, + "start": 458, + "type": "AssignmentExpression", + }, + "end": 481, + "generator": false, + "id": null, + "loc": SourceLocation { + "end": Position { + "column": 68, + "line": 23, + }, + "start": Position { + "column": 33, + "line": 30, + }, + }, + "params": Array [ + Node { + "end": 453, + "loc": SourceLocation { + "end": Position { + "column": 40, + "line": 23, + }, + "identifierName": "pokemon", + "start": Position { + "column": 33, + "line": 30, + }, + }, + "name": "pokemon", + "start": 446, + "type": "Identifier", + }, + ], + "start": 446, + "type": "ArrowFunctionExpression", + }, + ], + "callee": Node { + "computed": false, + "end": 445, + "loc": SourceLocation { + "end": Position { + "column": 32, + "line": 30, + }, + "start": Position { + "column": 4, + "line": 58, + }, + }, + "object": Node { + "arguments": Array [], + "callee": Node { + "computed": false, + "end": 438, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 30, + }, + "start": Position { + "column": 4, + "line": 58, + }, + }, + "object": Node { + "end": 431, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 23, + }, + "identifierName": "pokemonService", + "start": Position { + "column": 4, + "line": 58, + }, + }, + "name": "pokemonService", + "start": 417, + "type": "Identifier", + }, + "property": Node { + "end": 438, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 30, + }, + "identifierName": "getAll", + "start": Position { + "column": 19, + "line": 23, + }, + }, + "name": "getAll", + "start": 432, + "type": "Identifier", + }, + "start": 417, + "type": "MemberExpression", + }, + "end": 440, + "loc": SourceLocation { + "end": Position { + "column": 27, + "line": 23, + }, + "start": Position { + "column": 4, + "line": 58, + }, + }, + "start": 417, + "type": "CallExpression", + }, + "property": Node { + "end": 445, + "loc": SourceLocation { + "end": Position { + "column": 32, + "line": 30, + }, + "identifierName": "then", + "start": Position { + "column": 28, + "line": 23, + }, + }, + "name": "then", + "start": 441, + "type": "Identifier", + }, + "start": 417, + "type": "MemberExpression", + }, + "end": 482, + "loc": SourceLocation { + "end": Position { + "column": 69, + "line": 23, + }, + "start": Position { + "column": 4, + "line": 58, + }, + }, + "start": 417, + "type": "CallExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 70, + "line": 23, + }, + "start": Position { + "column": 4, + "line": 58, + }, + }, + "start": 417, + "type": "ExpressionStatement", + }, + ], + "directives": Array [], + "end": 487, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 31, + }, + "start": Position { + "column": 12, + "line": 22, + }, + }, + "start": 411, + "type": "BlockStatement", + }, + "computed": false, + "end": 487, + "generator": false, + "id": null, + "key": Node { + "end": 408, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 22, + }, + "identifierName": "created", + "start": Position { + "column": 2, + "line": 29, + }, + }, + "name": "created", + "start": 401, + "type": "Identifier", + }, + "kind": "method", + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 31, + }, + "start": Position { + "column": 2, + "line": 29, + }, + }, + "method": true, + "params": Array [], + "start": 401, + "type": "ObjectMethod", + }, + ], + "start": 301, + "type": "ObjectExpression", + }, + "end": 489, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 32, + }, + "start": Position { + "column": 0, + "line": 12, + }, + }, + "start": 286, + "type": "ExportDefaultDeclaration", + }, + ], + "directives": Array [], + "end": 490, + "interpreter": null, + "loc": SourceLocation { + "end": Position { + "column": 0, + "line": 26, + }, + "start": Position { + "column": 8, + "line": 8, + }, + }, + "sourceType": "module", + "start": 187, + "type": "Program", + }, + "start": 187, + "type": "File", + }, + }, + ], + }, +} +`; + +exports[`parser integration should allow to parse a an angular file 1`] = ` +Object { + "format": "ts", + "originFileName": "app.component.ts", + "rawContent": "import { Component } from '@angular/core'; + +@Component({ + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.scss'] +}) +export class AppComponent { + title = 'angular-app'; +} +", + "root": Node { + "comments": Array [], + "end": 216, + "errors": Array [], + "loc": SourceLocation { + "end": Position { + "column": 0, + "line": 11, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "program": Node { + "body": Array [ + Node { + "end": 42, + "importKind": "value", + "loc": SourceLocation { + "end": Position { + "column": 42, + "line": 1, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 42, + ], + "source": Node { + "end": 41, + "extra": Object { + "raw": "'@angular/core'", + "rawValue": "@angular/core", + }, + "loc": SourceLocation { + "end": Position { + "column": 41, + "line": 1, + }, + "start": Position { + "column": 26, + "line": 1, + }, + }, + "range": Array [ + 26, + 41, + ], + "start": 26, + "type": "StringLiteral", + "value": "@angular/core", + }, + "specifiers": Array [ + Node { + "end": 18, + "imported": Node { + "end": 18, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 1, + }, + "identifierName": "Component", + "start": Position { + "column": 9, + "line": 1, + }, + }, + "name": "Component", + "range": Array [ + 9, + 18, + ], + "start": 9, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 1, + }, + "start": Position { + "column": 9, + "line": 1, + }, + }, + "local": Node { + "end": 18, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 1, + }, + "identifierName": "Component", + "start": Position { + "column": 9, + "line": 1, + }, + }, + "name": "Component", + "range": Array [ + 9, + 18, + ], + "start": 9, + "type": "Identifier", + }, + "range": Array [ + 9, + 18, + ], + "start": 9, + "type": "ImportSpecifier", + }, + ], + "start": 0, + "type": "ImportDeclaration", + }, + Node { + "declaration": Node { + "body": Node { + "body": Array [ + Node { + "computed": false, + "end": 213, + "key": Node { + "end": 196, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 9, + }, + "identifierName": "title", + "start": Position { + "column": 2, + "line": 9, + }, + }, + "name": "title", + "range": Array [ + 191, + 196, + ], + "start": 191, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 9, + }, + "start": Position { + "column": 2, + "line": 9, + }, + }, + "range": Array [ + 191, + 213, + ], + "start": 191, + "static": false, + "type": "ClassProperty", + "value": Node { + "end": 212, + "extra": Object { + "raw": "'angular-app'", + "rawValue": "angular-app", + }, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 9, + }, + "start": Position { + "column": 10, + "line": 9, + }, + }, + "range": Array [ + 199, + 212, + ], + "start": 199, + "type": "StringLiteral", + "value": "angular-app", + }, + }, + ], + "end": 215, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 10, + }, + "start": Position { + "column": 26, + "line": 8, + }, + }, + "range": Array [ + 187, + 215, + ], + "start": 187, + "type": "ClassBody", + }, + "decorators": Array [ + Node { + "end": 160, + "expression": Node { + "arguments": Array [ + Node { + "end": 159, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 7, + }, + "start": Position { + "column": 11, + "line": 3, + }, + }, + "properties": Array [ + Node { + "computed": false, + "end": 79, + "key": Node { + "end": 67, + "loc": SourceLocation { + "end": Position { + "column": 10, + "line": 4, + }, + "identifierName": "selector", + "start": Position { + "column": 2, + "line": 4, + }, + }, + "name": "selector", + "range": Array [ + 59, + 67, + ], + "start": 59, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 4, + }, + "start": Position { + "column": 2, + "line": 4, + }, + }, + "method": false, + "range": Array [ + 59, + 79, + ], + "shorthand": false, + "start": 59, + "type": "ObjectProperty", + "value": Node { + "end": 79, + "extra": Object { + "raw": "'app-root'", + "rawValue": "app-root", + }, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 4, + }, + "start": Position { + "column": 12, + "line": 4, + }, + }, + "range": Array [ + 69, + 79, + ], + "start": 69, + "type": "StringLiteral", + "value": "app-root", + }, + }, + Node { + "computed": false, + "end": 118, + "key": Node { + "end": 94, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 5, + }, + "identifierName": "templateUrl", + "start": Position { + "column": 2, + "line": 5, + }, + }, + "name": "templateUrl", + "range": Array [ + 83, + 94, + ], + "start": 83, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 37, + "line": 5, + }, + "start": Position { + "column": 2, + "line": 5, + }, + }, + "method": false, + "range": Array [ + 83, + 118, + ], + "shorthand": false, + "start": 83, + "type": "ObjectProperty", + "value": Node { + "end": 118, + "extra": Object { + "raw": "'./app.component.html'", + "rawValue": "./app.component.html", + }, + "loc": SourceLocation { + "end": Position { + "column": 37, + "line": 5, + }, + "start": Position { + "column": 15, + "line": 5, + }, + }, + "range": Array [ + 96, + 118, + ], + "start": 96, + "type": "StringLiteral", + "value": "./app.component.html", + }, + }, + Node { + "computed": false, + "end": 157, + "key": Node { + "end": 131, + "loc": SourceLocation { + "end": Position { + "column": 11, + "line": 6, + }, + "identifierName": "styleUrls", + "start": Position { + "column": 2, + "line": 6, + }, + }, + "name": "styleUrls", + "range": Array [ + 122, + 131, + ], + "start": 122, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 37, + "line": 6, + }, + "start": Position { + "column": 2, + "line": 6, + }, + }, + "method": false, + "range": Array [ + 122, + 157, + ], + "shorthand": false, + "start": 122, + "type": "ObjectProperty", + "value": Node { + "elements": Array [ + Node { + "end": 156, + "extra": Object { + "raw": "'./app.component.scss'", + "rawValue": "./app.component.scss", + }, + "loc": SourceLocation { + "end": Position { + "column": 36, + "line": 6, + }, + "start": Position { + "column": 14, + "line": 6, + }, + }, + "range": Array [ + 134, + 156, + ], + "start": 134, + "type": "StringLiteral", + "value": "./app.component.scss", + }, + ], + "end": 157, + "loc": SourceLocation { + "end": Position { + "column": 37, + "line": 6, + }, + "start": Position { + "column": 13, + "line": 6, + }, + }, + "range": Array [ + 133, + 157, + ], + "start": 133, + "type": "ArrayExpression", + }, + }, + ], + "range": Array [ + 55, + 159, + ], + "start": 55, + "type": "ObjectExpression", + }, + ], + "callee": Node { + "end": 54, + "loc": SourceLocation { + "end": Position { + "column": 10, + "line": 3, + }, + "identifierName": "Component", + "start": Position { + "column": 1, + "line": 3, + }, + }, + "name": "Component", + "range": Array [ + 45, + 54, + ], + "start": 45, + "type": "Identifier", + }, + "end": 160, + "loc": SourceLocation { + "end": Position { + "column": 2, + "line": 7, + }, + "start": Position { + "column": 1, + "line": 3, + }, + }, + "range": Array [ + 45, + 160, + ], + "start": 45, + "type": "CallExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 2, + "line": 7, + }, + "start": Position { + "column": 0, + "line": 3, + }, + }, + "range": Array [ + 44, + 160, + ], + "start": 44, + "type": "Decorator", + }, + ], + "end": 215, + "id": Node { + "end": 186, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 8, + }, + "identifierName": "AppComponent", + "start": Position { + "column": 13, + "line": 8, + }, + }, + "name": "AppComponent", + "range": Array [ + 174, + 186, + ], + "start": 174, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 10, + }, + "start": Position { + "column": 0, + "line": 3, + }, + }, + "range": Array [ + 44, + 215, + ], + "start": 44, + "superClass": null, + "type": "ClassDeclaration", + }, + "end": 215, + "exportKind": "value", + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 10, + }, + "start": Position { + "column": 0, + "line": 8, + }, + }, + "range": Array [ + 161, + 215, + ], + "source": null, + "specifiers": Array [], + "start": 161, + "type": "ExportNamedDeclaration", + }, + ], + "directives": Array [], + "end": 216, + "interpreter": null, + "loc": SourceLocation { + "end": Position { + "column": 0, + "line": 11, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 216, + ], + "sourceType": "module", + "start": 0, + "type": "Program", + }, + "range": Array [ + 0, + 216, + ], + "start": 0, + "type": "File", + }, +} +`; + +exports[`parser integration should allow to parse a react file react code with project-wide configuration file 1`] = ` +Object { + "format": "js", + "originFileName": "jsx-with-project-wide-config/src/Badge.js", + "rawContent": "import React from 'react'; +import PropTypes from 'prop-types'; + +const propTypes = { + color: PropTypes.string +}; + +const defaultProps = { + color: 'secondary', +}; + +const Badge = (props) => { + let { + color, + ...attributes + } = props; + + const classes = ['badge', 'badge-' + color]; + + if (attributes.href && Tag === 'span') { + Tag = 'a'; + } + + return ( + + ); +}; + +Badge.propTypes = propTypes; +Badge.defaultProps = defaultProps; + +export default Badge; +", + "root": Node { + "comments": Array [], + "end": 507, + "errors": Array [], + "loc": SourceLocation { + "end": Position { + "column": 0, + "line": 33, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "program": Node { + "body": Array [ + Node { + "end": 26, + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 1, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "source": Node { + "end": 25, + "extra": Object { + "raw": "'react'", + "rawValue": "react", + }, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 1, + }, + "start": Position { + "column": 18, + "line": 1, + }, + }, + "start": 18, + "type": "StringLiteral", + "value": "react", + }, + "specifiers": Array [ + Node { + "end": 12, + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 1, + }, + "start": Position { + "column": 7, + "line": 1, + }, + }, + "local": Node { + "end": 12, + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 1, + }, + "identifierName": "React", + "start": Position { + "column": 7, + "line": 1, + }, + }, + "name": "React", + "start": 7, + "type": "Identifier", + }, + "start": 7, + "type": "ImportDefaultSpecifier", + }, + ], + "start": 0, + "type": "ImportDeclaration", + }, + Node { + "end": 62, + "loc": SourceLocation { + "end": Position { + "column": 35, + "line": 2, + }, + "start": Position { + "column": 0, + "line": 2, + }, + }, + "source": Node { + "end": 61, + "extra": Object { + "raw": "'prop-types'", + "rawValue": "prop-types", + }, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 2, + }, + "start": Position { + "column": 22, + "line": 2, + }, + }, + "start": 49, + "type": "StringLiteral", + "value": "prop-types", + }, + "specifiers": Array [ + Node { + "end": 43, + "loc": SourceLocation { + "end": Position { + "column": 16, + "line": 2, + }, + "start": Position { + "column": 7, + "line": 2, + }, + }, + "local": Node { + "end": 43, + "loc": SourceLocation { + "end": Position { + "column": 16, + "line": 2, + }, + "identifierName": "PropTypes", + "start": Position { + "column": 7, + "line": 2, + }, + }, + "name": "PropTypes", + "start": 34, + "type": "Identifier", + }, + "start": 34, + "type": "ImportDefaultSpecifier", + }, + ], + "start": 27, + "type": "ImportDeclaration", + }, + Node { + "declarations": Array [ + Node { + "end": 111, + "id": Node { + "end": 79, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 4, + }, + "identifierName": "propTypes", + "start": Position { + "column": 6, + "line": 4, + }, + }, + "name": "propTypes", + "start": 70, + "type": "Identifier", + }, + "init": Node { + "end": 111, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 6, + }, + "start": Position { + "column": 18, + "line": 4, + }, + }, + "properties": Array [ + Node { + "computed": false, + "end": 109, + "key": Node { + "end": 91, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 5, + }, + "identifierName": "color", + "start": Position { + "column": 2, + "line": 5, + }, + }, + "name": "color", + "start": 86, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 5, + }, + "start": Position { + "column": 2, + "line": 5, + }, + }, + "method": false, + "shorthand": false, + "start": 86, + "type": "ObjectProperty", + "value": Node { + "computed": false, + "end": 109, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 5, + }, + "start": Position { + "column": 9, + "line": 5, + }, + }, + "object": Node { + "end": 102, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 5, + }, + "identifierName": "PropTypes", + "start": Position { + "column": 9, + "line": 5, + }, + }, + "name": "PropTypes", + "start": 93, + "type": "Identifier", + }, + "property": Node { + "end": 109, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 5, + }, + "identifierName": "string", + "start": Position { + "column": 19, + "line": 5, + }, + }, + "name": "string", + "start": 103, + "type": "Identifier", + }, + "start": 93, + "type": "MemberExpression", + }, + }, + ], + "start": 82, + "type": "ObjectExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 6, + }, + "start": Position { + "column": 6, + "line": 4, + }, + }, + "start": 70, + "type": "VariableDeclarator", + }, + ], + "end": 112, + "kind": "const", + "loc": SourceLocation { + "end": Position { + "column": 2, + "line": 6, + }, + "start": Position { + "column": 0, + "line": 4, + }, + }, + "start": 64, + "type": "VariableDeclaration", + }, + Node { + "declarations": Array [ + Node { + "end": 160, + "id": Node { + "end": 132, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 8, + }, + "identifierName": "defaultProps", + "start": Position { + "column": 6, + "line": 8, + }, + }, + "name": "defaultProps", + "start": 120, + "type": "Identifier", + }, + "init": Node { + "end": 160, + "extra": Object { + "trailingComma": 157, + }, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 10, + }, + "start": Position { + "column": 21, + "line": 8, + }, + }, + "properties": Array [ + Node { + "computed": false, + "end": 157, + "key": Node { + "end": 144, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 9, + }, + "identifierName": "color", + "start": Position { + "column": 2, + "line": 9, + }, + }, + "name": "color", + "start": 139, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 9, + }, + "start": Position { + "column": 2, + "line": 9, + }, + }, + "method": false, + "shorthand": false, + "start": 139, + "type": "ObjectProperty", + "value": Node { + "end": 157, + "extra": Object { + "raw": "'secondary'", + "rawValue": "secondary", + }, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 9, + }, + "start": Position { + "column": 9, + "line": 9, + }, + }, + "start": 146, + "type": "StringLiteral", + "value": "secondary", + }, + }, + ], + "start": 135, + "type": "ObjectExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 10, + }, + "start": Position { + "column": 6, + "line": 8, + }, + }, + "start": 120, + "type": "VariableDeclarator", + }, + ], + "end": 161, + "kind": "const", + "loc": SourceLocation { + "end": Position { + "column": 2, + "line": 10, + }, + "start": Position { + "column": 0, + "line": 8, + }, + }, + "start": 114, + "type": "VariableDeclaration", + }, + Node { + "declarations": Array [ + Node { + "end": 417, + "id": Node { + "end": 174, + "loc": SourceLocation { + "end": Position { + "column": 11, + "line": 12, + }, + "identifierName": "Badge", + "start": Position { + "column": 6, + "line": 12, + }, + }, + "name": "Badge", + "start": 169, + "type": "Identifier", + }, + "init": Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "declarations": Array [ + Node { + "end": 238, + "id": Node { + "end": 230, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 16, + }, + "start": Position { + "column": 6, + "line": 13, + }, + }, + "properties": Array [ + Node { + "computed": false, + "end": 207, + "extra": Object { + "shorthand": true, + }, + "key": Node { + "end": 207, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 14, + }, + "identifierName": "color", + "start": Position { + "column": 4, + "line": 14, + }, + }, + "name": "color", + "start": 202, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 14, + }, + "start": Position { + "column": 4, + "line": 14, + }, + }, + "method": false, + "shorthand": true, + "start": 202, + "type": "ObjectProperty", + "value": Node { + "end": 207, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 14, + }, + "identifierName": "color", + "start": Position { + "column": 4, + "line": 14, + }, + }, + "name": "color", + "start": 202, + "type": "Identifier", + }, + }, + Node { + "argument": Node { + "end": 226, + "loc": SourceLocation { + "end": Position { + "column": 17, + "line": 15, + }, + "identifierName": "attributes", + "start": Position { + "column": 7, + "line": 15, + }, + }, + "name": "attributes", + "start": 216, + "type": "Identifier", + }, + "end": 226, + "loc": SourceLocation { + "end": Position { + "column": 17, + "line": 15, + }, + "start": Position { + "column": 4, + "line": 15, + }, + }, + "start": 213, + "type": "RestElement", + }, + ], + "start": 196, + "type": "ObjectPattern", + }, + "init": Node { + "end": 238, + "loc": SourceLocation { + "end": Position { + "column": 11, + "line": 16, + }, + "identifierName": "props", + "start": Position { + "column": 6, + "line": 16, + }, + }, + "name": "props", + "start": 233, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 11, + "line": 16, + }, + "start": Position { + "column": 6, + "line": 13, + }, + }, + "start": 196, + "type": "VariableDeclarator", + }, + ], + "end": 239, + "kind": "let", + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 16, + }, + "start": Position { + "column": 2, + "line": 13, + }, + }, + "start": 192, + "type": "VariableDeclaration", + }, + Node { + "declarations": Array [ + Node { + "end": 286, + "id": Node { + "end": 256, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 18, + }, + "identifierName": "classes", + "start": Position { + "column": 8, + "line": 18, + }, + }, + "name": "classes", + "start": 249, + "type": "Identifier", + }, + "init": Node { + "elements": Array [ + Node { + "end": 267, + "extra": Object { + "raw": "'badge'", + "rawValue": "badge", + }, + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 18, + }, + "start": Position { + "column": 19, + "line": 18, + }, + }, + "start": 260, + "type": "StringLiteral", + "value": "badge", + }, + Node { + "end": 285, + "left": Node { + "end": 277, + "extra": Object { + "raw": "'badge-'", + "rawValue": "badge-", + }, + "loc": SourceLocation { + "end": Position { + "column": 36, + "line": 18, + }, + "start": Position { + "column": 28, + "line": 18, + }, + }, + "start": 269, + "type": "StringLiteral", + "value": "badge-", + }, + "loc": SourceLocation { + "end": Position { + "column": 44, + "line": 18, + }, + "start": Position { + "column": 28, + "line": 18, + }, + }, + "operator": "+", + "right": Node { + "end": 285, + "loc": SourceLocation { + "end": Position { + "column": 44, + "line": 18, + }, + "identifierName": "color", + "start": Position { + "column": 39, + "line": 18, + }, + }, + "name": "color", + "start": 280, + "type": "Identifier", + }, + "start": 269, + "type": "BinaryExpression", + }, + ], + "end": 286, + "loc": SourceLocation { + "end": Position { + "column": 45, + "line": 18, + }, + "start": Position { + "column": 18, + "line": 18, + }, + }, + "start": 259, + "type": "ArrayExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 45, + "line": 18, + }, + "start": Position { + "column": 8, + "line": 18, + }, + }, + "start": 249, + "type": "VariableDeclarator", + }, + ], + "end": 287, + "kind": "const", + "loc": SourceLocation { + "end": Position { + "column": 46, + "line": 18, + }, + "start": Position { + "column": 2, + "line": 18, + }, + }, + "start": 243, + "type": "VariableDeclaration", + }, + Node { + "alternate": null, + "consequent": Node { + "body": Array [ + Node { + "end": 346, + "expression": Node { + "end": 345, + "left": Node { + "end": 339, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 21, + }, + "identifierName": "Tag", + "start": Position { + "column": 4, + "line": 21, + }, + }, + "name": "Tag", + "start": 336, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 21, + }, + "start": Position { + "column": 4, + "line": 21, + }, + }, + "operator": "=", + "right": Node { + "end": 345, + "extra": Object { + "raw": "'a'", + "rawValue": "a", + }, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 21, + }, + "start": Position { + "column": 10, + "line": 21, + }, + }, + "start": 342, + "type": "StringLiteral", + "value": "a", + }, + "start": 336, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 14, + "line": 21, + }, + "start": Position { + "column": 4, + "line": 21, + }, + }, + "start": 336, + "type": "ExpressionStatement", + }, + ], + "directives": Array [], + "end": 350, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 22, + }, + "start": Position { + "column": 41, + "line": 20, + }, + }, + "start": 330, + "type": "BlockStatement", + }, + "end": 350, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 22, + }, + "start": Position { + "column": 2, + "line": 20, + }, + }, + "start": 291, + "test": Node { + "end": 328, + "left": Node { + "computed": false, + "end": 310, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 20, + }, + "start": Position { + "column": 6, + "line": 20, + }, + }, + "object": Node { + "end": 305, + "loc": SourceLocation { + "end": Position { + "column": 16, + "line": 20, + }, + "identifierName": "attributes", + "start": Position { + "column": 6, + "line": 20, + }, + }, + "name": "attributes", + "start": 295, + "type": "Identifier", + }, + "property": Node { + "end": 310, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 20, + }, + "identifierName": "href", + "start": Position { + "column": 17, + "line": 20, + }, + }, + "name": "href", + "start": 306, + "type": "Identifier", + }, + "start": 295, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 39, + "line": 20, + }, + "start": Position { + "column": 6, + "line": 20, + }, + }, + "operator": "&&", + "right": Node { + "end": 328, + "left": Node { + "end": 317, + "loc": SourceLocation { + "end": Position { + "column": 28, + "line": 20, + }, + "identifierName": "Tag", + "start": Position { + "column": 25, + "line": 20, + }, + }, + "name": "Tag", + "start": 314, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 39, + "line": 20, + }, + "start": Position { + "column": 25, + "line": 20, + }, + }, + "operator": "===", + "right": Node { + "end": 328, + "extra": Object { + "raw": "'span'", + "rawValue": "span", + }, + "loc": SourceLocation { + "end": Position { + "column": 39, + "line": 20, + }, + "start": Position { + "column": 33, + "line": 20, + }, + }, + "start": 322, + "type": "StringLiteral", + "value": "span", + }, + "start": 314, + "type": "BinaryExpression", + }, + "start": 295, + "type": "LogicalExpression", + }, + "type": "IfStatement", + }, + Node { + "argument": Node { + "children": Array [], + "closingElement": null, + "end": 410, + "extra": Object { + "parenStart": 361, + "parenthesized": true, + }, + "loc": SourceLocation { + "end": Position { + "column": 47, + "line": 25, + }, + "start": Position { + "column": 4, + "line": 25, + }, + }, + "openingElement": Node { + "attributes": Array [ + Node { + "argument": Node { + "end": 386, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 25, + }, + "identifierName": "attributes", + "start": Position { + "column": 13, + "line": 25, + }, + }, + "name": "attributes", + "start": 376, + "type": "Identifier", + }, + "end": 387, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 25, + }, + "start": Position { + "column": 9, + "line": 25, + }, + }, + "start": 372, + "type": "JSXSpreadAttribute", + }, + Node { + "end": 407, + "loc": SourceLocation { + "end": Position { + "column": 44, + "line": 25, + }, + "start": Position { + "column": 25, + "line": 25, + }, + }, + "name": Node { + "end": 397, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 25, + }, + "start": Position { + "column": 25, + "line": 25, + }, + }, + "name": "className", + "start": 388, + "type": "JSXIdentifier", + }, + "start": 388, + "type": "JSXAttribute", + "value": Node { + "end": 407, + "expression": Node { + "end": 406, + "loc": SourceLocation { + "end": Position { + "column": 43, + "line": 25, + }, + "identifierName": "classes", + "start": Position { + "column": 36, + "line": 25, + }, + }, + "name": "classes", + "start": 399, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 44, + "line": 25, + }, + "start": Position { + "column": 35, + "line": 25, + }, + }, + "start": 398, + "type": "JSXExpressionContainer", + }, + }, + ], + "end": 410, + "loc": SourceLocation { + "end": Position { + "column": 47, + "line": 25, + }, + "start": Position { + "column": 4, + "line": 25, + }, + }, + "name": Node { + "end": 371, + "loc": SourceLocation { + "end": Position { + "column": 8, + "line": 25, + }, + "start": Position { + "column": 5, + "line": 25, + }, + }, + "name": "Tag", + "start": 368, + "type": "JSXIdentifier", + }, + "selfClosing": true, + "start": 367, + "type": "JSXOpeningElement", + }, + "start": 367, + "type": "JSXElement", + }, + "end": 415, + "loc": SourceLocation { + "end": Position { + "column": 4, + "line": 26, + }, + "start": Position { + "column": 2, + "line": 24, + }, + }, + "start": 354, + "type": "ReturnStatement", + }, + ], + "directives": Array [], + "end": 417, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 27, + }, + "start": Position { + "column": 25, + "line": 12, + }, + }, + "start": 188, + "type": "BlockStatement", + }, + "end": 417, + "generator": false, + "id": null, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 27, + }, + "start": Position { + "column": 14, + "line": 12, + }, + }, + "params": Array [ + Node { + "end": 183, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 12, + }, + "identifierName": "props", + "start": Position { + "column": 15, + "line": 12, + }, + }, + "name": "props", + "start": 178, + "type": "Identifier", + }, + ], + "start": 177, + "type": "ArrowFunctionExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 27, + }, + "start": Position { + "column": 6, + "line": 12, + }, + }, + "start": 169, + "type": "VariableDeclarator", + }, + ], + "end": 418, + "kind": "const", + "loc": SourceLocation { + "end": Position { + "column": 2, + "line": 27, + }, + "start": Position { + "column": 0, + "line": 12, + }, + }, + "start": 163, + "type": "VariableDeclaration", + }, + Node { + "end": 448, + "expression": Node { + "end": 447, + "left": Node { + "computed": false, + "end": 435, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 29, + }, + "start": Position { + "column": 0, + "line": 29, + }, + }, + "object": Node { + "end": 425, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 29, + }, + "identifierName": "Badge", + "start": Position { + "column": 0, + "line": 29, + }, + }, + "name": "Badge", + "start": 420, + "type": "Identifier", + }, + "property": Node { + "end": 435, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 29, + }, + "identifierName": "propTypes", + "start": Position { + "column": 6, + "line": 29, + }, + }, + "name": "propTypes", + "start": 426, + "type": "Identifier", + }, + "start": 420, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 27, + "line": 29, + }, + "start": Position { + "column": 0, + "line": 29, + }, + }, + "operator": "=", + "right": Node { + "end": 447, + "loc": SourceLocation { + "end": Position { + "column": 27, + "line": 29, + }, + "identifierName": "propTypes", + "start": Position { + "column": 18, + "line": 29, + }, + }, + "name": "propTypes", + "start": 438, + "type": "Identifier", + }, + "start": 420, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 28, + "line": 29, + }, + "start": Position { + "column": 0, + "line": 29, + }, + }, + "start": 420, + "type": "ExpressionStatement", + }, + Node { + "end": 483, + "expression": Node { + "end": 482, + "left": Node { + "computed": false, + "end": 467, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 30, + }, + "start": Position { + "column": 0, + "line": 30, + }, + }, + "object": Node { + "end": 454, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 30, + }, + "identifierName": "Badge", + "start": Position { + "column": 0, + "line": 30, + }, + }, + "name": "Badge", + "start": 449, + "type": "Identifier", + }, + "property": Node { + "end": 467, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 30, + }, + "identifierName": "defaultProps", + "start": Position { + "column": 6, + "line": 30, + }, + }, + "name": "defaultProps", + "start": 455, + "type": "Identifier", + }, + "start": 449, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 33, + "line": 30, + }, + "start": Position { + "column": 0, + "line": 30, + }, + }, + "operator": "=", + "right": Node { + "end": 482, + "loc": SourceLocation { + "end": Position { + "column": 33, + "line": 30, + }, + "identifierName": "defaultProps", + "start": Position { + "column": 21, + "line": 30, + }, + }, + "name": "defaultProps", + "start": 470, + "type": "Identifier", + }, + "start": 449, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 30, + }, + "start": Position { + "column": 0, + "line": 30, + }, + }, + "start": 449, + "type": "ExpressionStatement", + }, + Node { + "declaration": Node { + "end": 505, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 32, + }, + "identifierName": "Badge", + "start": Position { + "column": 15, + "line": 32, + }, + }, + "name": "Badge", + "start": 500, + "type": "Identifier", + }, + "end": 506, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 32, + }, + "start": Position { + "column": 0, + "line": 32, + }, + }, + "start": 485, + "type": "ExportDefaultDeclaration", + }, + ], + "directives": Array [], + "end": 507, + "interpreter": null, + "loc": SourceLocation { + "end": Position { + "column": 0, + "line": 33, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "sourceType": "module", + "start": 0, + "type": "Program", + }, + "start": 0, + "type": "File", + }, +} +`; + +exports[`parser integration should allow to parse a react file with custom babelrc file 1`] = ` +Object { + "format": "js", + "originFileName": "jsx-with-babelrc/Badge.js", + "rawContent": "import React from 'react'; +import PropTypes from 'prop-types'; + +const propTypes = { + color: PropTypes.string +}; + +const defaultProps = { + color: 'secondary', +}; + +const Badge = (props) => { + let { + color, + ...attributes + } = props; + + const classes = ['badge', 'badge-' + color]; + + if (attributes.href && Tag === 'span') { + Tag = 'a'; + } + + return ( + + ); +}; + +Badge.propTypes = propTypes; +Badge.defaultProps = defaultProps; + +export default Badge; +", + "root": Node { + "comments": Array [], + "end": 507, + "errors": Array [], + "loc": SourceLocation { + "end": Position { + "column": 0, + "line": 33, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "program": Node { + "body": Array [ + Node { + "end": 26, + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 1, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "source": Node { + "end": 25, + "extra": Object { + "raw": "'react'", + "rawValue": "react", + }, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 1, + }, + "start": Position { + "column": 18, + "line": 1, + }, + }, + "start": 18, + "type": "StringLiteral", + "value": "react", + }, + "specifiers": Array [ + Node { + "end": 12, + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 1, + }, + "start": Position { + "column": 7, + "line": 1, + }, + }, + "local": Node { + "end": 12, + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 1, + }, + "identifierName": "React", + "start": Position { + "column": 7, + "line": 1, + }, + }, + "name": "React", + "start": 7, + "type": "Identifier", + }, + "start": 7, + "type": "ImportDefaultSpecifier", + }, + ], + "start": 0, + "type": "ImportDeclaration", + }, + Node { + "end": 62, + "loc": SourceLocation { + "end": Position { + "column": 35, + "line": 2, + }, + "start": Position { + "column": 0, + "line": 2, + }, + }, + "source": Node { + "end": 61, + "extra": Object { + "raw": "'prop-types'", + "rawValue": "prop-types", + }, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 2, + }, + "start": Position { + "column": 22, + "line": 2, + }, + }, + "start": 49, + "type": "StringLiteral", + "value": "prop-types", + }, + "specifiers": Array [ + Node { + "end": 43, + "loc": SourceLocation { + "end": Position { + "column": 16, + "line": 2, + }, + "start": Position { + "column": 7, + "line": 2, + }, + }, + "local": Node { + "end": 43, + "loc": SourceLocation { + "end": Position { + "column": 16, + "line": 2, + }, + "identifierName": "PropTypes", + "start": Position { + "column": 7, + "line": 2, + }, + }, + "name": "PropTypes", + "start": 34, + "type": "Identifier", + }, + "start": 34, + "type": "ImportDefaultSpecifier", + }, + ], + "start": 27, + "type": "ImportDeclaration", + }, + Node { + "declarations": Array [ + Node { + "end": 111, + "id": Node { + "end": 79, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 4, + }, + "identifierName": "propTypes", + "start": Position { + "column": 6, + "line": 4, + }, + }, + "name": "propTypes", + "start": 70, + "type": "Identifier", + }, + "init": Node { + "end": 111, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 6, + }, + "start": Position { + "column": 18, + "line": 4, + }, + }, + "properties": Array [ + Node { + "computed": false, + "end": 109, + "key": Node { + "end": 91, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 5, + }, + "identifierName": "color", + "start": Position { + "column": 2, + "line": 5, + }, + }, + "name": "color", + "start": 86, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 5, + }, + "start": Position { + "column": 2, + "line": 5, + }, + }, + "method": false, + "shorthand": false, + "start": 86, + "type": "ObjectProperty", + "value": Node { + "computed": false, + "end": 109, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 5, + }, + "start": Position { + "column": 9, + "line": 5, + }, + }, + "object": Node { + "end": 102, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 5, + }, + "identifierName": "PropTypes", + "start": Position { + "column": 9, + "line": 5, + }, + }, + "name": "PropTypes", + "start": 93, + "type": "Identifier", + }, + "property": Node { + "end": 109, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 5, + }, + "identifierName": "string", + "start": Position { + "column": 19, + "line": 5, + }, + }, + "name": "string", + "start": 103, + "type": "Identifier", + }, + "start": 93, + "type": "MemberExpression", + }, + }, + ], + "start": 82, + "type": "ObjectExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 6, + }, + "start": Position { + "column": 6, + "line": 4, + }, + }, + "start": 70, + "type": "VariableDeclarator", + }, + ], + "end": 112, + "kind": "const", + "loc": SourceLocation { + "end": Position { + "column": 2, + "line": 6, + }, + "start": Position { + "column": 0, + "line": 4, + }, + }, + "start": 64, + "type": "VariableDeclaration", + }, + Node { + "declarations": Array [ + Node { + "end": 160, + "id": Node { + "end": 132, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 8, + }, + "identifierName": "defaultProps", + "start": Position { + "column": 6, + "line": 8, + }, + }, + "name": "defaultProps", + "start": 120, + "type": "Identifier", + }, + "init": Node { + "end": 160, + "extra": Object { + "trailingComma": 157, + }, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 10, + }, + "start": Position { + "column": 21, + "line": 8, + }, + }, + "properties": Array [ + Node { + "computed": false, + "end": 157, + "key": Node { + "end": 144, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 9, + }, + "identifierName": "color", + "start": Position { + "column": 2, + "line": 9, + }, + }, + "name": "color", + "start": 139, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 9, + }, + "start": Position { + "column": 2, + "line": 9, + }, + }, + "method": false, + "shorthand": false, + "start": 139, + "type": "ObjectProperty", + "value": Node { + "end": 157, + "extra": Object { + "raw": "'secondary'", + "rawValue": "secondary", + }, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 9, + }, + "start": Position { + "column": 9, + "line": 9, + }, + }, + "start": 146, + "type": "StringLiteral", + "value": "secondary", + }, + }, + ], + "start": 135, + "type": "ObjectExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 10, + }, + "start": Position { + "column": 6, + "line": 8, + }, + }, + "start": 120, + "type": "VariableDeclarator", + }, + ], + "end": 161, + "kind": "const", + "loc": SourceLocation { + "end": Position { + "column": 2, + "line": 10, + }, + "start": Position { + "column": 0, + "line": 8, + }, + }, + "start": 114, + "type": "VariableDeclaration", + }, + Node { + "declarations": Array [ + Node { + "end": 417, + "id": Node { + "end": 174, + "loc": SourceLocation { + "end": Position { + "column": 11, + "line": 12, + }, + "identifierName": "Badge", + "start": Position { + "column": 6, + "line": 12, + }, + }, + "name": "Badge", + "start": 169, + "type": "Identifier", + }, + "init": Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "declarations": Array [ + Node { + "end": 238, + "id": Node { + "end": 230, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 16, + }, + "start": Position { + "column": 6, + "line": 13, + }, + }, + "properties": Array [ + Node { + "computed": false, + "end": 207, + "extra": Object { + "shorthand": true, + }, + "key": Node { + "end": 207, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 14, + }, + "identifierName": "color", + "start": Position { + "column": 4, + "line": 14, + }, + }, + "name": "color", + "start": 202, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 14, + }, + "start": Position { + "column": 4, + "line": 14, + }, + }, + "method": false, + "shorthand": true, + "start": 202, + "type": "ObjectProperty", + "value": Node { + "end": 207, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 14, + }, + "identifierName": "color", + "start": Position { + "column": 4, + "line": 14, + }, + }, + "name": "color", + "start": 202, + "type": "Identifier", + }, + }, + Node { + "argument": Node { + "end": 226, + "loc": SourceLocation { + "end": Position { + "column": 17, + "line": 15, + }, + "identifierName": "attributes", + "start": Position { + "column": 7, + "line": 15, + }, + }, + "name": "attributes", + "start": 216, + "type": "Identifier", + }, + "end": 226, + "loc": SourceLocation { + "end": Position { + "column": 17, + "line": 15, + }, + "start": Position { + "column": 4, + "line": 15, + }, + }, + "start": 213, + "type": "RestElement", + }, + ], + "start": 196, + "type": "ObjectPattern", + }, + "init": Node { + "end": 238, + "loc": SourceLocation { + "end": Position { + "column": 11, + "line": 16, + }, + "identifierName": "props", + "start": Position { + "column": 6, + "line": 16, + }, + }, + "name": "props", + "start": 233, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 11, + "line": 16, + }, + "start": Position { + "column": 6, + "line": 13, + }, + }, + "start": 196, + "type": "VariableDeclarator", + }, + ], + "end": 239, + "kind": "let", + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 16, + }, + "start": Position { + "column": 2, + "line": 13, + }, + }, + "start": 192, + "type": "VariableDeclaration", + }, + Node { + "declarations": Array [ + Node { + "end": 286, + "id": Node { + "end": 256, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 18, + }, + "identifierName": "classes", + "start": Position { + "column": 8, + "line": 18, + }, + }, + "name": "classes", + "start": 249, + "type": "Identifier", + }, + "init": Node { + "elements": Array [ + Node { + "end": 267, + "extra": Object { + "raw": "'badge'", + "rawValue": "badge", + }, + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 18, + }, + "start": Position { + "column": 19, + "line": 18, + }, + }, + "start": 260, + "type": "StringLiteral", + "value": "badge", + }, + Node { + "end": 285, + "left": Node { + "end": 277, + "extra": Object { + "raw": "'badge-'", + "rawValue": "badge-", + }, + "loc": SourceLocation { + "end": Position { + "column": 36, + "line": 18, + }, + "start": Position { + "column": 28, + "line": 18, + }, + }, + "start": 269, + "type": "StringLiteral", + "value": "badge-", + }, + "loc": SourceLocation { + "end": Position { + "column": 44, + "line": 18, + }, + "start": Position { + "column": 28, + "line": 18, + }, + }, + "operator": "+", + "right": Node { + "end": 285, + "loc": SourceLocation { + "end": Position { + "column": 44, + "line": 18, + }, + "identifierName": "color", + "start": Position { + "column": 39, + "line": 18, + }, + }, + "name": "color", + "start": 280, + "type": "Identifier", + }, + "start": 269, + "type": "BinaryExpression", + }, + ], + "end": 286, + "loc": SourceLocation { + "end": Position { + "column": 45, + "line": 18, + }, + "start": Position { + "column": 18, + "line": 18, + }, + }, + "start": 259, + "type": "ArrayExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 45, + "line": 18, + }, + "start": Position { + "column": 8, + "line": 18, + }, + }, + "start": 249, + "type": "VariableDeclarator", + }, + ], + "end": 287, + "kind": "const", + "loc": SourceLocation { + "end": Position { + "column": 46, + "line": 18, + }, + "start": Position { + "column": 2, + "line": 18, + }, + }, + "start": 243, + "type": "VariableDeclaration", + }, + Node { + "alternate": null, + "consequent": Node { + "body": Array [ + Node { + "end": 346, + "expression": Node { + "end": 345, + "left": Node { + "end": 339, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 21, + }, + "identifierName": "Tag", + "start": Position { + "column": 4, + "line": 21, + }, + }, + "name": "Tag", + "start": 336, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 21, + }, + "start": Position { + "column": 4, + "line": 21, + }, + }, + "operator": "=", + "right": Node { + "end": 345, + "extra": Object { + "raw": "'a'", + "rawValue": "a", + }, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 21, + }, + "start": Position { + "column": 10, + "line": 21, + }, + }, + "start": 342, + "type": "StringLiteral", + "value": "a", + }, + "start": 336, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 14, + "line": 21, + }, + "start": Position { + "column": 4, + "line": 21, + }, + }, + "start": 336, + "type": "ExpressionStatement", + }, + ], + "directives": Array [], + "end": 350, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 22, + }, + "start": Position { + "column": 41, + "line": 20, + }, + }, + "start": 330, + "type": "BlockStatement", + }, + "end": 350, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 22, + }, + "start": Position { + "column": 2, + "line": 20, + }, + }, + "start": 291, + "test": Node { + "end": 328, + "left": Node { + "computed": false, + "end": 310, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 20, + }, + "start": Position { + "column": 6, + "line": 20, + }, + }, + "object": Node { + "end": 305, + "loc": SourceLocation { + "end": Position { + "column": 16, + "line": 20, + }, + "identifierName": "attributes", + "start": Position { + "column": 6, + "line": 20, + }, + }, + "name": "attributes", + "start": 295, + "type": "Identifier", + }, + "property": Node { + "end": 310, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 20, + }, + "identifierName": "href", + "start": Position { + "column": 17, + "line": 20, + }, + }, + "name": "href", + "start": 306, + "type": "Identifier", + }, + "start": 295, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 39, + "line": 20, + }, + "start": Position { + "column": 6, + "line": 20, + }, + }, + "operator": "&&", + "right": Node { + "end": 328, + "left": Node { + "end": 317, + "loc": SourceLocation { + "end": Position { + "column": 28, + "line": 20, + }, + "identifierName": "Tag", + "start": Position { + "column": 25, + "line": 20, + }, + }, + "name": "Tag", + "start": 314, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 39, + "line": 20, + }, + "start": Position { + "column": 25, + "line": 20, + }, + }, + "operator": "===", + "right": Node { + "end": 328, + "extra": Object { + "raw": "'span'", + "rawValue": "span", + }, + "loc": SourceLocation { + "end": Position { + "column": 39, + "line": 20, + }, + "start": Position { + "column": 33, + "line": 20, + }, + }, + "start": 322, + "type": "StringLiteral", + "value": "span", + }, + "start": 314, + "type": "BinaryExpression", + }, + "start": 295, + "type": "LogicalExpression", + }, + "type": "IfStatement", + }, + Node { + "argument": Node { + "children": Array [], + "closingElement": null, + "end": 410, + "extra": Object { + "parenStart": 361, + "parenthesized": true, + }, + "loc": SourceLocation { + "end": Position { + "column": 47, + "line": 25, + }, + "start": Position { + "column": 4, + "line": 25, + }, + }, + "openingElement": Node { + "attributes": Array [ + Node { + "argument": Node { + "end": 386, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 25, + }, + "identifierName": "attributes", + "start": Position { + "column": 13, + "line": 25, + }, + }, + "name": "attributes", + "start": 376, + "type": "Identifier", + }, + "end": 387, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 25, + }, + "start": Position { + "column": 9, + "line": 25, + }, + }, + "start": 372, + "type": "JSXSpreadAttribute", + }, + Node { + "end": 407, + "loc": SourceLocation { + "end": Position { + "column": 44, + "line": 25, + }, + "start": Position { + "column": 25, + "line": 25, + }, + }, + "name": Node { + "end": 397, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 25, + }, + "start": Position { + "column": 25, + "line": 25, + }, + }, + "name": "className", + "start": 388, + "type": "JSXIdentifier", + }, + "start": 388, + "type": "JSXAttribute", + "value": Node { + "end": 407, + "expression": Node { + "end": 406, + "loc": SourceLocation { + "end": Position { + "column": 43, + "line": 25, + }, + "identifierName": "classes", + "start": Position { + "column": 36, + "line": 25, + }, + }, + "name": "classes", + "start": 399, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 44, + "line": 25, + }, + "start": Position { + "column": 35, + "line": 25, + }, + }, + "start": 398, + "type": "JSXExpressionContainer", + }, + }, + ], + "end": 410, + "loc": SourceLocation { + "end": Position { + "column": 47, + "line": 25, + }, + "start": Position { + "column": 4, + "line": 25, + }, + }, + "name": Node { + "end": 371, + "loc": SourceLocation { + "end": Position { + "column": 8, + "line": 25, + }, + "start": Position { + "column": 5, + "line": 25, + }, + }, + "name": "Tag", + "start": 368, + "type": "JSXIdentifier", + }, + "selfClosing": true, + "start": 367, + "type": "JSXOpeningElement", + }, + "start": 367, + "type": "JSXElement", + }, + "end": 415, + "loc": SourceLocation { + "end": Position { + "column": 4, + "line": 26, + }, + "start": Position { + "column": 2, + "line": 24, + }, + }, + "start": 354, + "type": "ReturnStatement", + }, + ], + "directives": Array [], + "end": 417, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 27, + }, + "start": Position { + "column": 25, + "line": 12, + }, + }, + "start": 188, + "type": "BlockStatement", + }, + "end": 417, + "generator": false, + "id": null, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 27, + }, + "start": Position { + "column": 14, + "line": 12, + }, + }, + "params": Array [ + Node { + "end": 183, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 12, + }, + "identifierName": "props", + "start": Position { + "column": 15, + "line": 12, + }, + }, + "name": "props", + "start": 178, + "type": "Identifier", + }, + ], + "start": 177, + "type": "ArrowFunctionExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 27, + }, + "start": Position { + "column": 6, + "line": 12, + }, + }, + "start": 169, + "type": "VariableDeclarator", + }, + ], + "end": 418, + "kind": "const", + "loc": SourceLocation { + "end": Position { + "column": 2, + "line": 27, + }, + "start": Position { + "column": 0, + "line": 12, + }, + }, + "start": 163, + "type": "VariableDeclaration", + }, + Node { + "end": 448, + "expression": Node { + "end": 447, + "left": Node { + "computed": false, + "end": 435, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 29, + }, + "start": Position { + "column": 0, + "line": 29, + }, + }, + "object": Node { + "end": 425, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 29, + }, + "identifierName": "Badge", + "start": Position { + "column": 0, + "line": 29, + }, + }, + "name": "Badge", + "start": 420, + "type": "Identifier", + }, + "property": Node { + "end": 435, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 29, + }, + "identifierName": "propTypes", + "start": Position { + "column": 6, + "line": 29, + }, + }, + "name": "propTypes", + "start": 426, + "type": "Identifier", + }, + "start": 420, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 27, + "line": 29, + }, + "start": Position { + "column": 0, + "line": 29, + }, + }, + "operator": "=", + "right": Node { + "end": 447, + "loc": SourceLocation { + "end": Position { + "column": 27, + "line": 29, + }, + "identifierName": "propTypes", + "start": Position { + "column": 18, + "line": 29, + }, + }, + "name": "propTypes", + "start": 438, + "type": "Identifier", + }, + "start": 420, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 28, + "line": 29, + }, + "start": Position { + "column": 0, + "line": 29, + }, + }, + "start": 420, + "type": "ExpressionStatement", + }, + Node { + "end": 483, + "expression": Node { + "end": 482, + "left": Node { + "computed": false, + "end": 467, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 30, + }, + "start": Position { + "column": 0, + "line": 30, + }, + }, + "object": Node { + "end": 454, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 30, + }, + "identifierName": "Badge", + "start": Position { + "column": 0, + "line": 30, + }, + }, + "name": "Badge", + "start": 449, + "type": "Identifier", + }, + "property": Node { + "end": 467, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 30, + }, + "identifierName": "defaultProps", + "start": Position { + "column": 6, + "line": 30, + }, + }, + "name": "defaultProps", + "start": 455, + "type": "Identifier", + }, + "start": 449, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 33, + "line": 30, + }, + "start": Position { + "column": 0, + "line": 30, + }, + }, + "operator": "=", + "right": Node { + "end": 482, + "loc": SourceLocation { + "end": Position { + "column": 33, + "line": 30, + }, + "identifierName": "defaultProps", + "start": Position { + "column": 21, + "line": 30, + }, + }, + "name": "defaultProps", + "start": 470, + "type": "Identifier", + }, + "start": 449, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 30, + }, + "start": Position { + "column": 0, + "line": 30, + }, + }, + "start": 449, + "type": "ExpressionStatement", + }, + Node { + "declaration": Node { + "end": 505, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 32, + }, + "identifierName": "Badge", + "start": Position { + "column": 15, + "line": 32, + }, + }, + "name": "Badge", + "start": 500, + "type": "Identifier", + }, + "end": 506, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 32, + }, + "start": Position { + "column": 0, + "line": 32, + }, + }, + "start": 485, + "type": "ExportDefaultDeclaration", + }, + ], + "directives": Array [], + "end": 507, + "interpreter": null, + "loc": SourceLocation { + "end": Position { + "column": 0, + "line": 33, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "sourceType": "module", + "start": 0, + "type": "Program", + }, + "start": 0, + "type": "File", + }, +} +`; + +exports[`parser integration should allow to parse a react file with project-wide configuration file 1`] = ` +Object { + "format": "js", + "originFileName": "jsx-with-project-wide-config/src/Badge.js", + "rawContent": "import React from 'react'; +import PropTypes from 'prop-types'; + +const propTypes = { + color: PropTypes.string +}; + +const defaultProps = { + color: 'secondary', +}; + +const Badge = (props) => { + let { + color, + ...attributes + } = props; + + const classes = ['badge', 'badge-' + color]; + + if (attributes.href && Tag === 'span') { + Tag = 'a'; + } + + return ( + + ); +}; + +Badge.propTypes = propTypes; +Badge.defaultProps = defaultProps; + +export default Badge; +", + "root": Node { + "comments": Array [], + "end": 507, + "errors": Array [], + "loc": SourceLocation { + "end": Position { + "column": 0, + "line": 33, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "program": Node { + "body": Array [ + Node { + "end": 26, + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 1, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "source": Node { + "end": 25, + "extra": Object { + "raw": "'react'", + "rawValue": "react", + }, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 1, + }, + "start": Position { + "column": 18, + "line": 1, + }, + }, + "start": 18, + "type": "StringLiteral", + "value": "react", + }, + "specifiers": Array [ + Node { + "end": 12, + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 1, + }, + "start": Position { + "column": 7, + "line": 1, + }, + }, + "local": Node { + "end": 12, + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 1, + }, + "identifierName": "React", + "start": Position { + "column": 7, + "line": 1, + }, + }, + "name": "React", + "start": 7, + "type": "Identifier", + }, + "start": 7, + "type": "ImportDefaultSpecifier", + }, + ], + "start": 0, + "type": "ImportDeclaration", + }, + Node { + "end": 62, + "loc": SourceLocation { + "end": Position { + "column": 35, + "line": 2, + }, + "start": Position { + "column": 0, + "line": 2, + }, + }, + "source": Node { + "end": 61, + "extra": Object { + "raw": "'prop-types'", + "rawValue": "prop-types", + }, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 2, + }, + "start": Position { + "column": 22, + "line": 2, + }, + }, + "start": 49, + "type": "StringLiteral", + "value": "prop-types", + }, + "specifiers": Array [ + Node { + "end": 43, + "loc": SourceLocation { + "end": Position { + "column": 16, + "line": 2, + }, + "start": Position { + "column": 7, + "line": 2, + }, + }, + "local": Node { + "end": 43, + "loc": SourceLocation { + "end": Position { + "column": 16, + "line": 2, + }, + "identifierName": "PropTypes", + "start": Position { + "column": 7, + "line": 2, + }, + }, + "name": "PropTypes", + "start": 34, + "type": "Identifier", + }, + "start": 34, + "type": "ImportDefaultSpecifier", + }, + ], + "start": 27, + "type": "ImportDeclaration", + }, + Node { + "declarations": Array [ + Node { + "end": 111, + "id": Node { + "end": 79, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 4, + }, + "identifierName": "propTypes", + "start": Position { + "column": 6, + "line": 4, + }, + }, + "name": "propTypes", + "start": 70, + "type": "Identifier", + }, + "init": Node { + "end": 111, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 6, + }, + "start": Position { + "column": 18, + "line": 4, + }, + }, + "properties": Array [ + Node { + "computed": false, + "end": 109, + "key": Node { + "end": 91, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 5, + }, + "identifierName": "color", + "start": Position { + "column": 2, + "line": 5, + }, + }, + "name": "color", + "start": 86, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 5, + }, + "start": Position { + "column": 2, + "line": 5, + }, + }, + "method": false, + "shorthand": false, + "start": 86, + "type": "ObjectProperty", + "value": Node { + "computed": false, + "end": 109, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 5, + }, + "start": Position { + "column": 9, + "line": 5, + }, + }, + "object": Node { + "end": 102, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 5, + }, + "identifierName": "PropTypes", + "start": Position { + "column": 9, + "line": 5, + }, + }, + "name": "PropTypes", + "start": 93, + "type": "Identifier", + }, + "property": Node { + "end": 109, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 5, + }, + "identifierName": "string", + "start": Position { + "column": 19, + "line": 5, + }, + }, + "name": "string", + "start": 103, + "type": "Identifier", + }, + "start": 93, + "type": "MemberExpression", + }, + }, + ], + "start": 82, + "type": "ObjectExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 6, + }, + "start": Position { + "column": 6, + "line": 4, + }, + }, + "start": 70, + "type": "VariableDeclarator", + }, + ], + "end": 112, + "kind": "const", + "loc": SourceLocation { + "end": Position { + "column": 2, + "line": 6, + }, + "start": Position { + "column": 0, + "line": 4, + }, + }, + "start": 64, + "type": "VariableDeclaration", + }, + Node { + "declarations": Array [ + Node { + "end": 160, + "id": Node { + "end": 132, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 8, + }, + "identifierName": "defaultProps", + "start": Position { + "column": 6, + "line": 8, + }, + }, + "name": "defaultProps", + "start": 120, + "type": "Identifier", + }, + "init": Node { + "end": 160, + "extra": Object { + "trailingComma": 157, + }, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 10, + }, + "start": Position { + "column": 21, + "line": 8, + }, + }, + "properties": Array [ + Node { + "computed": false, + "end": 157, + "key": Node { + "end": 144, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 9, + }, + "identifierName": "color", + "start": Position { + "column": 2, + "line": 9, + }, + }, + "name": "color", + "start": 139, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 9, + }, + "start": Position { + "column": 2, + "line": 9, + }, + }, + "method": false, + "shorthand": false, + "start": 139, + "type": "ObjectProperty", + "value": Node { + "end": 157, + "extra": Object { + "raw": "'secondary'", + "rawValue": "secondary", + }, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 9, + }, + "start": Position { + "column": 9, + "line": 9, + }, + }, + "start": 146, + "type": "StringLiteral", + "value": "secondary", + }, + }, + ], + "start": 135, + "type": "ObjectExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 10, + }, + "start": Position { + "column": 6, + "line": 8, + }, + }, + "start": 120, + "type": "VariableDeclarator", + }, + ], + "end": 161, + "kind": "const", + "loc": SourceLocation { + "end": Position { + "column": 2, + "line": 10, + }, + "start": Position { + "column": 0, + "line": 8, + }, + }, + "start": 114, + "type": "VariableDeclaration", + }, + Node { + "declarations": Array [ + Node { + "end": 417, + "id": Node { + "end": 174, + "loc": SourceLocation { + "end": Position { + "column": 11, + "line": 12, + }, + "identifierName": "Badge", + "start": Position { + "column": 6, + "line": 12, + }, + }, + "name": "Badge", + "start": 169, + "type": "Identifier", + }, + "init": Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "declarations": Array [ + Node { + "end": 238, + "id": Node { + "end": 230, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 16, + }, + "start": Position { + "column": 6, + "line": 13, + }, + }, + "properties": Array [ + Node { + "computed": false, + "end": 207, + "extra": Object { + "shorthand": true, + }, + "key": Node { + "end": 207, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 14, + }, + "identifierName": "color", + "start": Position { + "column": 4, + "line": 14, + }, + }, + "name": "color", + "start": 202, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 14, + }, + "start": Position { + "column": 4, + "line": 14, + }, + }, + "method": false, + "shorthand": true, + "start": 202, + "type": "ObjectProperty", + "value": Node { + "end": 207, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 14, + }, + "identifierName": "color", + "start": Position { + "column": 4, + "line": 14, + }, + }, + "name": "color", + "start": 202, + "type": "Identifier", + }, + }, + Node { + "argument": Node { + "end": 226, + "loc": SourceLocation { + "end": Position { + "column": 17, + "line": 15, + }, + "identifierName": "attributes", + "start": Position { + "column": 7, + "line": 15, + }, + }, + "name": "attributes", + "start": 216, + "type": "Identifier", + }, + "end": 226, + "loc": SourceLocation { + "end": Position { + "column": 17, + "line": 15, + }, + "start": Position { + "column": 4, + "line": 15, + }, + }, + "start": 213, + "type": "RestElement", + }, + ], + "start": 196, + "type": "ObjectPattern", + }, + "init": Node { + "end": 238, + "loc": SourceLocation { + "end": Position { + "column": 11, + "line": 16, + }, + "identifierName": "props", + "start": Position { + "column": 6, + "line": 16, + }, + }, + "name": "props", + "start": 233, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 11, + "line": 16, + }, + "start": Position { + "column": 6, + "line": 13, + }, + }, + "start": 196, + "type": "VariableDeclarator", + }, + ], + "end": 239, + "kind": "let", + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 16, + }, + "start": Position { + "column": 2, + "line": 13, + }, + }, + "start": 192, + "type": "VariableDeclaration", + }, + Node { + "declarations": Array [ + Node { + "end": 286, + "id": Node { + "end": 256, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 18, + }, + "identifierName": "classes", + "start": Position { + "column": 8, + "line": 18, + }, + }, + "name": "classes", + "start": 249, + "type": "Identifier", + }, + "init": Node { + "elements": Array [ + Node { + "end": 267, + "extra": Object { + "raw": "'badge'", + "rawValue": "badge", + }, + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 18, + }, + "start": Position { + "column": 19, + "line": 18, + }, + }, + "start": 260, + "type": "StringLiteral", + "value": "badge", + }, + Node { + "end": 285, + "left": Node { + "end": 277, + "extra": Object { + "raw": "'badge-'", + "rawValue": "badge-", + }, + "loc": SourceLocation { + "end": Position { + "column": 36, + "line": 18, + }, + "start": Position { + "column": 28, + "line": 18, + }, + }, + "start": 269, + "type": "StringLiteral", + "value": "badge-", + }, + "loc": SourceLocation { + "end": Position { + "column": 44, + "line": 18, + }, + "start": Position { + "column": 28, + "line": 18, + }, + }, + "operator": "+", + "right": Node { + "end": 285, + "loc": SourceLocation { + "end": Position { + "column": 44, + "line": 18, + }, + "identifierName": "color", + "start": Position { + "column": 39, + "line": 18, + }, + }, + "name": "color", + "start": 280, + "type": "Identifier", + }, + "start": 269, + "type": "BinaryExpression", + }, + ], + "end": 286, + "loc": SourceLocation { + "end": Position { + "column": 45, + "line": 18, + }, + "start": Position { + "column": 18, + "line": 18, + }, + }, + "start": 259, + "type": "ArrayExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 45, + "line": 18, + }, + "start": Position { + "column": 8, + "line": 18, + }, + }, + "start": 249, + "type": "VariableDeclarator", + }, + ], + "end": 287, + "kind": "const", + "loc": SourceLocation { + "end": Position { + "column": 46, + "line": 18, + }, + "start": Position { + "column": 2, + "line": 18, + }, + }, + "start": 243, + "type": "VariableDeclaration", + }, + Node { + "alternate": null, + "consequent": Node { + "body": Array [ + Node { + "end": 346, + "expression": Node { + "end": 345, + "left": Node { + "end": 339, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 21, + }, + "identifierName": "Tag", + "start": Position { + "column": 4, + "line": 21, + }, + }, + "name": "Tag", + "start": 336, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 21, + }, + "start": Position { + "column": 4, + "line": 21, + }, + }, + "operator": "=", + "right": Node { + "end": 345, + "extra": Object { + "raw": "'a'", + "rawValue": "a", + }, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 21, + }, + "start": Position { + "column": 10, + "line": 21, + }, + }, + "start": 342, + "type": "StringLiteral", + "value": "a", + }, + "start": 336, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 14, + "line": 21, + }, + "start": Position { + "column": 4, + "line": 21, + }, + }, + "start": 336, + "type": "ExpressionStatement", + }, + ], + "directives": Array [], + "end": 350, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 22, + }, + "start": Position { + "column": 41, + "line": 20, + }, + }, + "start": 330, + "type": "BlockStatement", + }, + "end": 350, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 22, + }, + "start": Position { + "column": 2, + "line": 20, + }, + }, + "start": 291, + "test": Node { + "end": 328, + "left": Node { + "computed": false, + "end": 310, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 20, + }, + "start": Position { + "column": 6, + "line": 20, + }, + }, + "object": Node { + "end": 305, + "loc": SourceLocation { + "end": Position { + "column": 16, + "line": 20, + }, + "identifierName": "attributes", + "start": Position { + "column": 6, + "line": 20, + }, + }, + "name": "attributes", + "start": 295, + "type": "Identifier", + }, + "property": Node { + "end": 310, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 20, + }, + "identifierName": "href", + "start": Position { + "column": 17, + "line": 20, + }, + }, + "name": "href", + "start": 306, + "type": "Identifier", + }, + "start": 295, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 39, + "line": 20, + }, + "start": Position { + "column": 6, + "line": 20, + }, + }, + "operator": "&&", + "right": Node { + "end": 328, + "left": Node { + "end": 317, + "loc": SourceLocation { + "end": Position { + "column": 28, + "line": 20, + }, + "identifierName": "Tag", + "start": Position { + "column": 25, + "line": 20, + }, + }, + "name": "Tag", + "start": 314, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 39, + "line": 20, + }, + "start": Position { + "column": 25, + "line": 20, + }, + }, + "operator": "===", + "right": Node { + "end": 328, + "extra": Object { + "raw": "'span'", + "rawValue": "span", + }, + "loc": SourceLocation { + "end": Position { + "column": 39, + "line": 20, + }, + "start": Position { + "column": 33, + "line": 20, + }, + }, + "start": 322, + "type": "StringLiteral", + "value": "span", + }, + "start": 314, + "type": "BinaryExpression", + }, + "start": 295, + "type": "LogicalExpression", + }, + "type": "IfStatement", + }, + Node { + "argument": Node { + "children": Array [], + "closingElement": null, + "end": 410, + "extra": Object { + "parenStart": 361, + "parenthesized": true, + }, + "loc": SourceLocation { + "end": Position { + "column": 47, + "line": 25, + }, + "start": Position { + "column": 4, + "line": 25, + }, + }, + "openingElement": Node { + "attributes": Array [ + Node { + "argument": Node { + "end": 386, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 25, + }, + "identifierName": "attributes", + "start": Position { + "column": 13, + "line": 25, + }, + }, + "name": "attributes", + "start": 376, + "type": "Identifier", + }, + "end": 387, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 25, + }, + "start": Position { + "column": 9, + "line": 25, + }, + }, + "start": 372, + "type": "JSXSpreadAttribute", + }, + Node { + "end": 407, + "loc": SourceLocation { + "end": Position { + "column": 44, + "line": 25, + }, + "start": Position { + "column": 25, + "line": 25, + }, + }, + "name": Node { + "end": 397, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 25, + }, + "start": Position { + "column": 25, + "line": 25, + }, + }, + "name": "className", + "start": 388, + "type": "JSXIdentifier", + }, + "start": 388, + "type": "JSXAttribute", + "value": Node { + "end": 407, + "expression": Node { + "end": 406, + "loc": SourceLocation { + "end": Position { + "column": 43, + "line": 25, + }, + "identifierName": "classes", + "start": Position { + "column": 36, + "line": 25, + }, + }, + "name": "classes", + "start": 399, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 44, + "line": 25, + }, + "start": Position { + "column": 35, + "line": 25, + }, + }, + "start": 398, + "type": "JSXExpressionContainer", + }, + }, + ], + "end": 410, + "loc": SourceLocation { + "end": Position { + "column": 47, + "line": 25, + }, + "start": Position { + "column": 4, + "line": 25, + }, + }, + "name": Node { + "end": 371, + "loc": SourceLocation { + "end": Position { + "column": 8, + "line": 25, + }, + "start": Position { + "column": 5, + "line": 25, + }, + }, + "name": "Tag", + "start": 368, + "type": "JSXIdentifier", + }, + "selfClosing": true, + "start": 367, + "type": "JSXOpeningElement", + }, + "start": 367, + "type": "JSXElement", + }, + "end": 415, + "loc": SourceLocation { + "end": Position { + "column": 4, + "line": 26, + }, + "start": Position { + "column": 2, + "line": 24, + }, + }, + "start": 354, + "type": "ReturnStatement", + }, + ], + "directives": Array [], + "end": 417, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 27, + }, + "start": Position { + "column": 25, + "line": 12, + }, + }, + "start": 188, + "type": "BlockStatement", + }, + "end": 417, + "generator": false, + "id": null, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 27, + }, + "start": Position { + "column": 14, + "line": 12, + }, + }, + "params": Array [ + Node { + "end": 183, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 12, + }, + "identifierName": "props", + "start": Position { + "column": 15, + "line": 12, + }, + }, + "name": "props", + "start": 178, + "type": "Identifier", + }, + ], + "start": 177, + "type": "ArrowFunctionExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 27, + }, + "start": Position { + "column": 6, + "line": 12, + }, + }, + "start": 169, + "type": "VariableDeclarator", + }, + ], + "end": 418, + "kind": "const", + "loc": SourceLocation { + "end": Position { + "column": 2, + "line": 27, + }, + "start": Position { + "column": 0, + "line": 12, + }, + }, + "start": 163, + "type": "VariableDeclaration", + }, + Node { + "end": 448, + "expression": Node { + "end": 447, + "left": Node { + "computed": false, + "end": 435, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 29, + }, + "start": Position { + "column": 0, + "line": 29, + }, + }, + "object": Node { + "end": 425, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 29, + }, + "identifierName": "Badge", + "start": Position { + "column": 0, + "line": 29, + }, + }, + "name": "Badge", + "start": 420, + "type": "Identifier", + }, + "property": Node { + "end": 435, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 29, + }, + "identifierName": "propTypes", + "start": Position { + "column": 6, + "line": 29, + }, + }, + "name": "propTypes", + "start": 426, + "type": "Identifier", + }, + "start": 420, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 27, + "line": 29, + }, + "start": Position { + "column": 0, + "line": 29, + }, + }, + "operator": "=", + "right": Node { + "end": 447, + "loc": SourceLocation { + "end": Position { + "column": 27, + "line": 29, + }, + "identifierName": "propTypes", + "start": Position { + "column": 18, + "line": 29, + }, + }, + "name": "propTypes", + "start": 438, + "type": "Identifier", + }, + "start": 420, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 28, + "line": 29, + }, + "start": Position { + "column": 0, + "line": 29, + }, + }, + "start": 420, + "type": "ExpressionStatement", + }, + Node { + "end": 483, + "expression": Node { + "end": 482, + "left": Node { + "computed": false, + "end": 467, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 30, + }, + "start": Position { + "column": 0, + "line": 30, + }, + }, + "object": Node { + "end": 454, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 30, + }, + "identifierName": "Badge", + "start": Position { + "column": 0, + "line": 30, + }, + }, + "name": "Badge", + "start": 449, + "type": "Identifier", + }, + "property": Node { + "end": 467, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 30, + }, + "identifierName": "defaultProps", + "start": Position { + "column": 6, + "line": 30, + }, + }, + "name": "defaultProps", + "start": 455, + "type": "Identifier", + }, + "start": 449, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 33, + "line": 30, + }, + "start": Position { + "column": 0, + "line": 30, + }, + }, + "operator": "=", + "right": Node { + "end": 482, + "loc": SourceLocation { + "end": Position { + "column": 33, + "line": 30, + }, + "identifierName": "defaultProps", + "start": Position { + "column": 21, + "line": 30, + }, + }, + "name": "defaultProps", + "start": 470, + "type": "Identifier", + }, + "start": 449, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 30, + }, + "start": Position { + "column": 0, + "line": 30, + }, + }, + "start": 449, + "type": "ExpressionStatement", + }, + Node { + "declaration": Node { + "end": 505, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 32, + }, + "identifierName": "Badge", + "start": Position { + "column": 15, + "line": 32, + }, + }, + "name": "Badge", + "start": 500, + "type": "Identifier", + }, + "end": 506, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 32, + }, + "start": Position { + "column": 0, + "line": 32, + }, + }, + "start": 485, + "type": "ExportDefaultDeclaration", + }, + ], + "directives": Array [], + "end": 507, + "interpreter": null, + "loc": SourceLocation { + "end": Position { + "column": 0, + "line": 33, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "sourceType": "module", + "start": 0, + "type": "Program", + }, + "start": 0, + "type": "File", + }, +} +`; + +exports[`parser integration should allow to parse html with script tags 1`] = ` +Object { + "format": "html", + "originFileName": "index.html", + "rawContent": " + + + + + Document + + + + + + + +", + "root": Object { + "scripts": Array [ + Object { + "format": "js", + "originFileName": "index.html", + "rawContent": " + alert('hello there'); + ", + "root": Node { + "comments": Array [], + "end": 232, + "errors": Array [], + "loc": SourceLocation { + "end": Position { + "column": 4, + "line": 11, + }, + "start": Position { + "column": 12, + "line": 9, + }, + }, + "program": Node { + "body": Array [ + Node { + "end": 227, + "expression": Node { + "arguments": Array [ + Node { + "end": 225, + "extra": Object { + "raw": "'hello there'", + "rawValue": "hello there", + }, + "loc": SourceLocation { + "end": Position { + "column": 27, + "line": 10, + }, + "start": Position { + "column": 14, + "line": 10, + }, + }, + "start": 212, + "type": "StringLiteral", + "value": "hello there", + }, + ], + "callee": Node { + "end": 211, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 10, + }, + "identifierName": "alert", + "start": Position { + "column": 8, + "line": 26, + }, + }, + "name": "alert", + "start": 206, + "type": "Identifier", + }, + "end": 226, + "loc": SourceLocation { + "end": Position { + "column": 28, + "line": 10, + }, + "start": Position { + "column": 8, + "line": 26, + }, + }, + "start": 206, + "type": "CallExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 10, + }, + "start": Position { + "column": 8, + "line": 26, + }, + }, + "start": 206, + "type": "ExpressionStatement", + }, + ], + "directives": Array [], + "end": 232, + "interpreter": null, + "loc": SourceLocation { + "end": Position { + "column": 4, + "line": 11, + }, + "start": Position { + "column": 12, + "line": 9, + }, + }, + "sourceType": "module", + "start": 197, + "type": "Program", + }, + "start": 197, + "type": "File", + }, + }, + Object { + "format": "ts", + "originFileName": "index.html", + "rawContent": " + function fib(n: number) { + if (n == 0 || n == 1) { + return n; + } else { + return (f(n-1) + f(n-2)); + } + } + ", + "root": Node { + "comments": Array [], + "end": 452, + "errors": Array [], + "loc": SourceLocation { + "end": Position { + "column": 4, + "line": 21, + }, + "start": Position { + "column": 35, + "line": 13, + }, + }, + "program": Node { + "body": Array [ + Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "alternate": Node { + "body": Array [ + Node { + "argument": Node { + "end": 423, + "extra": Object { + "parenStart": 129, + "parenthesized": true, + }, + "left": Node { + "arguments": Array [ + Node { + "end": 413, + "left": Node { + "end": 411, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 18, + }, + "identifierName": "n", + "start": Position { + "column": 22, + "line": 30, + }, + }, + "name": "n", + "range": Array [ + 132, + 133, + ], + "start": 410, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 30, + }, + "start": Position { + "column": 22, + "line": 30, + }, + }, + "operator": "-", + "range": Array [ + 132, + 135, + ], + "right": Node { + "end": 413, + "extra": Object { + "raw": "1", + "rawValue": 1, + }, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 30, + }, + "start": Position { + "column": 24, + "line": 18, + }, + }, + "range": Array [ + 134, + 135, + ], + "start": 412, + "type": "NumericLiteral", + "value": 1, + }, + "start": 410, + "type": "BinaryExpression", + }, + ], + "callee": Node { + "end": 409, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 18, + }, + "identifierName": "f", + "start": Position { + "column": 20, + "line": 42, + }, + }, + "name": "f", + "range": Array [ + 130, + 131, + ], + "start": 408, + "type": "Identifier", + }, + "end": 414, + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 18, + }, + "start": Position { + "column": 20, + "line": 42, + }, + }, + "range": Array [ + 130, + 136, + ], + "start": 408, + "type": "CallExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 35, + "line": 30, + }, + "start": Position { + "column": 20, + "line": 42, + }, + }, + "operator": "+", + "range": Array [ + 130, + 145, + ], + "right": Node { + "arguments": Array [ + Node { + "end": 422, + "left": Node { + "end": 420, + "loc": SourceLocation { + "end": Position { + "column": 32, + "line": 18, + }, + "identifierName": "n", + "start": Position { + "column": 31, + "line": 30, + }, + }, + "name": "n", + "range": Array [ + 141, + 142, + ], + "start": 419, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 30, + }, + "start": Position { + "column": 31, + "line": 30, + }, + }, + "operator": "-", + "range": Array [ + 141, + 144, + ], + "right": Node { + "end": 422, + "extra": Object { + "raw": "2", + "rawValue": 2, + }, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 30, + }, + "start": Position { + "column": 33, + "line": 18, + }, + }, + "range": Array [ + 143, + 144, + ], + "start": 421, + "type": "NumericLiteral", + "value": 2, + }, + "start": 419, + "type": "BinaryExpression", + }, + ], + "callee": Node { + "end": 418, + "loc": SourceLocation { + "end": Position { + "column": 30, + "line": 18, + }, + "identifierName": "f", + "start": Position { + "column": 29, + "line": 30, + }, + }, + "name": "f", + "range": Array [ + 139, + 140, + ], + "start": 417, + "type": "Identifier", + }, + "end": 423, + "loc": SourceLocation { + "end": Position { + "column": 35, + "line": 30, + }, + "start": Position { + "column": 29, + "line": 30, + }, + }, + "range": Array [ + 139, + 145, + ], + "start": 417, + "type": "CallExpression", + }, + "start": 408, + "type": "BinaryExpression", + }, + "end": 425, + "loc": SourceLocation { + "end": Position { + "column": 37, + "line": 18, + }, + "start": Position { + "column": 12, + "line": 18, + }, + }, + "range": Array [ + 122, + 147, + ], + "start": 400, + "type": "ReturnStatement", + }, + ], + "directives": Array [], + "end": 437, + "loc": SourceLocation { + "end": Position { + "column": 11, + "line": 31, + }, + "start": Position { + "column": 17, + "line": 17, + }, + }, + "range": Array [ + 108, + 159, + ], + "start": 386, + "type": "BlockStatement", + }, + "consequent": Node { + "body": Array [ + Node { + "argument": Node { + "end": 367, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 16, + }, + "identifierName": "n", + "start": Position { + "column": 19, + "line": 16, + }, + }, + "name": "n", + "range": Array [ + 88, + 89, + ], + "start": 366, + "type": "Identifier", + }, + "end": 368, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 16, + }, + "start": Position { + "column": 12, + "line": 16, + }, + }, + "range": Array [ + 81, + 90, + ], + "start": 359, + "type": "ReturnStatement", + }, + ], + "directives": Array [], + "end": 380, + "loc": SourceLocation { + "end": Position { + "column": 11, + "line": 17, + }, + "start": Position { + "column": 32, + "line": 15, + }, + }, + "range": Array [ + 67, + 102, + ], + "start": 345, + "type": "BlockStatement", + }, + "end": 437, + "loc": SourceLocation { + "end": Position { + "column": 11, + "line": 31, + }, + "start": Position { + "column": 10, + "line": 15, + }, + }, + "range": Array [ + 45, + 159, + ], + "start": 323, + "test": Node { + "end": 343, + "left": Node { + "end": 333, + "left": Node { + "end": 328, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 15, + }, + "identifierName": "n", + "start": Position { + "column": 14, + "line": 39, + }, + }, + "name": "n", + "range": Array [ + 49, + 50, + ], + "start": 327, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 27, + }, + "start": Position { + "column": 14, + "line": 39, + }, + }, + "operator": "==", + "range": Array [ + 49, + 55, + ], + "right": Node { + "end": 333, + "extra": Object { + "raw": "0", + "rawValue": 0, + }, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 27, + }, + "start": Position { + "column": 19, + "line": 15, + }, + }, + "range": Array [ + 54, + 55, + ], + "start": 332, + "type": "NumericLiteral", + "value": 0, + }, + "start": 327, + "type": "BinaryExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 30, + "line": 39, + }, + "start": Position { + "column": 14, + "line": 39, + }, + }, + "operator": "||", + "range": Array [ + 49, + 65, + ], + "right": Node { + "end": 343, + "left": Node { + "end": 338, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 15, + }, + "identifierName": "n", + "start": Position { + "column": 24, + "line": 27, + }, + }, + "name": "n", + "range": Array [ + 59, + 60, + ], + "start": 337, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 30, + "line": 39, + }, + "start": Position { + "column": 24, + "line": 27, + }, + }, + "operator": "==", + "range": Array [ + 59, + 65, + ], + "right": Node { + "end": 343, + "extra": Object { + "raw": "1", + "rawValue": 1, + }, + "loc": SourceLocation { + "end": Position { + "column": 30, + "line": 39, + }, + "start": Position { + "column": 29, + "line": 15, + }, + }, + "range": Array [ + 64, + 65, + ], + "start": 342, + "type": "NumericLiteral", + "value": 1, + }, + "start": 337, + "type": "BinaryExpression", + }, + "start": 327, + "type": "LogicalExpression", + }, + "type": "IfStatement", + }, + ], + "directives": Array [], + "end": 447, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 32, + }, + "start": Position { + "column": 32, + "line": 14, + }, + }, + "range": Array [ + 33, + 169, + ], + "start": 311, + "type": "BlockStatement", + }, + "end": 447, + "generator": false, + "id": Node { + "end": 299, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 14, + }, + "identifierName": "fib", + "start": Position { + "column": 17, + "line": 14, + }, + }, + "name": "fib", + "range": Array [ + 18, + 21, + ], + "start": 296, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 32, + }, + "start": Position { + "column": 8, + "line": 14, + }, + }, + "params": Array [ + Node { + "end": 309, + "loc": SourceLocation { + "end": Position { + "column": 30, + "line": 38, + }, + "identifierName": "n", + "start": Position { + "column": 21, + "line": 14, + }, + }, + "name": "n", + "range": Array [ + 22, + 31, + ], + "start": 300, + "type": "Identifier", + "typeAnnotation": Node { + "end": 309, + "loc": SourceLocation { + "end": Position { + "column": 30, + "line": 38, + }, + "start": Position { + "column": 22, + "line": 14, + }, + }, + "range": Array [ + 23, + 31, + ], + "start": 301, + "type": "TSTypeAnnotation", + "typeAnnotation": Node { + "end": 309, + "loc": SourceLocation { + "end": Position { + "column": 30, + "line": 38, + }, + "start": Position { + "column": 24, + "line": 14, + }, + }, + "range": Array [ + 25, + 31, + ], + "start": 303, + "type": "TSNumberKeyword", + }, + }, + }, + ], + "range": Array [ + 9, + 169, + ], + "start": 287, + "type": "FunctionDeclaration", + }, + ], + "directives": Array [], + "end": 452, + "interpreter": null, + "loc": SourceLocation { + "end": Position { + "column": 4, + "line": 21, + }, + "start": Position { + "column": 35, + "line": 13, + }, + }, + "range": Array [ + 0, + 174, + ], + "sourceType": "module", + "start": 278, + "type": "Program", + }, + "range": Array [ + 0, + 174, + ], + "start": 278, + "type": "File", + }, + }, + ], + }, +} +`; + +exports[`parsers integration should allow a plugin that conflicts with the default plugins as long as plugins are emptied out 1`] = ` +Object { + "format": "js", + "originFileName": "js-in-babel-project/src/app.js", + "rawContent": "class App {} +", + "root": Node { + "comments": Array [], + "end": 13, + "errors": Array [], + "loc": SourceLocation { + "end": Position { + "column": 0, + "line": 2, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "program": Node { + "body": Array [ + Node { + "body": Node { + "body": Array [], + "end": 12, + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 1, + }, + "start": Position { + "column": 10, + "line": 1, + }, + }, + "start": 10, + "type": "ClassBody", + }, + "end": 12, + "id": Node { + "end": 9, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 1, + }, + "identifierName": "App", + "start": Position { + "column": 6, + "line": 1, + }, + }, + "name": "App", + "start": 6, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 1, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "start": 0, + "superClass": null, + "type": "ClassDeclaration", + }, + ], + "directives": Array [], + "end": 13, + "interpreter": null, + "loc": SourceLocation { + "end": Position { + "column": 0, + "line": 2, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "sourceType": "module", + "start": 0, + "type": "Program", + }, + "start": 0, + "type": "File", + }, +} +`; + +exports[`parsers integration should allow custom babel config to override default options when overriding plugins 1`] = ` +Object { + "format": "js", + "originFileName": "js-in-babel-project/src/app.js", + "rawContent": "class App {} +", + "root": Node { + "comments": Array [], + "end": 13, + "errors": Array [], + "loc": SourceLocation { + "end": Position { + "column": 0, + "line": 2, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "program": Node { + "body": Array [ + Node { + "body": Node { + "body": Array [], + "end": 12, + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 1, + }, + "start": Position { + "column": 10, + "line": 1, + }, + }, + "start": 10, + "type": "ClassBody", + }, + "end": 12, + "id": Node { + "end": 9, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 1, + }, + "identifierName": "App", + "start": Position { + "column": 6, + "line": 1, + }, + }, + "name": "App", + "start": 6, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 1, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "start": 0, + "superClass": null, + "type": "ClassDeclaration", + }, + ], + "directives": Array [], + "end": 13, + "interpreter": null, + "loc": SourceLocation { + "end": Position { + "column": 0, + "line": 2, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "sourceType": "module", + "start": 0, + "type": "Program", + }, + "start": 0, + "type": "File", + }, +} +`; + +exports[`parsers integration should allow to parse a *.vue file 1`] = ` +Object { + "format": "html", + "originFileName": "App.vue", + "rawContent": " + + + + +", + "root": Object { + "scripts": Array [ + Object { + "format": "js", + "originFileName": "App.vue", + "rawContent": " +import PokemonComponent from './Pokemon.vue' +import { pokemonService } from './pokemon.service'; + +export default { + components: { + PokemonComponent + }, + data() { + return { + pokemon: [] + } + }, + + created() { + pokemonService.getAll().then(pokemon => (this.pokemon = pokemon)); + } +} +", + "root": Node { + "comments": Array [], + "end": 490, + "errors": Array [], + "loc": SourceLocation { + "end": Position { + "column": 0, + "line": 26, + }, + "start": Position { + "column": 8, + "line": 8, + }, + }, + "program": Node { + "body": Array [ + Node { + "end": 232, + "loc": SourceLocation { + "end": Position { + "column": 44, + "line": 16, + }, + "start": Position { + "column": 0, + "line": 9, + }, + }, + "source": Node { + "end": 232, + "extra": Object { + "raw": "'./Pokemon.vue'", + "rawValue": "./Pokemon.vue", + }, + "loc": SourceLocation { + "end": Position { + "column": 44, + "line": 16, + }, + "start": Position { + "column": 29, + "line": 9, + }, + }, + "start": 217, + "type": "StringLiteral", + "value": "./Pokemon.vue", + }, + "specifiers": Array [ + Node { + "end": 211, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 16, + }, + "start": Position { + "column": 7, + "line": 16, + }, + }, + "local": Node { + "end": 211, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 16, + }, + "identifierName": "PokemonComponent", + "start": Position { + "column": 7, + "line": 16, + }, + }, + "name": "PokemonComponent", + "start": 195, + "type": "Identifier", + }, + "start": 195, + "type": "ImportDefaultSpecifier", + }, + ], + "start": 188, + "type": "ImportDeclaration", + }, + Node { + "end": 284, + "loc": SourceLocation { + "end": Position { + "column": 51, + "line": 10, + }, + "start": Position { + "column": 0, + "line": 10, + }, + }, + "source": Node { + "end": 283, + "extra": Object { + "raw": "'./pokemon.service'", + "rawValue": "./pokemon.service", + }, + "loc": SourceLocation { + "end": Position { + "column": 50, + "line": 10, + }, + "start": Position { + "column": 31, + "line": 10, + }, + }, + "start": 264, + "type": "StringLiteral", + "value": "./pokemon.service", + }, + "specifiers": Array [ + Node { + "end": 256, + "imported": Node { + "end": 256, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 24, + }, + "identifierName": "pokemonService", + "start": Position { + "column": 9, + "line": 24, + }, + }, + "name": "pokemonService", + "start": 242, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 24, + }, + "start": Position { + "column": 9, + "line": 24, + }, + }, + "local": Node { + "end": 256, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 24, + }, + "identifierName": "pokemonService", + "start": Position { + "column": 9, + "line": 24, + }, + }, + "name": "pokemonService", + "start": 242, + "type": "Identifier", + }, + "start": 242, + "type": "ImportSpecifier", + }, + ], + "start": 233, + "type": "ImportDeclaration", + }, + Node { + "declaration": Node { + "end": 489, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 32, + }, + "start": Position { + "column": 15, + "line": 12, + }, + }, + "properties": Array [ + Node { + "computed": false, + "end": 343, + "key": Node { + "end": 315, + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 13, + }, + "identifierName": "components", + "start": Position { + "column": 2, + "line": 20, + }, + }, + "name": "components", + "start": 305, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 22, + }, + "start": Position { + "column": 2, + "line": 20, + }, + }, + "method": false, + "shorthand": false, + "start": 305, + "type": "ObjectProperty", + "value": Node { + "end": 343, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 22, + }, + "start": Position { + "column": 14, + "line": 13, + }, + }, + "properties": Array [ + Node { + "computed": false, + "end": 339, + "extra": Object { + "shorthand": true, + }, + "key": Node { + "end": 339, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 28, + }, + "identifierName": "PokemonComponent", + "start": Position { + "column": 4, + "line": 28, + }, + }, + "name": "PokemonComponent", + "start": 323, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 28, + }, + "start": Position { + "column": 4, + "line": 28, + }, + }, + "method": false, + "shorthand": true, + "start": 323, + "type": "ObjectProperty", + "value": Node { + "end": 339, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 28, + }, + "identifierName": "PokemonComponent", + "start": Position { + "column": 4, + "line": 28, + }, + }, + "name": "PokemonComponent", + "start": 323, + "type": "Identifier", + }, + }, + ], + "start": 317, + "type": "ObjectExpression", + }, + }, + Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "argument": Node { + "end": 392, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 26, + }, + "start": Position { + "column": 11, + "line": 17, + }, + }, + "properties": Array [ + Node { + "computed": false, + "end": 386, + "key": Node { + "end": 382, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 18, + }, + "identifierName": "pokemon", + "start": Position { + "column": 6, + "line": 25, + }, + }, + "name": "pokemon", + "start": 375, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 17, + "line": 25, + }, + "start": Position { + "column": 6, + "line": 25, + }, + }, + "method": false, + "shorthand": false, + "start": 375, + "type": "ObjectProperty", + "value": Node { + "elements": Array [], + "end": 386, + "loc": SourceLocation { + "end": Position { + "column": 17, + "line": 25, + }, + "start": Position { + "column": 15, + "line": 18, + }, + }, + "start": 384, + "type": "ArrayExpression", + }, + }, + ], + "start": 367, + "type": "ObjectExpression", + }, + "end": 392, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 26, + }, + "start": Position { + "column": 4, + "line": 17, + }, + }, + "start": 360, + "type": "ReturnStatement", + }, + ], + "directives": Array [], + "end": 396, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 27, + }, + "start": Position { + "column": 9, + "line": 16, + }, + }, + "start": 354, + "type": "BlockStatement", + }, + "computed": false, + "end": 396, + "generator": false, + "id": null, + "key": Node { + "end": 351, + "loc": SourceLocation { + "end": Position { + "column": 6, + "line": 16, + }, + "identifierName": "data", + "start": Position { + "column": 2, + "line": 23, + }, + }, + "name": "data", + "start": 347, + "type": "Identifier", + }, + "kind": "method", + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 27, + }, + "start": Position { + "column": 2, + "line": 23, + }, + }, + "method": true, + "params": Array [], + "start": 347, + "type": "ObjectMethod", + }, + Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "end": 483, + "expression": Node { + "arguments": Array [ + Node { + "async": false, + "body": Node { + "end": 480, + "extra": Object { + "parenStart": 270, + "parenthesized": true, + }, + "left": Node { + "computed": false, + "end": 470, + "loc": SourceLocation { + "end": Position { + "column": 57, + "line": 30, + }, + "start": Position { + "column": 45, + "line": 37, + }, + }, + "object": Node { + "end": 462, + "loc": SourceLocation { + "end": Position { + "column": 49, + "line": 23, + }, + "start": Position { + "column": 45, + "line": 37, + }, + }, + "start": 458, + "type": "ThisExpression", + }, + "property": Node { + "end": 470, + "loc": SourceLocation { + "end": Position { + "column": 57, + "line": 30, + }, + "identifierName": "pokemon", + "start": Position { + "column": 50, + "line": 23, + }, + }, + "name": "pokemon", + "start": 463, + "type": "Identifier", + }, + "start": 458, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 67, + "line": 30, + }, + "start": Position { + "column": 45, + "line": 37, + }, + }, + "operator": "=", + "right": Node { + "end": 480, + "loc": SourceLocation { + "end": Position { + "column": 67, + "line": 30, + }, + "identifierName": "pokemon", + "start": Position { + "column": 60, + "line": 23, + }, + }, + "name": "pokemon", + "start": 473, + "type": "Identifier", + }, + "start": 458, + "type": "AssignmentExpression", + }, + "end": 481, + "generator": false, + "id": null, + "loc": SourceLocation { + "end": Position { + "column": 68, + "line": 23, + }, + "start": Position { + "column": 33, + "line": 30, + }, + }, + "params": Array [ + Node { + "end": 453, + "loc": SourceLocation { + "end": Position { + "column": 40, + "line": 23, + }, + "identifierName": "pokemon", + "start": Position { + "column": 33, + "line": 30, + }, + }, + "name": "pokemon", + "start": 446, + "type": "Identifier", + }, + ], + "start": 446, + "type": "ArrowFunctionExpression", + }, + ], + "callee": Node { + "computed": false, + "end": 445, + "loc": SourceLocation { + "end": Position { + "column": 32, + "line": 30, + }, + "start": Position { + "column": 4, + "line": 58, + }, + }, + "object": Node { + "arguments": Array [], + "callee": Node { + "computed": false, + "end": 438, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 30, + }, + "start": Position { + "column": 4, + "line": 58, + }, + }, + "object": Node { + "end": 431, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 23, + }, + "identifierName": "pokemonService", + "start": Position { + "column": 4, + "line": 58, + }, + }, + "name": "pokemonService", + "start": 417, + "type": "Identifier", + }, + "property": Node { + "end": 438, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 30, + }, + "identifierName": "getAll", + "start": Position { + "column": 19, + "line": 23, + }, + }, + "name": "getAll", + "start": 432, + "type": "Identifier", + }, + "start": 417, + "type": "MemberExpression", + }, + "end": 440, + "loc": SourceLocation { + "end": Position { + "column": 27, + "line": 23, + }, + "start": Position { + "column": 4, + "line": 58, + }, + }, + "start": 417, + "type": "CallExpression", + }, + "property": Node { + "end": 445, + "loc": SourceLocation { + "end": Position { + "column": 32, + "line": 30, + }, + "identifierName": "then", + "start": Position { + "column": 28, + "line": 23, + }, + }, + "name": "then", + "start": 441, + "type": "Identifier", + }, + "start": 417, + "type": "MemberExpression", + }, + "end": 482, + "loc": SourceLocation { + "end": Position { + "column": 69, + "line": 23, + }, + "start": Position { + "column": 4, + "line": 58, + }, + }, + "start": 417, + "type": "CallExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 70, + "line": 23, + }, + "start": Position { + "column": 4, + "line": 58, + }, + }, + "start": 417, + "type": "ExpressionStatement", + }, + ], + "directives": Array [], + "end": 487, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 31, + }, + "start": Position { + "column": 12, + "line": 22, + }, + }, + "start": 411, + "type": "BlockStatement", + }, + "computed": false, + "end": 487, + "generator": false, + "id": null, + "key": Node { + "end": 408, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 22, + }, + "identifierName": "created", + "start": Position { + "column": 2, + "line": 29, + }, + }, + "name": "created", + "start": 401, + "type": "Identifier", + }, + "kind": "method", + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 31, + }, + "start": Position { + "column": 2, + "line": 29, + }, + }, + "method": true, + "params": Array [], + "start": 401, + "type": "ObjectMethod", + }, + ], + "start": 301, + "type": "ObjectExpression", + }, + "end": 489, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 32, + }, + "start": Position { + "column": 0, + "line": 12, + }, + }, + "start": 286, + "type": "ExportDefaultDeclaration", + }, + ], + "directives": Array [], + "end": 490, + "interpreter": null, + "loc": SourceLocation { + "end": Position { + "column": 0, + "line": 26, + }, + "start": Position { + "column": 8, + "line": 8, + }, + }, + "sourceType": "module", + "start": 187, + "type": "Program", + }, + "start": 187, + "type": "File", + }, + }, + ], + }, +} +`; + +exports[`parsers integration should allow to parse a an angular file 1`] = ` +Object { + "format": "ts", + "originFileName": "app.component.ts", + "rawContent": "import { Component } from '@angular/core'; + +@Component({ + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.scss'] +}) +export class AppComponent { + title = 'angular-app'; +} +", + "root": Node { + "comments": Array [], + "end": 216, + "errors": Array [], + "loc": SourceLocation { + "end": Position { + "column": 0, + "line": 11, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "program": Node { + "body": Array [ + Node { + "end": 42, + "importKind": "value", + "loc": SourceLocation { + "end": Position { + "column": 42, + "line": 1, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 42, + ], + "source": Node { + "end": 41, + "extra": Object { + "raw": "'@angular/core'", + "rawValue": "@angular/core", + }, + "loc": SourceLocation { + "end": Position { + "column": 41, + "line": 1, + }, + "start": Position { + "column": 26, + "line": 1, + }, + }, + "range": Array [ + 26, + 41, + ], + "start": 26, + "type": "StringLiteral", + "value": "@angular/core", + }, + "specifiers": Array [ + Node { + "end": 18, + "imported": Node { + "end": 18, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 1, + }, + "identifierName": "Component", + "start": Position { + "column": 9, + "line": 1, + }, + }, + "name": "Component", + "range": Array [ + 9, + 18, + ], + "start": 9, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 1, + }, + "start": Position { + "column": 9, + "line": 1, + }, + }, + "local": Node { + "end": 18, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 1, + }, + "identifierName": "Component", + "start": Position { + "column": 9, + "line": 1, + }, + }, + "name": "Component", + "range": Array [ + 9, + 18, + ], + "start": 9, + "type": "Identifier", + }, + "range": Array [ + 9, + 18, + ], + "start": 9, + "type": "ImportSpecifier", + }, + ], + "start": 0, + "type": "ImportDeclaration", + }, + Node { + "declaration": Node { + "body": Node { + "body": Array [ + Node { + "computed": false, + "end": 213, + "key": Node { + "end": 196, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 9, + }, + "identifierName": "title", + "start": Position { + "column": 2, + "line": 9, + }, + }, + "name": "title", + "range": Array [ + 191, + 196, + ], + "start": 191, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 9, + }, + "start": Position { + "column": 2, + "line": 9, + }, + }, + "range": Array [ + 191, + 213, + ], + "start": 191, + "static": false, + "type": "ClassProperty", + "value": Node { + "end": 212, + "extra": Object { + "raw": "'angular-app'", + "rawValue": "angular-app", + }, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 9, + }, + "start": Position { + "column": 10, + "line": 9, + }, + }, + "range": Array [ + 199, + 212, + ], + "start": 199, + "type": "StringLiteral", + "value": "angular-app", + }, + }, + ], + "end": 215, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 10, + }, + "start": Position { + "column": 26, + "line": 8, + }, + }, + "range": Array [ + 187, + 215, + ], + "start": 187, + "type": "ClassBody", + }, + "decorators": Array [ + Node { + "end": 160, + "expression": Node { + "arguments": Array [ + Node { + "end": 159, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 7, + }, + "start": Position { + "column": 11, + "line": 3, + }, + }, + "properties": Array [ + Node { + "computed": false, + "end": 79, + "key": Node { + "end": 67, + "loc": SourceLocation { + "end": Position { + "column": 10, + "line": 4, + }, + "identifierName": "selector", + "start": Position { + "column": 2, + "line": 4, + }, + }, + "name": "selector", + "range": Array [ + 59, + 67, + ], + "start": 59, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 4, + }, + "start": Position { + "column": 2, + "line": 4, + }, + }, + "method": false, + "range": Array [ + 59, + 79, + ], + "shorthand": false, + "start": 59, + "type": "ObjectProperty", + "value": Node { + "end": 79, + "extra": Object { + "raw": "'app-root'", + "rawValue": "app-root", + }, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 4, + }, + "start": Position { + "column": 12, + "line": 4, + }, + }, + "range": Array [ + 69, + 79, + ], + "start": 69, + "type": "StringLiteral", + "value": "app-root", + }, + }, + Node { + "computed": false, + "end": 118, + "key": Node { + "end": 94, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 5, + }, + "identifierName": "templateUrl", + "start": Position { + "column": 2, + "line": 5, + }, + }, + "name": "templateUrl", + "range": Array [ + 83, + 94, + ], + "start": 83, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 37, + "line": 5, + }, + "start": Position { + "column": 2, + "line": 5, + }, + }, + "method": false, + "range": Array [ + 83, + 118, + ], + "shorthand": false, + "start": 83, + "type": "ObjectProperty", + "value": Node { + "end": 118, + "extra": Object { + "raw": "'./app.component.html'", + "rawValue": "./app.component.html", + }, + "loc": SourceLocation { + "end": Position { + "column": 37, + "line": 5, + }, + "start": Position { + "column": 15, + "line": 5, + }, + }, + "range": Array [ + 96, + 118, + ], + "start": 96, + "type": "StringLiteral", + "value": "./app.component.html", + }, + }, + Node { + "computed": false, + "end": 157, + "key": Node { + "end": 131, + "loc": SourceLocation { + "end": Position { + "column": 11, + "line": 6, + }, + "identifierName": "styleUrls", + "start": Position { + "column": 2, + "line": 6, + }, + }, + "name": "styleUrls", + "range": Array [ + 122, + 131, + ], + "start": 122, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 37, + "line": 6, + }, + "start": Position { + "column": 2, + "line": 6, + }, + }, + "method": false, + "range": Array [ + 122, + 157, + ], + "shorthand": false, + "start": 122, + "type": "ObjectProperty", + "value": Node { + "elements": Array [ + Node { + "end": 156, + "extra": Object { + "raw": "'./app.component.scss'", + "rawValue": "./app.component.scss", + }, + "loc": SourceLocation { + "end": Position { + "column": 36, + "line": 6, + }, + "start": Position { + "column": 14, + "line": 6, + }, + }, + "range": Array [ + 134, + 156, + ], + "start": 134, + "type": "StringLiteral", + "value": "./app.component.scss", + }, + ], + "end": 157, + "loc": SourceLocation { + "end": Position { + "column": 37, + "line": 6, + }, + "start": Position { + "column": 13, + "line": 6, + }, + }, + "range": Array [ + 133, + 157, + ], + "start": 133, + "type": "ArrayExpression", + }, + }, + ], + "range": Array [ + 55, + 159, + ], + "start": 55, + "type": "ObjectExpression", + }, + ], + "callee": Node { + "end": 54, + "loc": SourceLocation { + "end": Position { + "column": 10, + "line": 3, + }, + "identifierName": "Component", + "start": Position { + "column": 1, + "line": 3, + }, + }, + "name": "Component", + "range": Array [ + 45, + 54, + ], + "start": 45, + "type": "Identifier", + }, + "end": 160, + "loc": SourceLocation { + "end": Position { + "column": 2, + "line": 7, + }, + "start": Position { + "column": 1, + "line": 3, + }, + }, + "range": Array [ + 45, + 160, + ], + "start": 45, + "type": "CallExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 2, + "line": 7, + }, + "start": Position { + "column": 0, + "line": 3, + }, + }, + "range": Array [ + 44, + 160, + ], + "start": 44, + "type": "Decorator", + }, + ], + "end": 215, + "id": Node { + "end": 186, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 8, + }, + "identifierName": "AppComponent", + "start": Position { + "column": 13, + "line": 8, + }, + }, + "name": "AppComponent", + "range": Array [ + 174, + 186, + ], + "start": 174, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 10, + }, + "start": Position { + "column": 0, + "line": 3, + }, + }, + "range": Array [ + 44, + 215, + ], + "start": 44, + "superClass": null, + "type": "ClassDeclaration", + }, + "end": 215, + "exportKind": "value", + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 10, + }, + "start": Position { + "column": 0, + "line": 8, + }, + }, + "range": Array [ + 161, + 215, + ], + "source": null, + "specifiers": Array [], + "start": 161, + "type": "ExportNamedDeclaration", + }, + ], + "directives": Array [], + "end": 216, + "interpreter": null, + "loc": SourceLocation { + "end": Position { + "column": 0, + "line": 11, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 216, + ], + "sourceType": "module", + "start": 0, + "type": "Program", + }, + "range": Array [ + 0, + 216, + ], + "start": 0, + "type": "File", + }, +} +`; + +exports[`parsers integration should allow to parse a cjs file 1`] = ` +Object { + "format": "js", + "originFileName": "app.cjs", + "rawContent": "module.exports = class App {}", + "root": Node { + "comments": Array [], + "end": 29, + "errors": Array [], + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 1, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "program": Node { + "body": Array [ + Node { + "end": 29, + "expression": Node { + "end": 29, + "left": Node { + "computed": false, + "end": 14, + "loc": SourceLocation { + "end": Position { + "column": 14, + "line": 1, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "object": Node { + "end": 6, + "loc": SourceLocation { + "end": Position { + "column": 6, + "line": 1, + }, + "identifierName": "module", + "start": Position { + "column": 0, + "line": 1, + }, + }, + "name": "module", + "start": 0, + "type": "Identifier", + }, + "property": Node { + "end": 14, + "loc": SourceLocation { + "end": Position { + "column": 14, + "line": 1, + }, + "identifierName": "exports", + "start": Position { + "column": 7, + "line": 1, + }, + }, + "name": "exports", + "start": 7, + "type": "Identifier", + }, + "start": 0, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 1, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "operator": "=", + "right": Node { + "body": Node { + "body": Array [], + "end": 29, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 1, + }, + "start": Position { + "column": 27, + "line": 1, + }, + }, + "start": 27, + "type": "ClassBody", + }, + "end": 29, + "id": Node { + "end": 26, + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 1, + }, + "identifierName": "App", + "start": Position { + "column": 23, + "line": 1, + }, + }, + "name": "App", + "start": 23, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 1, + }, + "start": Position { + "column": 17, + "line": 1, + }, + }, + "start": 17, + "superClass": null, + "type": "ClassExpression", + }, + "start": 0, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 1, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "start": 0, + "type": "ExpressionStatement", + }, + ], + "directives": Array [], + "end": 29, + "interpreter": null, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 1, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "sourceType": "module", + "start": 0, + "type": "Program", + }, + "start": 0, + "type": "File", + }, +} +`; + +exports[`parsers integration should allow to parse a mjs file 1`] = ` +Object { + "format": "js", + "originFileName": "app.mjs", + "rawContent": "export class App {}", + "root": Node { + "comments": Array [], + "end": 19, + "errors": Array [], + "loc": SourceLocation { + "end": Position { + "column": 19, + "line": 1, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "program": Node { + "body": Array [ + Node { + "declaration": Node { + "body": Node { + "body": Array [], + "end": 19, + "loc": SourceLocation { + "end": Position { + "column": 19, + "line": 1, + }, + "start": Position { + "column": 17, + "line": 1, + }, + }, + "start": 17, + "type": "ClassBody", + }, + "end": 19, + "id": Node { + "end": 16, + "loc": SourceLocation { + "end": Position { + "column": 16, + "line": 1, + }, + "identifierName": "App", + "start": Position { + "column": 13, + "line": 1, + }, + }, + "name": "App", + "start": 13, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 19, + "line": 1, + }, + "start": Position { + "column": 7, + "line": 1, + }, + }, + "start": 7, + "superClass": null, + "type": "ClassDeclaration", + }, + "end": 19, + "loc": SourceLocation { + "end": Position { + "column": 19, + "line": 1, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "source": null, + "specifiers": Array [], + "start": 0, + "type": "ExportNamedDeclaration", + }, + ], + "directives": Array [], + "end": 19, + "interpreter": null, + "loc": SourceLocation { + "end": Position { + "column": 19, + "line": 1, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "sourceType": "module", + "start": 0, + "type": "Program", + }, + "start": 0, + "type": "File", + }, +} +`; + +exports[`parsers integration should allow to parse a react file with custom babelrc file 1`] = ` +Object { + "format": "js", + "originFileName": "jsx-with-babelrc/Badge.js", + "rawContent": "import React from 'react'; +import PropTypes from 'prop-types'; + +const propTypes = { + color: PropTypes.string +}; + +const defaultProps = { + color: 'secondary', +}; + +const Badge = (props) => { + let { + color, + ...attributes + } = props; + + const classes = ['badge', 'badge-' + color]; + + if (attributes.href && Tag === 'span') { + Tag = 'a'; + } + + return ( + + ); +}; + +Badge.propTypes = propTypes; +Badge.defaultProps = defaultProps; + +export default Badge; +", + "root": Node { + "comments": Array [], + "end": 507, + "errors": Array [], + "loc": SourceLocation { + "end": Position { + "column": 0, + "line": 33, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "program": Node { + "body": Array [ + Node { + "end": 26, + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 1, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "source": Node { + "end": 25, + "extra": Object { + "raw": "'react'", + "rawValue": "react", + }, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 1, + }, + "start": Position { + "column": 18, + "line": 1, + }, + }, + "start": 18, + "type": "StringLiteral", + "value": "react", + }, + "specifiers": Array [ + Node { + "end": 12, + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 1, + }, + "start": Position { + "column": 7, + "line": 1, + }, + }, + "local": Node { + "end": 12, + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 1, + }, + "identifierName": "React", + "start": Position { + "column": 7, + "line": 1, + }, + }, + "name": "React", + "start": 7, + "type": "Identifier", + }, + "start": 7, + "type": "ImportDefaultSpecifier", + }, + ], + "start": 0, + "type": "ImportDeclaration", + }, + Node { + "end": 62, + "loc": SourceLocation { + "end": Position { + "column": 35, + "line": 2, + }, + "start": Position { + "column": 0, + "line": 2, + }, + }, + "source": Node { + "end": 61, + "extra": Object { + "raw": "'prop-types'", + "rawValue": "prop-types", + }, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 2, + }, + "start": Position { + "column": 22, + "line": 2, + }, + }, + "start": 49, + "type": "StringLiteral", + "value": "prop-types", + }, + "specifiers": Array [ + Node { + "end": 43, + "loc": SourceLocation { + "end": Position { + "column": 16, + "line": 2, + }, + "start": Position { + "column": 7, + "line": 2, + }, + }, + "local": Node { + "end": 43, + "loc": SourceLocation { + "end": Position { + "column": 16, + "line": 2, + }, + "identifierName": "PropTypes", + "start": Position { + "column": 7, + "line": 2, + }, + }, + "name": "PropTypes", + "start": 34, + "type": "Identifier", + }, + "start": 34, + "type": "ImportDefaultSpecifier", + }, + ], + "start": 27, + "type": "ImportDeclaration", + }, + Node { + "declarations": Array [ + Node { + "end": 111, + "id": Node { + "end": 79, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 4, + }, + "identifierName": "propTypes", + "start": Position { + "column": 6, + "line": 4, + }, + }, + "name": "propTypes", + "start": 70, + "type": "Identifier", + }, + "init": Node { + "end": 111, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 6, + }, + "start": Position { + "column": 18, + "line": 4, + }, + }, + "properties": Array [ + Node { + "computed": false, + "end": 109, + "key": Node { + "end": 91, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 5, + }, + "identifierName": "color", + "start": Position { + "column": 2, + "line": 5, + }, + }, + "name": "color", + "start": 86, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 5, + }, + "start": Position { + "column": 2, + "line": 5, + }, + }, + "method": false, + "shorthand": false, + "start": 86, + "type": "ObjectProperty", + "value": Node { + "computed": false, + "end": 109, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 5, + }, + "start": Position { + "column": 9, + "line": 5, + }, + }, + "object": Node { + "end": 102, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 5, + }, + "identifierName": "PropTypes", + "start": Position { + "column": 9, + "line": 5, + }, + }, + "name": "PropTypes", + "start": 93, + "type": "Identifier", + }, + "property": Node { + "end": 109, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 5, + }, + "identifierName": "string", + "start": Position { + "column": 19, + "line": 5, + }, + }, + "name": "string", + "start": 103, + "type": "Identifier", + }, + "start": 93, + "type": "MemberExpression", + }, + }, + ], + "start": 82, + "type": "ObjectExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 6, + }, + "start": Position { + "column": 6, + "line": 4, + }, + }, + "start": 70, + "type": "VariableDeclarator", + }, + ], + "end": 112, + "kind": "const", + "loc": SourceLocation { + "end": Position { + "column": 2, + "line": 6, + }, + "start": Position { + "column": 0, + "line": 4, + }, + }, + "start": 64, + "type": "VariableDeclaration", + }, + Node { + "declarations": Array [ + Node { + "end": 160, + "id": Node { + "end": 132, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 8, + }, + "identifierName": "defaultProps", + "start": Position { + "column": 6, + "line": 8, + }, + }, + "name": "defaultProps", + "start": 120, + "type": "Identifier", + }, + "init": Node { + "end": 160, + "extra": Object { + "trailingComma": 157, + }, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 10, + }, + "start": Position { + "column": 21, + "line": 8, + }, + }, + "properties": Array [ + Node { + "computed": false, + "end": 157, + "key": Node { + "end": 144, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 9, + }, + "identifierName": "color", + "start": Position { + "column": 2, + "line": 9, + }, + }, + "name": "color", + "start": 139, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 9, + }, + "start": Position { + "column": 2, + "line": 9, + }, + }, + "method": false, + "shorthand": false, + "start": 139, + "type": "ObjectProperty", + "value": Node { + "end": 157, + "extra": Object { + "raw": "'secondary'", + "rawValue": "secondary", + }, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 9, + }, + "start": Position { + "column": 9, + "line": 9, + }, + }, + "start": 146, + "type": "StringLiteral", + "value": "secondary", + }, + }, + ], + "start": 135, + "type": "ObjectExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 10, + }, + "start": Position { + "column": 6, + "line": 8, + }, + }, + "start": 120, + "type": "VariableDeclarator", + }, + ], + "end": 161, + "kind": "const", + "loc": SourceLocation { + "end": Position { + "column": 2, + "line": 10, + }, + "start": Position { + "column": 0, + "line": 8, + }, + }, + "start": 114, + "type": "VariableDeclaration", + }, + Node { + "declarations": Array [ + Node { + "end": 417, + "id": Node { + "end": 174, + "loc": SourceLocation { + "end": Position { + "column": 11, + "line": 12, + }, + "identifierName": "Badge", + "start": Position { + "column": 6, + "line": 12, + }, + }, + "name": "Badge", + "start": 169, + "type": "Identifier", + }, + "init": Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "declarations": Array [ + Node { + "end": 238, + "id": Node { + "end": 230, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 16, + }, + "start": Position { + "column": 6, + "line": 13, + }, + }, + "properties": Array [ + Node { + "computed": false, + "end": 207, + "extra": Object { + "shorthand": true, + }, + "key": Node { + "end": 207, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 14, + }, + "identifierName": "color", + "start": Position { + "column": 4, + "line": 14, + }, + }, + "name": "color", + "start": 202, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 14, + }, + "start": Position { + "column": 4, + "line": 14, + }, + }, + "method": false, + "shorthand": true, + "start": 202, + "type": "ObjectProperty", + "value": Node { + "end": 207, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 14, + }, + "identifierName": "color", + "start": Position { + "column": 4, + "line": 14, + }, + }, + "name": "color", + "start": 202, + "type": "Identifier", + }, + }, + Node { + "argument": Node { + "end": 226, + "loc": SourceLocation { + "end": Position { + "column": 17, + "line": 15, + }, + "identifierName": "attributes", + "start": Position { + "column": 7, + "line": 15, + }, + }, + "name": "attributes", + "start": 216, + "type": "Identifier", + }, + "end": 226, + "loc": SourceLocation { + "end": Position { + "column": 17, + "line": 15, + }, + "start": Position { + "column": 4, + "line": 15, + }, + }, + "start": 213, + "type": "RestElement", + }, + ], + "start": 196, + "type": "ObjectPattern", + }, + "init": Node { + "end": 238, + "loc": SourceLocation { + "end": Position { + "column": 11, + "line": 16, + }, + "identifierName": "props", + "start": Position { + "column": 6, + "line": 16, + }, + }, + "name": "props", + "start": 233, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 11, + "line": 16, + }, + "start": Position { + "column": 6, + "line": 13, + }, + }, + "start": 196, + "type": "VariableDeclarator", + }, + ], + "end": 239, + "kind": "let", + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 16, + }, + "start": Position { + "column": 2, + "line": 13, + }, + }, + "start": 192, + "type": "VariableDeclaration", + }, + Node { + "declarations": Array [ + Node { + "end": 286, + "id": Node { + "end": 256, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 18, + }, + "identifierName": "classes", + "start": Position { + "column": 8, + "line": 18, + }, + }, + "name": "classes", + "start": 249, + "type": "Identifier", + }, + "init": Node { + "elements": Array [ + Node { + "end": 267, + "extra": Object { + "raw": "'badge'", + "rawValue": "badge", + }, + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 18, + }, + "start": Position { + "column": 19, + "line": 18, + }, + }, + "start": 260, + "type": "StringLiteral", + "value": "badge", + }, + Node { + "end": 285, + "left": Node { + "end": 277, + "extra": Object { + "raw": "'badge-'", + "rawValue": "badge-", + }, + "loc": SourceLocation { + "end": Position { + "column": 36, + "line": 18, + }, + "start": Position { + "column": 28, + "line": 18, + }, + }, + "start": 269, + "type": "StringLiteral", + "value": "badge-", + }, + "loc": SourceLocation { + "end": Position { + "column": 44, + "line": 18, + }, + "start": Position { + "column": 28, + "line": 18, + }, + }, + "operator": "+", + "right": Node { + "end": 285, + "loc": SourceLocation { + "end": Position { + "column": 44, + "line": 18, + }, + "identifierName": "color", + "start": Position { + "column": 39, + "line": 18, + }, + }, + "name": "color", + "start": 280, + "type": "Identifier", + }, + "start": 269, + "type": "BinaryExpression", + }, + ], + "end": 286, + "loc": SourceLocation { + "end": Position { + "column": 45, + "line": 18, + }, + "start": Position { + "column": 18, + "line": 18, + }, + }, + "start": 259, + "type": "ArrayExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 45, + "line": 18, + }, + "start": Position { + "column": 8, + "line": 18, + }, + }, + "start": 249, + "type": "VariableDeclarator", + }, + ], + "end": 287, + "kind": "const", + "loc": SourceLocation { + "end": Position { + "column": 46, + "line": 18, + }, + "start": Position { + "column": 2, + "line": 18, + }, + }, + "start": 243, + "type": "VariableDeclaration", + }, + Node { + "alternate": null, + "consequent": Node { + "body": Array [ + Node { + "end": 346, + "expression": Node { + "end": 345, + "left": Node { + "end": 339, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 21, + }, + "identifierName": "Tag", + "start": Position { + "column": 4, + "line": 21, + }, + }, + "name": "Tag", + "start": 336, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 21, + }, + "start": Position { + "column": 4, + "line": 21, + }, + }, + "operator": "=", + "right": Node { + "end": 345, + "extra": Object { + "raw": "'a'", + "rawValue": "a", + }, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 21, + }, + "start": Position { + "column": 10, + "line": 21, + }, + }, + "start": 342, + "type": "StringLiteral", + "value": "a", + }, + "start": 336, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 14, + "line": 21, + }, + "start": Position { + "column": 4, + "line": 21, + }, + }, + "start": 336, + "type": "ExpressionStatement", + }, + ], + "directives": Array [], + "end": 350, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 22, + }, + "start": Position { + "column": 41, + "line": 20, + }, + }, + "start": 330, + "type": "BlockStatement", + }, + "end": 350, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 22, + }, + "start": Position { + "column": 2, + "line": 20, + }, + }, + "start": 291, + "test": Node { + "end": 328, + "left": Node { + "computed": false, + "end": 310, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 20, + }, + "start": Position { + "column": 6, + "line": 20, + }, + }, + "object": Node { + "end": 305, + "loc": SourceLocation { + "end": Position { + "column": 16, + "line": 20, + }, + "identifierName": "attributes", + "start": Position { + "column": 6, + "line": 20, + }, + }, + "name": "attributes", + "start": 295, + "type": "Identifier", + }, + "property": Node { + "end": 310, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 20, + }, + "identifierName": "href", + "start": Position { + "column": 17, + "line": 20, + }, + }, + "name": "href", + "start": 306, + "type": "Identifier", + }, + "start": 295, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 39, + "line": 20, + }, + "start": Position { + "column": 6, + "line": 20, + }, + }, + "operator": "&&", + "right": Node { + "end": 328, + "left": Node { + "end": 317, + "loc": SourceLocation { + "end": Position { + "column": 28, + "line": 20, + }, + "identifierName": "Tag", + "start": Position { + "column": 25, + "line": 20, + }, + }, + "name": "Tag", + "start": 314, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 39, + "line": 20, + }, + "start": Position { + "column": 25, + "line": 20, + }, + }, + "operator": "===", + "right": Node { + "end": 328, + "extra": Object { + "raw": "'span'", + "rawValue": "span", + }, + "loc": SourceLocation { + "end": Position { + "column": 39, + "line": 20, + }, + "start": Position { + "column": 33, + "line": 20, + }, + }, + "start": 322, + "type": "StringLiteral", + "value": "span", + }, + "start": 314, + "type": "BinaryExpression", + }, + "start": 295, + "type": "LogicalExpression", + }, + "type": "IfStatement", + }, + Node { + "argument": Node { + "children": Array [], + "closingElement": null, + "end": 410, + "extra": Object { + "parenStart": 361, + "parenthesized": true, + }, + "loc": SourceLocation { + "end": Position { + "column": 47, + "line": 25, + }, + "start": Position { + "column": 4, + "line": 25, + }, + }, + "openingElement": Node { + "attributes": Array [ + Node { + "argument": Node { + "end": 386, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 25, + }, + "identifierName": "attributes", + "start": Position { + "column": 13, + "line": 25, + }, + }, + "name": "attributes", + "start": 376, + "type": "Identifier", + }, + "end": 387, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 25, + }, + "start": Position { + "column": 9, + "line": 25, + }, + }, + "start": 372, + "type": "JSXSpreadAttribute", + }, + Node { + "end": 407, + "loc": SourceLocation { + "end": Position { + "column": 44, + "line": 25, + }, + "start": Position { + "column": 25, + "line": 25, + }, + }, + "name": Node { + "end": 397, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 25, + }, + "start": Position { + "column": 25, + "line": 25, + }, + }, + "name": "className", + "start": 388, + "type": "JSXIdentifier", + }, + "start": 388, + "type": "JSXAttribute", + "value": Node { + "end": 407, + "expression": Node { + "end": 406, + "loc": SourceLocation { + "end": Position { + "column": 43, + "line": 25, + }, + "identifierName": "classes", + "start": Position { + "column": 36, + "line": 25, + }, + }, + "name": "classes", + "start": 399, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 44, + "line": 25, + }, + "start": Position { + "column": 35, + "line": 25, + }, + }, + "start": 398, + "type": "JSXExpressionContainer", + }, + }, + ], + "end": 410, + "loc": SourceLocation { + "end": Position { + "column": 47, + "line": 25, + }, + "start": Position { + "column": 4, + "line": 25, + }, + }, + "name": Node { + "end": 371, + "loc": SourceLocation { + "end": Position { + "column": 8, + "line": 25, + }, + "start": Position { + "column": 5, + "line": 25, + }, + }, + "name": "Tag", + "start": 368, + "type": "JSXIdentifier", + }, + "selfClosing": true, + "start": 367, + "type": "JSXOpeningElement", + }, + "start": 367, + "type": "JSXElement", + }, + "end": 415, + "loc": SourceLocation { + "end": Position { + "column": 4, + "line": 26, + }, + "start": Position { + "column": 2, + "line": 24, + }, + }, + "start": 354, + "type": "ReturnStatement", + }, + ], + "directives": Array [], + "end": 417, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 27, + }, + "start": Position { + "column": 25, + "line": 12, + }, + }, + "start": 188, + "type": "BlockStatement", + }, + "end": 417, + "generator": false, + "id": null, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 27, + }, + "start": Position { + "column": 14, + "line": 12, + }, + }, + "params": Array [ + Node { + "end": 183, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 12, + }, + "identifierName": "props", + "start": Position { + "column": 15, + "line": 12, + }, + }, + "name": "props", + "start": 178, + "type": "Identifier", + }, + ], + "start": 177, + "type": "ArrowFunctionExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 27, + }, + "start": Position { + "column": 6, + "line": 12, + }, + }, + "start": 169, + "type": "VariableDeclarator", + }, + ], + "end": 418, + "kind": "const", + "loc": SourceLocation { + "end": Position { + "column": 2, + "line": 27, + }, + "start": Position { + "column": 0, + "line": 12, + }, + }, + "start": 163, + "type": "VariableDeclaration", + }, + Node { + "end": 448, + "expression": Node { + "end": 447, + "left": Node { + "computed": false, + "end": 435, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 29, + }, + "start": Position { + "column": 0, + "line": 29, + }, + }, + "object": Node { + "end": 425, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 29, + }, + "identifierName": "Badge", + "start": Position { + "column": 0, + "line": 29, + }, + }, + "name": "Badge", + "start": 420, + "type": "Identifier", + }, + "property": Node { + "end": 435, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 29, + }, + "identifierName": "propTypes", + "start": Position { + "column": 6, + "line": 29, + }, + }, + "name": "propTypes", + "start": 426, + "type": "Identifier", + }, + "start": 420, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 27, + "line": 29, + }, + "start": Position { + "column": 0, + "line": 29, + }, + }, + "operator": "=", + "right": Node { + "end": 447, + "loc": SourceLocation { + "end": Position { + "column": 27, + "line": 29, + }, + "identifierName": "propTypes", + "start": Position { + "column": 18, + "line": 29, + }, + }, + "name": "propTypes", + "start": 438, + "type": "Identifier", + }, + "start": 420, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 28, + "line": 29, + }, + "start": Position { + "column": 0, + "line": 29, + }, + }, + "start": 420, + "type": "ExpressionStatement", + }, + Node { + "end": 483, + "expression": Node { + "end": 482, + "left": Node { + "computed": false, + "end": 467, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 30, + }, + "start": Position { + "column": 0, + "line": 30, + }, + }, + "object": Node { + "end": 454, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 30, + }, + "identifierName": "Badge", + "start": Position { + "column": 0, + "line": 30, + }, + }, + "name": "Badge", + "start": 449, + "type": "Identifier", + }, + "property": Node { + "end": 467, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 30, + }, + "identifierName": "defaultProps", + "start": Position { + "column": 6, + "line": 30, + }, + }, + "name": "defaultProps", + "start": 455, + "type": "Identifier", + }, + "start": 449, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 33, + "line": 30, + }, + "start": Position { + "column": 0, + "line": 30, + }, + }, + "operator": "=", + "right": Node { + "end": 482, + "loc": SourceLocation { + "end": Position { + "column": 33, + "line": 30, + }, + "identifierName": "defaultProps", + "start": Position { + "column": 21, + "line": 30, + }, + }, + "name": "defaultProps", + "start": 470, + "type": "Identifier", + }, + "start": 449, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 30, + }, + "start": Position { + "column": 0, + "line": 30, + }, + }, + "start": 449, + "type": "ExpressionStatement", + }, + Node { + "declaration": Node { + "end": 505, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 32, + }, + "identifierName": "Badge", + "start": Position { + "column": 15, + "line": 32, + }, + }, + "name": "Badge", + "start": 500, + "type": "Identifier", + }, + "end": 506, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 32, + }, + "start": Position { + "column": 0, + "line": 32, + }, + }, + "start": 485, + "type": "ExportDefaultDeclaration", + }, + ], + "directives": Array [], + "end": 507, + "interpreter": null, + "loc": SourceLocation { + "end": Position { + "column": 0, + "line": 33, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "sourceType": "module", + "start": 0, + "type": "Program", + }, + "start": 0, + "type": "File", + }, +} +`; + +exports[`parsers integration should allow to parse a react file with project-wide configuration file 1`] = ` +Object { + "format": "js", + "originFileName": "jsx-with-project-wide-config/src/Badge.js", + "rawContent": "import React from 'react'; +import PropTypes from 'prop-types'; + +const propTypes = { + color: PropTypes.string +}; + +const defaultProps = { + color: 'secondary', +}; + +const Badge = (props) => { + let { + color, + ...attributes + } = props; + + const classes = ['badge', 'badge-' + color]; + + if (attributes.href && Tag === 'span') { + Tag = 'a'; + } + + return ( + + ); +}; + +Badge.propTypes = propTypes; +Badge.defaultProps = defaultProps; + +export default Badge; +", + "root": Node { + "comments": Array [], + "end": 507, + "errors": Array [], + "loc": SourceLocation { + "end": Position { + "column": 0, + "line": 33, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "program": Node { + "body": Array [ + Node { + "end": 26, + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 1, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "source": Node { + "end": 25, + "extra": Object { + "raw": "'react'", + "rawValue": "react", + }, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 1, + }, + "start": Position { + "column": 18, + "line": 1, + }, + }, + "start": 18, + "type": "StringLiteral", + "value": "react", + }, + "specifiers": Array [ + Node { + "end": 12, + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 1, + }, + "start": Position { + "column": 7, + "line": 1, + }, + }, + "local": Node { + "end": 12, + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 1, + }, + "identifierName": "React", + "start": Position { + "column": 7, + "line": 1, + }, + }, + "name": "React", + "start": 7, + "type": "Identifier", + }, + "start": 7, + "type": "ImportDefaultSpecifier", + }, + ], + "start": 0, + "type": "ImportDeclaration", + }, + Node { + "end": 62, + "loc": SourceLocation { + "end": Position { + "column": 35, + "line": 2, + }, + "start": Position { + "column": 0, + "line": 2, + }, + }, + "source": Node { + "end": 61, + "extra": Object { + "raw": "'prop-types'", + "rawValue": "prop-types", + }, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 2, + }, + "start": Position { + "column": 22, + "line": 2, + }, + }, + "start": 49, + "type": "StringLiteral", + "value": "prop-types", + }, + "specifiers": Array [ + Node { + "end": 43, + "loc": SourceLocation { + "end": Position { + "column": 16, + "line": 2, + }, + "start": Position { + "column": 7, + "line": 2, + }, + }, + "local": Node { + "end": 43, + "loc": SourceLocation { + "end": Position { + "column": 16, + "line": 2, + }, + "identifierName": "PropTypes", + "start": Position { + "column": 7, + "line": 2, + }, + }, + "name": "PropTypes", + "start": 34, + "type": "Identifier", + }, + "start": 34, + "type": "ImportDefaultSpecifier", + }, + ], + "start": 27, + "type": "ImportDeclaration", + }, + Node { + "declarations": Array [ + Node { + "end": 111, + "id": Node { + "end": 79, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 4, + }, + "identifierName": "propTypes", + "start": Position { + "column": 6, + "line": 4, + }, + }, + "name": "propTypes", + "start": 70, + "type": "Identifier", + }, + "init": Node { + "end": 111, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 6, + }, + "start": Position { + "column": 18, + "line": 4, + }, + }, + "properties": Array [ + Node { + "computed": false, + "end": 109, + "key": Node { + "end": 91, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 5, + }, + "identifierName": "color", + "start": Position { + "column": 2, + "line": 5, + }, + }, + "name": "color", + "start": 86, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 5, + }, + "start": Position { + "column": 2, + "line": 5, + }, + }, + "method": false, + "shorthand": false, + "start": 86, + "type": "ObjectProperty", + "value": Node { + "computed": false, + "end": 109, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 5, + }, + "start": Position { + "column": 9, + "line": 5, + }, + }, + "object": Node { + "end": 102, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 5, + }, + "identifierName": "PropTypes", + "start": Position { + "column": 9, + "line": 5, + }, + }, + "name": "PropTypes", + "start": 93, + "type": "Identifier", + }, + "property": Node { + "end": 109, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 5, + }, + "identifierName": "string", + "start": Position { + "column": 19, + "line": 5, + }, + }, + "name": "string", + "start": 103, + "type": "Identifier", + }, + "start": 93, + "type": "MemberExpression", + }, + }, + ], + "start": 82, + "type": "ObjectExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 6, + }, + "start": Position { + "column": 6, + "line": 4, + }, + }, + "start": 70, + "type": "VariableDeclarator", + }, + ], + "end": 112, + "kind": "const", + "loc": SourceLocation { + "end": Position { + "column": 2, + "line": 6, + }, + "start": Position { + "column": 0, + "line": 4, + }, + }, + "start": 64, + "type": "VariableDeclaration", + }, + Node { + "declarations": Array [ + Node { + "end": 160, + "id": Node { + "end": 132, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 8, + }, + "identifierName": "defaultProps", + "start": Position { + "column": 6, + "line": 8, + }, + }, + "name": "defaultProps", + "start": 120, + "type": "Identifier", + }, + "init": Node { + "end": 160, + "extra": Object { + "trailingComma": 157, + }, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 10, + }, + "start": Position { + "column": 21, + "line": 8, + }, + }, + "properties": Array [ + Node { + "computed": false, + "end": 157, + "key": Node { + "end": 144, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 9, + }, + "identifierName": "color", + "start": Position { + "column": 2, + "line": 9, + }, + }, + "name": "color", + "start": 139, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 9, + }, + "start": Position { + "column": 2, + "line": 9, + }, + }, + "method": false, + "shorthand": false, + "start": 139, + "type": "ObjectProperty", + "value": Node { + "end": 157, + "extra": Object { + "raw": "'secondary'", + "rawValue": "secondary", + }, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 9, + }, + "start": Position { + "column": 9, + "line": 9, + }, + }, + "start": 146, + "type": "StringLiteral", + "value": "secondary", + }, + }, + ], + "start": 135, + "type": "ObjectExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 10, + }, + "start": Position { + "column": 6, + "line": 8, + }, + }, + "start": 120, + "type": "VariableDeclarator", + }, + ], + "end": 161, + "kind": "const", + "loc": SourceLocation { + "end": Position { + "column": 2, + "line": 10, + }, + "start": Position { + "column": 0, + "line": 8, + }, + }, + "start": 114, + "type": "VariableDeclaration", + }, + Node { + "declarations": Array [ + Node { + "end": 417, + "id": Node { + "end": 174, + "loc": SourceLocation { + "end": Position { + "column": 11, + "line": 12, + }, + "identifierName": "Badge", + "start": Position { + "column": 6, + "line": 12, + }, + }, + "name": "Badge", + "start": 169, + "type": "Identifier", + }, + "init": Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "declarations": Array [ + Node { + "end": 238, + "id": Node { + "end": 230, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 16, + }, + "start": Position { + "column": 6, + "line": 13, + }, + }, + "properties": Array [ + Node { + "computed": false, + "end": 207, + "extra": Object { + "shorthand": true, + }, + "key": Node { + "end": 207, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 14, + }, + "identifierName": "color", + "start": Position { + "column": 4, + "line": 14, + }, + }, + "name": "color", + "start": 202, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 14, + }, + "start": Position { + "column": 4, + "line": 14, + }, + }, + "method": false, + "shorthand": true, + "start": 202, + "type": "ObjectProperty", + "value": Node { + "end": 207, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 14, + }, + "identifierName": "color", + "start": Position { + "column": 4, + "line": 14, + }, + }, + "name": "color", + "start": 202, + "type": "Identifier", + }, + }, + Node { + "argument": Node { + "end": 226, + "loc": SourceLocation { + "end": Position { + "column": 17, + "line": 15, + }, + "identifierName": "attributes", + "start": Position { + "column": 7, + "line": 15, + }, + }, + "name": "attributes", + "start": 216, + "type": "Identifier", + }, + "end": 226, + "loc": SourceLocation { + "end": Position { + "column": 17, + "line": 15, + }, + "start": Position { + "column": 4, + "line": 15, + }, + }, + "start": 213, + "type": "RestElement", + }, + ], + "start": 196, + "type": "ObjectPattern", + }, + "init": Node { + "end": 238, + "loc": SourceLocation { + "end": Position { + "column": 11, + "line": 16, + }, + "identifierName": "props", + "start": Position { + "column": 6, + "line": 16, + }, + }, + "name": "props", + "start": 233, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 11, + "line": 16, + }, + "start": Position { + "column": 6, + "line": 13, + }, + }, + "start": 196, + "type": "VariableDeclarator", + }, + ], + "end": 239, + "kind": "let", + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 16, + }, + "start": Position { + "column": 2, + "line": 13, + }, + }, + "start": 192, + "type": "VariableDeclaration", + }, + Node { + "declarations": Array [ + Node { + "end": 286, + "id": Node { + "end": 256, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 18, + }, + "identifierName": "classes", + "start": Position { + "column": 8, + "line": 18, + }, + }, + "name": "classes", + "start": 249, + "type": "Identifier", + }, + "init": Node { + "elements": Array [ + Node { + "end": 267, + "extra": Object { + "raw": "'badge'", + "rawValue": "badge", + }, + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 18, + }, + "start": Position { + "column": 19, + "line": 18, + }, + }, + "start": 260, + "type": "StringLiteral", + "value": "badge", + }, + Node { + "end": 285, + "left": Node { + "end": 277, + "extra": Object { + "raw": "'badge-'", + "rawValue": "badge-", + }, + "loc": SourceLocation { + "end": Position { + "column": 36, + "line": 18, + }, + "start": Position { + "column": 28, + "line": 18, + }, + }, + "start": 269, + "type": "StringLiteral", + "value": "badge-", + }, + "loc": SourceLocation { + "end": Position { + "column": 44, + "line": 18, + }, + "start": Position { + "column": 28, + "line": 18, + }, + }, + "operator": "+", + "right": Node { + "end": 285, + "loc": SourceLocation { + "end": Position { + "column": 44, + "line": 18, + }, + "identifierName": "color", + "start": Position { + "column": 39, + "line": 18, + }, + }, + "name": "color", + "start": 280, + "type": "Identifier", + }, + "start": 269, + "type": "BinaryExpression", + }, + ], + "end": 286, + "loc": SourceLocation { + "end": Position { + "column": 45, + "line": 18, + }, + "start": Position { + "column": 18, + "line": 18, + }, + }, + "start": 259, + "type": "ArrayExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 45, + "line": 18, + }, + "start": Position { + "column": 8, + "line": 18, + }, + }, + "start": 249, + "type": "VariableDeclarator", + }, + ], + "end": 287, + "kind": "const", + "loc": SourceLocation { + "end": Position { + "column": 46, + "line": 18, + }, + "start": Position { + "column": 2, + "line": 18, + }, + }, + "start": 243, + "type": "VariableDeclaration", + }, + Node { + "alternate": null, + "consequent": Node { + "body": Array [ + Node { + "end": 346, + "expression": Node { + "end": 345, + "left": Node { + "end": 339, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 21, + }, + "identifierName": "Tag", + "start": Position { + "column": 4, + "line": 21, + }, + }, + "name": "Tag", + "start": 336, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 21, + }, + "start": Position { + "column": 4, + "line": 21, + }, + }, + "operator": "=", + "right": Node { + "end": 345, + "extra": Object { + "raw": "'a'", + "rawValue": "a", + }, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 21, + }, + "start": Position { + "column": 10, + "line": 21, + }, + }, + "start": 342, + "type": "StringLiteral", + "value": "a", + }, + "start": 336, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 14, + "line": 21, + }, + "start": Position { + "column": 4, + "line": 21, + }, + }, + "start": 336, + "type": "ExpressionStatement", + }, + ], + "directives": Array [], + "end": 350, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 22, + }, + "start": Position { + "column": 41, + "line": 20, + }, + }, + "start": 330, + "type": "BlockStatement", + }, + "end": 350, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 22, + }, + "start": Position { + "column": 2, + "line": 20, + }, + }, + "start": 291, + "test": Node { + "end": 328, + "left": Node { + "computed": false, + "end": 310, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 20, + }, + "start": Position { + "column": 6, + "line": 20, + }, + }, + "object": Node { + "end": 305, + "loc": SourceLocation { + "end": Position { + "column": 16, + "line": 20, + }, + "identifierName": "attributes", + "start": Position { + "column": 6, + "line": 20, + }, + }, + "name": "attributes", + "start": 295, + "type": "Identifier", + }, + "property": Node { + "end": 310, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 20, + }, + "identifierName": "href", + "start": Position { + "column": 17, + "line": 20, + }, + }, + "name": "href", + "start": 306, + "type": "Identifier", + }, + "start": 295, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 39, + "line": 20, + }, + "start": Position { + "column": 6, + "line": 20, + }, + }, + "operator": "&&", + "right": Node { + "end": 328, + "left": Node { + "end": 317, + "loc": SourceLocation { + "end": Position { + "column": 28, + "line": 20, + }, + "identifierName": "Tag", + "start": Position { + "column": 25, + "line": 20, + }, + }, + "name": "Tag", + "start": 314, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 39, + "line": 20, + }, + "start": Position { + "column": 25, + "line": 20, + }, + }, + "operator": "===", + "right": Node { + "end": 328, + "extra": Object { + "raw": "'span'", + "rawValue": "span", + }, + "loc": SourceLocation { + "end": Position { + "column": 39, + "line": 20, + }, + "start": Position { + "column": 33, + "line": 20, + }, + }, + "start": 322, + "type": "StringLiteral", + "value": "span", + }, + "start": 314, + "type": "BinaryExpression", + }, + "start": 295, + "type": "LogicalExpression", + }, + "type": "IfStatement", + }, + Node { + "argument": Node { + "children": Array [], + "closingElement": null, + "end": 410, + "extra": Object { + "parenStart": 361, + "parenthesized": true, + }, + "loc": SourceLocation { + "end": Position { + "column": 47, + "line": 25, + }, + "start": Position { + "column": 4, + "line": 25, + }, + }, + "openingElement": Node { + "attributes": Array [ + Node { + "argument": Node { + "end": 386, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 25, + }, + "identifierName": "attributes", + "start": Position { + "column": 13, + "line": 25, + }, + }, + "name": "attributes", + "start": 376, + "type": "Identifier", + }, + "end": 387, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 25, + }, + "start": Position { + "column": 9, + "line": 25, + }, + }, + "start": 372, + "type": "JSXSpreadAttribute", + }, + Node { + "end": 407, + "loc": SourceLocation { + "end": Position { + "column": 44, + "line": 25, + }, + "start": Position { + "column": 25, + "line": 25, + }, + }, + "name": Node { + "end": 397, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 25, + }, + "start": Position { + "column": 25, + "line": 25, + }, + }, + "name": "className", + "start": 388, + "type": "JSXIdentifier", + }, + "start": 388, + "type": "JSXAttribute", + "value": Node { + "end": 407, + "expression": Node { + "end": 406, + "loc": SourceLocation { + "end": Position { + "column": 43, + "line": 25, + }, + "identifierName": "classes", + "start": Position { + "column": 36, + "line": 25, + }, + }, + "name": "classes", + "start": 399, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 44, + "line": 25, + }, + "start": Position { + "column": 35, + "line": 25, + }, + }, + "start": 398, + "type": "JSXExpressionContainer", + }, + }, + ], + "end": 410, + "loc": SourceLocation { + "end": Position { + "column": 47, + "line": 25, + }, + "start": Position { + "column": 4, + "line": 25, + }, + }, + "name": Node { + "end": 371, + "loc": SourceLocation { + "end": Position { + "column": 8, + "line": 25, + }, + "start": Position { + "column": 5, + "line": 25, + }, + }, + "name": "Tag", + "start": 368, + "type": "JSXIdentifier", + }, + "selfClosing": true, + "start": 367, + "type": "JSXOpeningElement", + }, + "start": 367, + "type": "JSXElement", + }, + "end": 415, + "loc": SourceLocation { + "end": Position { + "column": 4, + "line": 26, + }, + "start": Position { + "column": 2, + "line": 24, + }, + }, + "start": 354, + "type": "ReturnStatement", + }, + ], + "directives": Array [], + "end": 417, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 27, + }, + "start": Position { + "column": 25, + "line": 12, + }, + }, + "start": 188, + "type": "BlockStatement", + }, + "end": 417, + "generator": false, + "id": null, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 27, + }, + "start": Position { + "column": 14, + "line": 12, + }, + }, + "params": Array [ + Node { + "end": 183, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 12, + }, + "identifierName": "props", + "start": Position { + "column": 15, + "line": 12, + }, + }, + "name": "props", + "start": 178, + "type": "Identifier", + }, + ], + "start": 177, + "type": "ArrowFunctionExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 27, + }, + "start": Position { + "column": 6, + "line": 12, + }, + }, + "start": 169, + "type": "VariableDeclarator", + }, + ], + "end": 418, + "kind": "const", + "loc": SourceLocation { + "end": Position { + "column": 2, + "line": 27, + }, + "start": Position { + "column": 0, + "line": 12, + }, + }, + "start": 163, + "type": "VariableDeclaration", + }, + Node { + "end": 448, + "expression": Node { + "end": 447, + "left": Node { + "computed": false, + "end": 435, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 29, + }, + "start": Position { + "column": 0, + "line": 29, + }, + }, + "object": Node { + "end": 425, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 29, + }, + "identifierName": "Badge", + "start": Position { + "column": 0, + "line": 29, + }, + }, + "name": "Badge", + "start": 420, + "type": "Identifier", + }, + "property": Node { + "end": 435, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 29, + }, + "identifierName": "propTypes", + "start": Position { + "column": 6, + "line": 29, + }, + }, + "name": "propTypes", + "start": 426, + "type": "Identifier", + }, + "start": 420, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 27, + "line": 29, + }, + "start": Position { + "column": 0, + "line": 29, + }, + }, + "operator": "=", + "right": Node { + "end": 447, + "loc": SourceLocation { + "end": Position { + "column": 27, + "line": 29, + }, + "identifierName": "propTypes", + "start": Position { + "column": 18, + "line": 29, + }, + }, + "name": "propTypes", + "start": 438, + "type": "Identifier", + }, + "start": 420, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 28, + "line": 29, + }, + "start": Position { + "column": 0, + "line": 29, + }, + }, + "start": 420, + "type": "ExpressionStatement", + }, + Node { + "end": 483, + "expression": Node { + "end": 482, + "left": Node { + "computed": false, + "end": 467, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 30, + }, + "start": Position { + "column": 0, + "line": 30, + }, + }, + "object": Node { + "end": 454, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 30, + }, + "identifierName": "Badge", + "start": Position { + "column": 0, + "line": 30, + }, + }, + "name": "Badge", + "start": 449, + "type": "Identifier", + }, + "property": Node { + "end": 467, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 30, + }, + "identifierName": "defaultProps", + "start": Position { + "column": 6, + "line": 30, + }, + }, + "name": "defaultProps", + "start": 455, + "type": "Identifier", + }, + "start": 449, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 33, + "line": 30, + }, + "start": Position { + "column": 0, + "line": 30, + }, + }, + "operator": "=", + "right": Node { + "end": 482, + "loc": SourceLocation { + "end": Position { + "column": 33, + "line": 30, + }, + "identifierName": "defaultProps", + "start": Position { + "column": 21, + "line": 30, + }, + }, + "name": "defaultProps", + "start": 470, + "type": "Identifier", + }, + "start": 449, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 30, + }, + "start": Position { + "column": 0, + "line": 30, + }, + }, + "start": 449, + "type": "ExpressionStatement", + }, + Node { + "declaration": Node { + "end": 505, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 32, + }, + "identifierName": "Badge", + "start": Position { + "column": 15, + "line": 32, + }, + }, + "name": "Badge", + "start": 500, + "type": "Identifier", + }, + "end": 506, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 32, + }, + "start": Position { + "column": 0, + "line": 32, + }, + }, + "start": 485, + "type": "ExportDefaultDeclaration", + }, + ], + "directives": Array [], + "end": 507, + "interpreter": null, + "loc": SourceLocation { + "end": Position { + "column": 0, + "line": 33, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "sourceType": "module", + "start": 0, + "type": "Program", + }, + "start": 0, + "type": "File", + }, +} +`; + +exports[`parsers integration should allow to parse a tsx file 1`] = ` +Object { + "format": "ts", + "originFileName": "App.tsx", + "rawContent": "const app = +", + "root": Node { + "comments": Array [], + "end": 36, + "errors": Array [], + "loc": SourceLocation { + "end": Position { + "column": 0, + "line": 2, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "program": Node { + "body": Array [ + Node { + "declarations": Array [ + Node { + "end": 35, + "id": Node { + "end": 9, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 1, + }, + "identifierName": "app", + "start": Position { + "column": 6, + "line": 1, + }, + }, + "name": "app", + "range": Array [ + 6, + 9, + ], + "start": 6, + "type": "Identifier", + }, + "init": Node { + "children": Array [], + "closingElement": Node { + "end": 35, + "loc": SourceLocation { + "end": Position { + "column": 35, + "line": 1, + }, + "start": Position { + "column": 28, + "line": 1, + }, + }, + "name": Node { + "end": 34, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 1, + }, + "start": Position { + "column": 30, + "line": 1, + }, + }, + "name": "Html", + "range": Array [ + 30, + 34, + ], + "start": 30, + "type": "JSXIdentifier", + }, + "range": Array [ + 28, + 35, + ], + "start": 28, + "type": "JSXClosingElement", + }, + "end": 35, + "loc": SourceLocation { + "end": Position { + "column": 35, + "line": 1, + }, + "start": Position { + "column": 12, + "line": 1, + }, + }, + "openingElement": Node { + "attributes": Array [ + Node { + "end": 27, + "loc": SourceLocation { + "end": Position { + "column": 27, + "line": 1, + }, + "start": Position { + "column": 18, + "line": 1, + }, + }, + "name": Node { + "end": 21, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 1, + }, + "start": Position { + "column": 18, + "line": 1, + }, + }, + "name": "foo", + "range": Array [ + 18, + 21, + ], + "start": 18, + "type": "JSXIdentifier", + }, + "range": Array [ + 18, + 27, + ], + "start": 18, + "type": "JSXAttribute", + "value": Node { + "end": 27, + "expression": Node { + "end": 26, + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 1, + }, + "identifierName": "bar", + "start": Position { + "column": 23, + "line": 1, + }, + }, + "name": "bar", + "range": Array [ + 23, + 26, + ], + "start": 23, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 27, + "line": 1, + }, + "start": Position { + "column": 22, + "line": 1, + }, + }, + "range": Array [ + 22, + 27, + ], + "start": 22, + "type": "JSXExpressionContainer", + }, + }, + ], + "end": 28, + "loc": SourceLocation { + "end": Position { + "column": 28, + "line": 1, + }, + "start": Position { + "column": 12, + "line": 1, + }, + }, + "name": Node { + "end": 17, + "loc": SourceLocation { + "end": Position { + "column": 17, + "line": 1, + }, + "start": Position { + "column": 13, + "line": 1, + }, + }, + "name": "Html", + "range": Array [ + 13, + 17, + ], + "start": 13, + "type": "JSXIdentifier", + }, + "range": Array [ + 12, + 28, + ], + "selfClosing": false, + "start": 12, + "type": "JSXOpeningElement", + }, + "range": Array [ + 12, + 35, + ], + "start": 12, + "type": "JSXElement", + }, + "loc": SourceLocation { + "end": Position { + "column": 35, + "line": 1, + }, + "start": Position { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 35, + ], + "start": 6, + "type": "VariableDeclarator", + }, + ], + "end": 35, + "kind": "const", + "loc": SourceLocation { + "end": Position { + "column": 35, + "line": 1, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 35, + ], + "start": 0, + "type": "VariableDeclaration", + }, + ], + "directives": Array [], + "end": 36, + "interpreter": null, + "loc": SourceLocation { + "end": Position { + "column": 0, + "line": 2, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 36, + ], + "sourceType": "module", + "start": 0, + "type": "Program", + }, + "range": Array [ + 0, + 36, + ], + "start": 0, + "type": "File", + }, +} +`; + +exports[`parsers integration should allow to parse html with script tags 1`] = ` +Object { + "format": "html", + "originFileName": "index.html", + "rawContent": " + + + + + Document + + + + + + + +", + "root": Object { + "scripts": Array [ + Object { + "format": "js", + "originFileName": "index.html", + "rawContent": " + alert('hello there'); + ", + "root": Node { + "comments": Array [], + "end": 232, + "errors": Array [], + "loc": SourceLocation { + "end": Position { + "column": 4, + "line": 11, + }, + "start": Position { + "column": 12, + "line": 9, + }, + }, + "program": Node { + "body": Array [ + Node { + "end": 227, + "expression": Node { + "arguments": Array [ + Node { + "end": 225, + "extra": Object { + "raw": "'hello there'", + "rawValue": "hello there", + }, + "loc": SourceLocation { + "end": Position { + "column": 27, + "line": 10, + }, + "start": Position { + "column": 14, + "line": 10, + }, + }, + "start": 212, + "type": "StringLiteral", + "value": "hello there", + }, + ], + "callee": Node { + "end": 211, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 10, + }, + "identifierName": "alert", + "start": Position { + "column": 8, + "line": 26, + }, + }, + "name": "alert", + "start": 206, + "type": "Identifier", + }, + "end": 226, + "loc": SourceLocation { + "end": Position { + "column": 28, + "line": 10, + }, + "start": Position { + "column": 8, + "line": 26, + }, + }, + "start": 206, + "type": "CallExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 10, + }, + "start": Position { + "column": 8, + "line": 26, + }, + }, + "start": 206, + "type": "ExpressionStatement", + }, + ], + "directives": Array [], + "end": 232, + "interpreter": null, + "loc": SourceLocation { + "end": Position { + "column": 4, + "line": 11, + }, + "start": Position { + "column": 12, + "line": 9, + }, + }, + "sourceType": "module", + "start": 197, + "type": "Program", + }, + "start": 197, + "type": "File", + }, + }, + Object { + "format": "ts", + "originFileName": "index.html", + "rawContent": " + function fib(n: number) { + if (n == 0 || n == 1) { + return n; + } else { + return (f(n-1) + f(n-2)); + } + } + ", + "root": Node { + "comments": Array [], + "end": 452, + "errors": Array [], + "loc": SourceLocation { + "end": Position { + "column": 4, + "line": 21, + }, + "start": Position { + "column": 35, + "line": 13, + }, + }, + "program": Node { + "body": Array [ + Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "alternate": Node { + "body": Array [ + Node { + "argument": Node { + "end": 423, + "extra": Object { + "parenStart": 129, + "parenthesized": true, + }, + "left": Node { + "arguments": Array [ + Node { + "end": 413, + "left": Node { + "end": 411, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 18, + }, + "identifierName": "n", + "start": Position { + "column": 22, + "line": 30, + }, + }, + "name": "n", + "range": Array [ + 132, + 133, + ], + "start": 410, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 30, + }, + "start": Position { + "column": 22, + "line": 30, + }, + }, + "operator": "-", + "range": Array [ + 132, + 135, + ], + "right": Node { + "end": 413, + "extra": Object { + "raw": "1", + "rawValue": 1, + }, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 30, + }, + "start": Position { + "column": 24, + "line": 18, + }, + }, + "range": Array [ + 134, + 135, + ], + "start": 412, + "type": "NumericLiteral", + "value": 1, + }, + "start": 410, + "type": "BinaryExpression", + }, + ], + "callee": Node { + "end": 409, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 18, + }, + "identifierName": "f", + "start": Position { + "column": 20, + "line": 42, + }, + }, + "name": "f", + "range": Array [ + 130, + 131, + ], + "start": 408, + "type": "Identifier", + }, + "end": 414, + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 18, + }, + "start": Position { + "column": 20, + "line": 42, + }, + }, + "range": Array [ + 130, + 136, + ], + "start": 408, + "type": "CallExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 35, + "line": 30, + }, + "start": Position { + "column": 20, + "line": 42, + }, + }, + "operator": "+", + "range": Array [ + 130, + 145, + ], + "right": Node { + "arguments": Array [ + Node { + "end": 422, + "left": Node { + "end": 420, + "loc": SourceLocation { + "end": Position { + "column": 32, + "line": 18, + }, + "identifierName": "n", + "start": Position { + "column": 31, + "line": 30, + }, + }, + "name": "n", + "range": Array [ + 141, + 142, + ], + "start": 419, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 30, + }, + "start": Position { + "column": 31, + "line": 30, + }, + }, + "operator": "-", + "range": Array [ + 141, + 144, + ], + "right": Node { + "end": 422, + "extra": Object { + "raw": "2", + "rawValue": 2, + }, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 30, + }, + "start": Position { + "column": 33, + "line": 18, + }, + }, + "range": Array [ + 143, + 144, + ], + "start": 421, + "type": "NumericLiteral", + "value": 2, + }, + "start": 419, + "type": "BinaryExpression", + }, + ], + "callee": Node { + "end": 418, + "loc": SourceLocation { + "end": Position { + "column": 30, + "line": 18, + }, + "identifierName": "f", + "start": Position { + "column": 29, + "line": 30, + }, + }, + "name": "f", + "range": Array [ + 139, + 140, + ], + "start": 417, + "type": "Identifier", + }, + "end": 423, + "loc": SourceLocation { + "end": Position { + "column": 35, + "line": 30, + }, + "start": Position { + "column": 29, + "line": 30, + }, + }, + "range": Array [ + 139, + 145, + ], + "start": 417, + "type": "CallExpression", + }, + "start": 408, + "type": "BinaryExpression", + }, + "end": 425, + "loc": SourceLocation { + "end": Position { + "column": 37, + "line": 18, + }, + "start": Position { + "column": 12, + "line": 18, + }, + }, + "range": Array [ + 122, + 147, + ], + "start": 400, + "type": "ReturnStatement", + }, + ], + "directives": Array [], + "end": 437, + "loc": SourceLocation { + "end": Position { + "column": 11, + "line": 31, + }, + "start": Position { + "column": 17, + "line": 17, + }, + }, + "range": Array [ + 108, + 159, + ], + "start": 386, + "type": "BlockStatement", + }, + "consequent": Node { + "body": Array [ + Node { + "argument": Node { + "end": 367, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 16, + }, + "identifierName": "n", + "start": Position { + "column": 19, + "line": 16, + }, + }, + "name": "n", + "range": Array [ + 88, + 89, + ], + "start": 366, + "type": "Identifier", + }, + "end": 368, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 16, + }, + "start": Position { + "column": 12, + "line": 16, + }, + }, + "range": Array [ + 81, + 90, + ], + "start": 359, + "type": "ReturnStatement", + }, + ], + "directives": Array [], + "end": 380, + "loc": SourceLocation { + "end": Position { + "column": 11, + "line": 17, + }, + "start": Position { + "column": 32, + "line": 15, + }, + }, + "range": Array [ + 67, + 102, + ], + "start": 345, + "type": "BlockStatement", + }, + "end": 437, + "loc": SourceLocation { + "end": Position { + "column": 11, + "line": 31, + }, + "start": Position { + "column": 10, + "line": 15, + }, + }, + "range": Array [ + 45, + 159, + ], + "start": 323, + "test": Node { + "end": 343, + "left": Node { + "end": 333, + "left": Node { + "end": 328, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 15, + }, + "identifierName": "n", + "start": Position { + "column": 14, + "line": 39, + }, + }, + "name": "n", + "range": Array [ + 49, + 50, + ], + "start": 327, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 27, + }, + "start": Position { + "column": 14, + "line": 39, + }, + }, + "operator": "==", + "range": Array [ + 49, + 55, + ], + "right": Node { + "end": 333, + "extra": Object { + "raw": "0", + "rawValue": 0, + }, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 27, + }, + "start": Position { + "column": 19, + "line": 15, + }, + }, + "range": Array [ + 54, + 55, + ], + "start": 332, + "type": "NumericLiteral", + "value": 0, + }, + "start": 327, + "type": "BinaryExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 30, + "line": 39, + }, + "start": Position { + "column": 14, + "line": 39, + }, + }, + "operator": "||", + "range": Array [ + 49, + 65, + ], + "right": Node { + "end": 343, + "left": Node { + "end": 338, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 15, + }, + "identifierName": "n", + "start": Position { + "column": 24, + "line": 27, + }, + }, + "name": "n", + "range": Array [ + 59, + 60, + ], + "start": 337, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 30, + "line": 39, + }, + "start": Position { + "column": 24, + "line": 27, + }, + }, + "operator": "==", + "range": Array [ + 59, + 65, + ], + "right": Node { + "end": 343, + "extra": Object { + "raw": "1", + "rawValue": 1, + }, + "loc": SourceLocation { + "end": Position { + "column": 30, + "line": 39, + }, + "start": Position { + "column": 29, + "line": 15, + }, + }, + "range": Array [ + 64, + 65, + ], + "start": 342, + "type": "NumericLiteral", + "value": 1, + }, + "start": 337, + "type": "BinaryExpression", + }, + "start": 327, + "type": "LogicalExpression", + }, + "type": "IfStatement", + }, + ], + "directives": Array [], + "end": 447, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 32, + }, + "start": Position { + "column": 32, + "line": 14, + }, + }, + "range": Array [ + 33, + 169, + ], + "start": 311, + "type": "BlockStatement", + }, + "end": 447, + "generator": false, + "id": Node { + "end": 299, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 14, + }, + "identifierName": "fib", + "start": Position { + "column": 17, + "line": 14, + }, + }, + "name": "fib", + "range": Array [ + 18, + 21, + ], + "start": 296, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 32, + }, + "start": Position { + "column": 8, + "line": 14, + }, + }, + "params": Array [ + Node { + "end": 309, + "loc": SourceLocation { + "end": Position { + "column": 30, + "line": 38, + }, + "identifierName": "n", + "start": Position { + "column": 21, + "line": 14, + }, + }, + "name": "n", + "range": Array [ + 22, + 31, + ], + "start": 300, + "type": "Identifier", + "typeAnnotation": Node { + "end": 309, + "loc": SourceLocation { + "end": Position { + "column": 30, + "line": 38, + }, + "start": Position { + "column": 22, + "line": 14, + }, + }, + "range": Array [ + 23, + 31, + ], + "start": 301, + "type": "TSTypeAnnotation", + "typeAnnotation": Node { + "end": 309, + "loc": SourceLocation { + "end": Position { + "column": 30, + "line": 38, + }, + "start": Position { + "column": 24, + "line": 14, + }, + }, + "range": Array [ + 25, + 31, + ], + "start": 303, + "type": "TSNumberKeyword", + }, + }, + }, + ], + "range": Array [ + 9, + 169, + ], + "start": 287, + "type": "FunctionDeclaration", + }, + ], + "directives": Array [], + "end": 452, + "interpreter": null, + "loc": SourceLocation { + "end": Position { + "column": 4, + "line": 21, + }, + "start": Position { + "column": 35, + "line": 13, + }, + }, + "range": Array [ + 0, + 174, + ], + "sourceType": "module", + "start": 278, + "type": "Program", + }, + "range": Array [ + 0, + 174, + ], + "start": 278, + "type": "File", + }, + }, + ], + }, +} +`; + +exports[`parsers integration should ignore configuration when parsing ts files 1`] = ` +Object { + "format": "ts", + "originFileName": "ts-in-babel-project/src/app.ts", + "rawContent": "class App {} +", + "root": Node { + "comments": Array [], + "end": 13, + "errors": Array [], + "loc": SourceLocation { + "end": Position { + "column": 0, + "line": 2, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "program": Node { + "body": Array [ + Node { + "body": Node { + "body": Array [], + "end": 12, + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 1, + }, + "start": Position { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 12, + ], + "start": 10, + "type": "ClassBody", + }, + "end": 12, + "id": Node { + "end": 9, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 1, + }, + "identifierName": "App", + "start": Position { + "column": 6, + "line": 1, + }, + }, + "name": "App", + "range": Array [ + 6, + 9, + ], + "start": 6, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 1, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 12, + ], + "start": 0, + "superClass": null, + "type": "ClassDeclaration", + }, + ], + "directives": Array [], + "end": 13, + "interpreter": null, + "loc": SourceLocation { + "end": Position { + "column": 0, + "line": 2, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 13, + ], + "sourceType": "module", + "start": 0, + "type": "Program", + }, + "range": Array [ + 0, + 13, + ], + "start": 0, + "type": "File", + }, +} +`; diff --git a/packages/instrumenter/test/integration/parsers.it.spec.ts b/packages/instrumenter/test/integration/parsers.it.spec.ts new file mode 100644 index 0000000000..84c2833aa1 --- /dev/null +++ b/packages/instrumenter/test/integration/parsers.it.spec.ts @@ -0,0 +1,104 @@ +import { promises as fs } from 'fs'; +import path from 'path'; + +import { expect } from 'chai'; + +import { createParser, ParserOptions } from '../../src/parsers'; +import { AstFormat, HtmlAst, TSAst, JSAst, Ast } from '../../src/syntax'; +import { createParserOptions } from '../helpers/factories'; + +const resolveTestResource = path.resolve.bind(path, __dirname, '..' /* integration */, '..' /* test */, '..' /* dist */, 'testResources', 'parser'); + +describe('parsers integration', () => { + it('should allow to parse html with script tags', async () => { + const actual = await actAssertHtml('index.html'); + expect(actual.root.scripts).lengthOf(2); + expect(actual).to.matchSnapshot(); + }); + + it('should allow to parse a *.vue file', async () => { + const actual = await actAssertHtml('App.vue'); + expect(actual.format).eq(AstFormat.Html); + expect(actual.root.scripts).lengthOf(1); + expect(actual).to.matchSnapshot(); + }); + + it('should allow to parse a an angular file', async () => { + const actual = await actAssertTS('app.component.ts'); + expect(actual).to.matchSnapshot(); + }); + + it('should allow to parse a tsx file', async () => { + const actual = await actAssertTS('App.tsx'); + expect(actual).to.matchSnapshot(); + }); + + it('should allow to parse a react file with custom babelrc file', async () => { + const actual = await actAssertJS('jsx-with-babelrc/Badge.js'); + expect(actual).to.matchSnapshot(); + }); + + it('should allow to parse a react file with project-wide configuration file', async () => { + process.chdir(resolveTestResource('jsx-with-project-wide-config')); + const actual = await actAssertJS('jsx-with-project-wide-config/src/Badge.js'); + expect(actual).to.matchSnapshot(); + }); + + it('should ignore configuration when parsing ts files', async () => { + process.chdir(resolveTestResource('ts-in-babel-project')); + const actual = await actAssertTS('ts-in-babel-project/src/app.ts'); + expect(actual).to.matchSnapshot(); + }); + + it('should allow a plugin that conflicts with the default plugins as long as plugins are emptied out', async () => { + process.chdir(resolveTestResource('js-in-babel-project')); + const actual = await actAssertJS('js-in-babel-project/src/app.js', createParserOptions({ plugins: [] })); + expect(actual).to.matchSnapshot(); + }); + + it('should allow to parse a mjs file', async () => { + const actual = await actAssertJS('app.mjs'); + expect(actual).to.matchSnapshot(); + }); + + it('should allow to parse a cjs file', async () => { + const actual = await actAssertJS('app.cjs'); + expect(actual).to.matchSnapshot(); + }); + + async function act(testResourceFileName: string, options: ParserOptions) { + const fileName = resolveTestResource(testResourceFileName); + const input = await fs.readFile(fileName, 'utf8'); + const actual = await createParser(options)(input, fileName); + cleanFileName(actual, testResourceFileName); + return actual; + } + async function actAssertHtml(testResourceFileName: string, options = createParserOptions()): Promise { + const actual = await act(testResourceFileName, options); + expect(actual.format).eq(AstFormat.Html); + return actual as HtmlAst; + } + async function actAssertTS(testResourceFileName: string, options = createParserOptions()): Promise { + const actual = await act(testResourceFileName, options); + expect(actual.format).eq(AstFormat.TS); + return actual as TSAst; + } + async function actAssertJS(testResourceFileName: string, options = createParserOptions()): Promise { + const actual = await act(testResourceFileName, options); + expect(actual.format).eq(AstFormat.JS); + return actual as JSAst; + } + + /** + * Reset the file name, so snapshots are the same locally as in ci/cd + */ + function cleanFileName(ast: Ast, fileNameOverride: string) { + ast.originFileName = fileNameOverride; + switch (ast.format) { + case AstFormat.Html: + ast.root.scripts.forEach((script) => { + script.originFileName = fileNameOverride; + }); + } + } +}); diff --git a/packages/instrumenter/test/integration/printers.it.spec.ts b/packages/instrumenter/test/integration/printers.it.spec.ts new file mode 100644 index 0000000000..b24833f059 --- /dev/null +++ b/packages/instrumenter/test/integration/printers.it.spec.ts @@ -0,0 +1,41 @@ +import path from 'path'; +import { promises as fs } from 'fs'; + +import { normalizeWhitespaces } from '@stryker-mutator/util'; +import { expect } from 'chai'; + +import { createParser } from '../../src/parsers'; +import { print } from '../../src/printers'; +import { createParserOptions } from '../helpers/factories'; + +const resolveTestResource = path.resolve.bind(path, __dirname, '..' /* integration */, '..' /* test */, '..' /* dist */, 'testResources', 'printer'); + +describe('parse and print integration', () => { + describe('echo', () => { + it('should leave comments in a typescript file', async () => { + await actArrangeAndAssert('ts-with-comments.ts'); + }); + + async function actArrangeAndAssert(relativeFileName: string) { + const fileName = resolveTestResource('echo', relativeFileName); + const code = await fs.readFile(fileName, 'utf8'); + const parsed = await createParser(createParserOptions())(code, fileName); + const output = print(parsed); + expect(normalizeWhitespaces(output)).eq(normalizeWhitespaces(code)); + } + }); + describe('html', () => { + it('should be able to print html files with multiple script tags', async () => { + await actArrangeAndAssert('hello-world'); + }); + + async function actArrangeAndAssert(testCase: string) { + const inputFileName = resolveTestResource('html', `${testCase}.in.html`); + const outputFileName = resolveTestResource('html', `${testCase}.out.html`); + const [input, expectedOutput] = await Promise.all([fs.readFile(inputFileName, 'utf8'), fs.readFile(outputFileName, 'utf8')]); + const parsed = await createParser(createParserOptions())(input, inputFileName); + const actualOutput = print(parsed); + expect(normalizeWhitespaces(actualOutput)).eq(normalizeWhitespaces(expectedOutput)); + } + }); +}); diff --git a/packages/instrumenter/test/integration/transformers.it.spec.js.snap b/packages/instrumenter/test/integration/transformers.it.spec.js.snap new file mode 100644 index 0000000000..d3f792a7ce --- /dev/null +++ b/packages/instrumenter/test/integration/transformers.it.spec.js.snap @@ -0,0 +1,13029 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`transformers integration should transform a js file 1`] = ` +Object { + "format": "js", + "originFileName": "example.js", + "rawContent": "const foo = 40 + 2", + "root": Node { + "comments": Array [], + "end": 18, + "errors": Array [], + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 1, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "program": Node { + "body": Array [ + Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "declarations": Array [ + Node { + "end": 64, + "id": Node { + "end": 32, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 2, + }, + "identifierName": "g", + "start": Position { + "column": 6, + "line": 2, + }, + }, + "name": "g", + "start": 31, + "type": "Identifier", + }, + "init": Node { + "arguments": Array [], + "callee": Node { + "arguments": Array [ + Node { + "end": 61, + "extra": Object { + "raw": "\\"return this\\"", + "rawValue": "return this", + }, + "loc": SourceLocation { + "end": Position { + "column": 36, + "line": 2, + }, + "start": Position { + "column": 23, + "line": 2, + }, + }, + "start": 48, + "type": "StringLiteral", + "value": "return this", + }, + ], + "callee": Node { + "end": 47, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 2, + }, + "identifierName": "Function", + "start": Position { + "column": 14, + "line": 2, + }, + }, + "name": "Function", + "start": 39, + "type": "Identifier", + }, + "end": 62, + "loc": SourceLocation { + "end": Position { + "column": 37, + "line": 2, + }, + "start": Position { + "column": 10, + "line": 2, + }, + }, + "start": 35, + "type": "NewExpression", + }, + "end": 64, + "loc": SourceLocation { + "end": Position { + "column": 39, + "line": 2, + }, + "start": Position { + "column": 10, + "line": 2, + }, + }, + "start": 35, + "type": "CallExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 39, + "line": 2, + }, + "start": Position { + "column": 6, + "line": 2, + }, + }, + "start": 31, + "type": "VariableDeclarator", + }, + ], + "end": 65, + "kind": "var", + "loc": SourceLocation { + "end": Position { + "column": 40, + "line": 2, + }, + "start": Position { + "column": 2, + "line": 2, + }, + }, + "start": 27, + "type": "VariableDeclaration", + }, + Node { + "declarations": Array [ + Node { + "end": 114, + "id": Node { + "end": 74, + "loc": SourceLocation { + "end": Position { + "column": 8, + "line": 3, + }, + "identifierName": "ns", + "start": Position { + "column": 6, + "line": 3, + }, + }, + "name": "ns", + "start": 72, + "type": "Identifier", + }, + "init": Node { + "end": 114, + "left": Node { + "computed": false, + "end": 90, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 3, + }, + "start": Position { + "column": 11, + "line": 3, + }, + }, + "object": Node { + "end": 78, + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 3, + }, + "identifierName": "g", + "start": Position { + "column": 11, + "line": 3, + }, + }, + "name": "g", + "start": 77, + "type": "Identifier", + }, + "property": Node { + "end": 90, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 3, + }, + "identifierName": "__stryker__", + "start": Position { + "column": 13, + "line": 3, + }, + }, + "name": "__stryker__", + "start": 79, + "type": "Identifier", + }, + "start": 77, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 48, + "line": 3, + }, + "start": Position { + "column": 11, + "line": 3, + }, + }, + "operator": "||", + "right": Node { + "end": 113, + "extra": Object { + "parenStart": 94, + "parenthesized": true, + }, + "left": Node { + "computed": false, + "end": 108, + "loc": SourceLocation { + "end": Position { + "column": 42, + "line": 3, + }, + "start": Position { + "column": 29, + "line": 3, + }, + }, + "object": Node { + "end": 96, + "loc": SourceLocation { + "end": Position { + "column": 30, + "line": 3, + }, + "identifierName": "g", + "start": Position { + "column": 29, + "line": 3, + }, + }, + "name": "g", + "start": 95, + "type": "Identifier", + }, + "property": Node { + "end": 108, + "loc": SourceLocation { + "end": Position { + "column": 42, + "line": 3, + }, + "identifierName": "__stryker__", + "start": Position { + "column": 31, + "line": 3, + }, + }, + "name": "__stryker__", + "start": 97, + "type": "Identifier", + }, + "start": 95, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 47, + "line": 3, + }, + "start": Position { + "column": 29, + "line": 3, + }, + }, + "operator": "=", + "right": Node { + "end": 113, + "loc": SourceLocation { + "end": Position { + "column": 47, + "line": 3, + }, + "start": Position { + "column": 45, + "line": 3, + }, + }, + "properties": Array [], + "start": 111, + "type": "ObjectExpression", + }, + "start": 95, + "type": "AssignmentExpression", + }, + "start": 77, + "type": "LogicalExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 48, + "line": 3, + }, + "start": Position { + "column": 6, + "line": 3, + }, + }, + "start": 72, + "type": "VariableDeclarator", + }, + ], + "end": 115, + "kind": "var", + "loc": SourceLocation { + "end": Position { + "column": 49, + "line": 3, + }, + "start": Position { + "column": 2, + "line": 3, + }, + }, + "start": 68, + "type": "VariableDeclaration", + }, + Node { + "alternate": null, + "consequent": Node { + "body": Array [ + Node { + "end": 298, + "expression": Node { + "end": 297, + "left": Node { + "computed": false, + "end": 247, + "loc": SourceLocation { + "end": Position { + "column": 19, + "line": 5, + }, + "start": Position { + "column": 4, + "line": 5, + }, + }, + "object": Node { + "end": 234, + "loc": SourceLocation { + "end": Position { + "column": 6, + "line": 5, + }, + "identifierName": "ns", + "start": Position { + "column": 4, + "line": 5, + }, + }, + "name": "ns", + "start": 232, + "type": "Identifier", + }, + "property": Node { + "end": 247, + "loc": SourceLocation { + "end": Position { + "column": 19, + "line": 5, + }, + "identifierName": "activeMutant", + "start": Position { + "column": 7, + "line": 5, + }, + }, + "name": "activeMutant", + "start": 235, + "type": "Identifier", + }, + "start": 232, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 69, + "line": 5, + }, + "start": Position { + "column": 4, + "line": 5, + }, + }, + "operator": "=", + "right": Node { + "arguments": Array [ + Node { + "computed": false, + "end": 296, + "loc": SourceLocation { + "end": Position { + "column": 68, + "line": 5, + }, + "start": Position { + "column": 29, + "line": 5, + }, + }, + "object": Node { + "computed": false, + "end": 270, + "loc": SourceLocation { + "end": Position { + "column": 42, + "line": 5, + }, + "start": Position { + "column": 29, + "line": 5, + }, + }, + "object": Node { + "computed": false, + "end": 266, + "loc": SourceLocation { + "end": Position { + "column": 38, + "line": 5, + }, + "start": Position { + "column": 29, + "line": 5, + }, + }, + "object": Node { + "end": 258, + "loc": SourceLocation { + "end": Position { + "column": 30, + "line": 5, + }, + "identifierName": "g", + "start": Position { + "column": 29, + "line": 5, + }, + }, + "name": "g", + "start": 257, + "type": "Identifier", + }, + "property": Node { + "end": 266, + "loc": SourceLocation { + "end": Position { + "column": 38, + "line": 5, + }, + "identifierName": "process", + "start": Position { + "column": 31, + "line": 5, + }, + }, + "name": "process", + "start": 259, + "type": "Identifier", + }, + "start": 257, + "type": "MemberExpression", + }, + "property": Node { + "end": 270, + "loc": SourceLocation { + "end": Position { + "column": 42, + "line": 5, + }, + "identifierName": "env", + "start": Position { + "column": 39, + "line": 5, + }, + }, + "name": "env", + "start": 267, + "type": "Identifier", + }, + "start": 257, + "type": "MemberExpression", + }, + "property": Node { + "end": 296, + "loc": SourceLocation { + "end": Position { + "column": 68, + "line": 5, + }, + "identifierName": "__STRYKER_ACTIVE_MUTANT__", + "start": Position { + "column": 43, + "line": 5, + }, + }, + "name": "__STRYKER_ACTIVE_MUTANT__", + "start": 271, + "type": "Identifier", + }, + "start": 257, + "type": "MemberExpression", + }, + ], + "callee": Node { + "end": 256, + "loc": SourceLocation { + "end": Position { + "column": 28, + "line": 5, + }, + "identifierName": "Number", + "start": Position { + "column": 22, + "line": 5, + }, + }, + "name": "Number", + "start": 250, + "type": "Identifier", + }, + "end": 297, + "loc": SourceLocation { + "end": Position { + "column": 69, + "line": 5, + }, + "start": Position { + "column": 22, + "line": 5, + }, + }, + "start": 250, + "type": "CallExpression", + }, + "start": 232, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 70, + "line": 5, + }, + "start": Position { + "column": 4, + "line": 5, + }, + }, + "start": 232, + "type": "ExpressionStatement", + }, + ], + "directives": Array [], + "end": 302, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 6, + }, + "start": Position { + "column": 110, + "line": 4, + }, + }, + "start": 226, + "type": "BlockStatement", + }, + "end": 302, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 6, + }, + "start": Position { + "column": 2, + "line": 4, + }, + }, + "start": 118, + "test": Node { + "end": 224, + "left": Node { + "end": 181, + "left": Node { + "end": 164, + "left": Node { + "end": 151, + "left": Node { + "computed": false, + "end": 137, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 4, + }, + "start": Position { + "column": 6, + "line": 4, + }, + }, + "object": Node { + "end": 124, + "loc": SourceLocation { + "end": Position { + "column": 8, + "line": 4, + }, + "identifierName": "ns", + "start": Position { + "column": 6, + "line": 4, + }, + }, + "name": "ns", + "start": 122, + "type": "Identifier", + }, + "property": Node { + "end": 137, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 4, + }, + "identifierName": "activeMutant", + "start": Position { + "column": 9, + "line": 4, + }, + }, + "name": "activeMutant", + "start": 125, + "type": "Identifier", + }, + "start": 122, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 35, + "line": 4, + }, + "start": Position { + "column": 6, + "line": 4, + }, + }, + "operator": "===", + "right": Node { + "end": 151, + "loc": SourceLocation { + "end": Position { + "column": 35, + "line": 4, + }, + "identifierName": "undefined", + "start": Position { + "column": 26, + "line": 4, + }, + }, + "name": "undefined", + "start": 142, + "type": "Identifier", + }, + "start": 122, + "type": "BinaryExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 48, + "line": 4, + }, + "start": Position { + "column": 6, + "line": 4, + }, + }, + "operator": "&&", + "right": Node { + "computed": false, + "end": 164, + "loc": SourceLocation { + "end": Position { + "column": 48, + "line": 4, + }, + "start": Position { + "column": 39, + "line": 4, + }, + }, + "object": Node { + "end": 156, + "loc": SourceLocation { + "end": Position { + "column": 40, + "line": 4, + }, + "identifierName": "g", + "start": Position { + "column": 39, + "line": 4, + }, + }, + "name": "g", + "start": 155, + "type": "Identifier", + }, + "property": Node { + "end": 164, + "loc": SourceLocation { + "end": Position { + "column": 48, + "line": 4, + }, + "identifierName": "process", + "start": Position { + "column": 41, + "line": 4, + }, + }, + "name": "process", + "start": 157, + "type": "Identifier", + }, + "start": 155, + "type": "MemberExpression", + }, + "start": 122, + "type": "LogicalExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 65, + "line": 4, + }, + "start": Position { + "column": 6, + "line": 4, + }, + }, + "operator": "&&", + "right": Node { + "computed": false, + "end": 181, + "loc": SourceLocation { + "end": Position { + "column": 65, + "line": 4, + }, + "start": Position { + "column": 52, + "line": 4, + }, + }, + "object": Node { + "computed": false, + "end": 177, + "loc": SourceLocation { + "end": Position { + "column": 61, + "line": 4, + }, + "start": Position { + "column": 52, + "line": 4, + }, + }, + "object": Node { + "end": 169, + "loc": SourceLocation { + "end": Position { + "column": 53, + "line": 4, + }, + "identifierName": "g", + "start": Position { + "column": 52, + "line": 4, + }, + }, + "name": "g", + "start": 168, + "type": "Identifier", + }, + "property": Node { + "end": 177, + "loc": SourceLocation { + "end": Position { + "column": 61, + "line": 4, + }, + "identifierName": "process", + "start": Position { + "column": 54, + "line": 4, + }, + }, + "name": "process", + "start": 170, + "type": "Identifier", + }, + "start": 168, + "type": "MemberExpression", + }, + "property": Node { + "end": 181, + "loc": SourceLocation { + "end": Position { + "column": 65, + "line": 4, + }, + "identifierName": "env", + "start": Position { + "column": 62, + "line": 4, + }, + }, + "name": "env", + "start": 178, + "type": "Identifier", + }, + "start": 168, + "type": "MemberExpression", + }, + "start": 122, + "type": "LogicalExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 108, + "line": 4, + }, + "start": Position { + "column": 6, + "line": 4, + }, + }, + "operator": "&&", + "right": Node { + "computed": false, + "end": 224, + "loc": SourceLocation { + "end": Position { + "column": 108, + "line": 4, + }, + "start": Position { + "column": 69, + "line": 4, + }, + }, + "object": Node { + "computed": false, + "end": 198, + "loc": SourceLocation { + "end": Position { + "column": 82, + "line": 4, + }, + "start": Position { + "column": 69, + "line": 4, + }, + }, + "object": Node { + "computed": false, + "end": 194, + "loc": SourceLocation { + "end": Position { + "column": 78, + "line": 4, + }, + "start": Position { + "column": 69, + "line": 4, + }, + }, + "object": Node { + "end": 186, + "loc": SourceLocation { + "end": Position { + "column": 70, + "line": 4, + }, + "identifierName": "g", + "start": Position { + "column": 69, + "line": 4, + }, + }, + "name": "g", + "start": 185, + "type": "Identifier", + }, + "property": Node { + "end": 194, + "loc": SourceLocation { + "end": Position { + "column": 78, + "line": 4, + }, + "identifierName": "process", + "start": Position { + "column": 71, + "line": 4, + }, + }, + "name": "process", + "start": 187, + "type": "Identifier", + }, + "start": 185, + "type": "MemberExpression", + }, + "property": Node { + "end": 198, + "loc": SourceLocation { + "end": Position { + "column": 82, + "line": 4, + }, + "identifierName": "env", + "start": Position { + "column": 79, + "line": 4, + }, + }, + "name": "env", + "start": 195, + "type": "Identifier", + }, + "start": 185, + "type": "MemberExpression", + }, + "property": Node { + "end": 224, + "loc": SourceLocation { + "end": Position { + "column": 108, + "line": 4, + }, + "identifierName": "__STRYKER_ACTIVE_MUTANT__", + "start": Position { + "column": 83, + "line": 4, + }, + }, + "name": "__STRYKER_ACTIVE_MUTANT__", + "start": 199, + "type": "Identifier", + }, + "start": 185, + "type": "MemberExpression", + }, + "start": 122, + "type": "LogicalExpression", + }, + "type": "IfStatement", + }, + Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "argument": Node { + "end": 341, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 8, + }, + "identifierName": "ns", + "start": Position { + "column": 11, + "line": 8, + }, + }, + "name": "ns", + "start": 339, + "type": "Identifier", + }, + "end": 342, + "loc": SourceLocation { + "end": Position { + "column": 14, + "line": 8, + }, + "start": Position { + "column": 4, + "line": 8, + }, + }, + "start": 332, + "type": "ReturnStatement", + }, + ], + "directives": Array [], + "end": 346, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 9, + }, + "start": Position { + "column": 23, + "line": 7, + }, + }, + "start": 326, + "type": "BlockStatement", + }, + "end": 346, + "generator": false, + "id": Node { + "end": 324, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 7, + }, + "identifierName": "retrieveNS", + "start": Position { + "column": 11, + "line": 7, + }, + }, + "name": "retrieveNS", + "start": 314, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 9, + }, + "start": Position { + "column": 2, + "line": 7, + }, + }, + "params": Array [], + "start": 305, + "type": "FunctionDeclaration", + }, + Node { + "end": 375, + "expression": Node { + "end": 374, + "left": Node { + "end": 361, + "loc": SourceLocation { + "end": Position { + "column": 14, + "line": 10, + }, + "identifierName": "stryNS_9fa48", + "start": Position { + "column": 2, + "line": 10, + }, + }, + "name": "stryNS_9fa48", + "start": 349, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 27, + "line": 10, + }, + "start": Position { + "column": 2, + "line": 10, + }, + }, + "operator": "=", + "right": Node { + "end": 374, + "loc": SourceLocation { + "end": Position { + "column": 27, + "line": 10, + }, + "identifierName": "retrieveNS", + "start": Position { + "column": 17, + "line": 10, + }, + }, + "name": "retrieveNS", + "start": 364, + "type": "Identifier", + }, + "start": 349, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 28, + "line": 10, + }, + "start": Position { + "column": 2, + "line": 10, + }, + }, + "start": 349, + "type": "ExpressionStatement", + }, + Node { + "argument": Node { + "arguments": Array [], + "callee": Node { + "end": 395, + "loc": SourceLocation { + "end": Position { + "column": 19, + "line": 11, + }, + "identifierName": "retrieveNS", + "start": Position { + "column": 9, + "line": 11, + }, + }, + "name": "retrieveNS", + "start": 385, + "type": "Identifier", + }, + "end": 397, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 11, + }, + "start": Position { + "column": 9, + "line": 11, + }, + }, + "start": 385, + "type": "CallExpression", + }, + "end": 398, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 11, + }, + "start": Position { + "column": 2, + "line": 11, + }, + }, + "start": 378, + "type": "ReturnStatement", + }, + ], + "directives": Array [], + "end": 400, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 12, + }, + "start": Position { + "column": 23, + "line": 1, + }, + }, + "start": 23, + "type": "BlockStatement", + }, + "end": 400, + "generator": false, + "id": Node { + "end": 21, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 1, + }, + "identifierName": "stryNS_9fa48", + "start": Position { + "column": 9, + "line": 1, + }, + }, + "name": "stryNS_9fa48", + "start": 9, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 12, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "params": Array [], + "start": 0, + "type": "FunctionDeclaration", + }, + Node { + "end": 416, + "expression": Node { + "arguments": Array [], + "callee": Node { + "end": 413, + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 13, + }, + "identifierName": "stryNS_9fa48", + "start": Position { + "column": 0, + "line": 13, + }, + }, + "name": "stryNS_9fa48", + "start": 401, + "type": "Identifier", + }, + "end": 415, + "loc": SourceLocation { + "end": Position { + "column": 14, + "line": 13, + }, + "start": Position { + "column": 0, + "line": 13, + }, + }, + "start": 401, + "type": "CallExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 13, + }, + "start": Position { + "column": 0, + "line": 13, + }, + }, + "start": 401, + "type": "ExpressionStatement", + }, + Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "declarations": Array [ + Node { + "end": 470, + "id": Node { + "end": 453, + "loc": SourceLocation { + "end": Position { + "column": 8, + "line": 16, + }, + "identifierName": "ns", + "start": Position { + "column": 6, + "line": 16, + }, + }, + "name": "ns", + "start": 451, + "type": "Identifier", + }, + "init": Node { + "arguments": Array [], + "callee": Node { + "end": 468, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 16, + }, + "identifierName": "stryNS_9fa48", + "start": Position { + "column": 11, + "line": 16, + }, + }, + "name": "stryNS_9fa48", + "start": 456, + "type": "Identifier", + }, + "end": 470, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 16, + }, + "start": Position { + "column": 11, + "line": 16, + }, + }, + "start": 456, + "type": "CallExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 16, + }, + "start": Position { + "column": 6, + "line": 16, + }, + }, + "start": 451, + "type": "VariableDeclarator", + }, + ], + "end": 471, + "kind": "var", + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 16, + }, + "start": Position { + "column": 2, + "line": 16, + }, + }, + "start": 447, + "type": "VariableDeclaration", + }, + Node { + "declarations": Array [ + Node { + "end": 554, + "id": Node { + "end": 481, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 17, + }, + "identifierName": "cov", + "start": Position { + "column": 6, + "line": 17, + }, + }, + "name": "cov", + "start": 478, + "type": "Identifier", + }, + "init": Node { + "end": 554, + "left": Node { + "computed": false, + "end": 501, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 17, + }, + "start": Position { + "column": 12, + "line": 17, + }, + }, + "object": Node { + "end": 486, + "loc": SourceLocation { + "end": Position { + "column": 14, + "line": 17, + }, + "identifierName": "ns", + "start": Position { + "column": 12, + "line": 17, + }, + }, + "name": "ns", + "start": 484, + "type": "Identifier", + }, + "property": Node { + "end": 501, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 17, + }, + "identifierName": "mutantCoverage", + "start": Position { + "column": 15, + "line": 17, + }, + }, + "name": "mutantCoverage", + "start": 487, + "type": "Identifier", + }, + "start": 484, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 82, + "line": 17, + }, + "start": Position { + "column": 12, + "line": 17, + }, + }, + "operator": "||", + "right": Node { + "end": 553, + "extra": Object { + "parenStart": 505, + "parenthesized": true, + }, + "left": Node { + "computed": false, + "end": 523, + "loc": SourceLocation { + "end": Position { + "column": 51, + "line": 17, + }, + "start": Position { + "column": 34, + "line": 17, + }, + }, + "object": Node { + "end": 508, + "loc": SourceLocation { + "end": Position { + "column": 36, + "line": 17, + }, + "identifierName": "ns", + "start": Position { + "column": 34, + "line": 17, + }, + }, + "name": "ns", + "start": 506, + "type": "Identifier", + }, + "property": Node { + "end": 523, + "loc": SourceLocation { + "end": Position { + "column": 51, + "line": 17, + }, + "identifierName": "mutantCoverage", + "start": Position { + "column": 37, + "line": 17, + }, + }, + "name": "mutantCoverage", + "start": 509, + "type": "Identifier", + }, + "start": 506, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 81, + "line": 17, + }, + "start": Position { + "column": 34, + "line": 17, + }, + }, + "operator": "=", + "right": Node { + "end": 553, + "loc": SourceLocation { + "end": Position { + "column": 81, + "line": 17, + }, + "start": Position { + "column": 54, + "line": 17, + }, + }, + "properties": Array [ + Node { + "computed": false, + "end": 538, + "key": Node { + "end": 534, + "loc": SourceLocation { + "end": Position { + "column": 62, + "line": 17, + }, + "identifierName": "static", + "start": Position { + "column": 56, + "line": 17, + }, + }, + "name": "static", + "start": 528, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 66, + "line": 17, + }, + "start": Position { + "column": 56, + "line": 17, + }, + }, + "method": false, + "shorthand": false, + "start": 528, + "type": "ObjectProperty", + "value": Node { + "end": 538, + "loc": SourceLocation { + "end": Position { + "column": 66, + "line": 17, + }, + "start": Position { + "column": 64, + "line": 17, + }, + }, + "properties": Array [], + "start": 536, + "type": "ObjectExpression", + }, + }, + Node { + "computed": false, + "end": 551, + "key": Node { + "end": 547, + "loc": SourceLocation { + "end": Position { + "column": 75, + "line": 17, + }, + "identifierName": "perTest", + "start": Position { + "column": 68, + "line": 17, + }, + }, + "name": "perTest", + "start": 540, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 79, + "line": 17, + }, + "start": Position { + "column": 68, + "line": 17, + }, + }, + "method": false, + "shorthand": false, + "start": 540, + "type": "ObjectProperty", + "value": Node { + "end": 551, + "loc": SourceLocation { + "end": Position { + "column": 79, + "line": 17, + }, + "start": Position { + "column": 77, + "line": 17, + }, + }, + "properties": Array [], + "start": 549, + "type": "ObjectExpression", + }, + }, + ], + "start": 526, + "type": "ObjectExpression", + }, + "start": 506, + "type": "AssignmentExpression", + }, + "start": 484, + "type": "LogicalExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 82, + "line": 17, + }, + "start": Position { + "column": 6, + "line": 17, + }, + }, + "start": 478, + "type": "VariableDeclarator", + }, + ], + "end": 555, + "kind": "var", + "loc": SourceLocation { + "end": Position { + "column": 83, + "line": 17, + }, + "start": Position { + "column": 2, + "line": 17, + }, + }, + "start": 474, + "type": "VariableDeclaration", + }, + Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "declarations": Array [ + Node { + "end": 599, + "id": Node { + "end": 586, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 19, + }, + "identifierName": "c", + "start": Position { + "column": 8, + "line": 19, + }, + }, + "name": "c", + "start": 585, + "type": "Identifier", + }, + "init": Node { + "computed": false, + "end": 599, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 19, + }, + "start": Position { + "column": 12, + "line": 19, + }, + }, + "object": Node { + "end": 592, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 19, + }, + "identifierName": "cov", + "start": Position { + "column": 12, + "line": 19, + }, + }, + "name": "cov", + "start": 589, + "type": "Identifier", + }, + "property": Node { + "end": 599, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 19, + }, + "identifierName": "static", + "start": Position { + "column": 16, + "line": 19, + }, + }, + "name": "static", + "start": 593, + "type": "Identifier", + }, + "start": 589, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 19, + }, + "start": Position { + "column": 8, + "line": 19, + }, + }, + "start": 585, + "type": "VariableDeclarator", + }, + ], + "end": 600, + "kind": "var", + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 19, + }, + "start": Position { + "column": 4, + "line": 19, + }, + }, + "start": 581, + "type": "VariableDeclaration", + }, + Node { + "alternate": null, + "consequent": Node { + "body": Array [ + Node { + "end": 707, + "expression": Node { + "end": 706, + "left": Node { + "end": 636, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 21, + }, + "identifierName": "c", + "start": Position { + "column": 6, + "line": 21, + }, + }, + "name": "c", + "start": 635, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 77, + "line": 21, + }, + "start": Position { + "column": 6, + "line": 21, + }, + }, + "operator": "=", + "right": Node { + "end": 706, + "left": Node { + "computed": true, + "end": 668, + "loc": SourceLocation { + "end": Position { + "column": 39, + "line": 21, + }, + "start": Position { + "column": 10, + "line": 21, + }, + }, + "object": Node { + "computed": false, + "end": 650, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 21, + }, + "start": Position { + "column": 10, + "line": 21, + }, + }, + "object": Node { + "end": 642, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 21, + }, + "identifierName": "cov", + "start": Position { + "column": 10, + "line": 21, + }, + }, + "name": "cov", + "start": 639, + "type": "Identifier", + }, + "property": Node { + "end": 650, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 21, + }, + "identifierName": "perTest", + "start": Position { + "column": 14, + "line": 21, + }, + }, + "name": "perTest", + "start": 643, + "type": "Identifier", + }, + "start": 639, + "type": "MemberExpression", + }, + "property": Node { + "computed": false, + "end": 667, + "loc": SourceLocation { + "end": Position { + "column": 38, + "line": 21, + }, + "start": Position { + "column": 22, + "line": 21, + }, + }, + "object": Node { + "end": 653, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 21, + }, + "identifierName": "ns", + "start": Position { + "column": 22, + "line": 21, + }, + }, + "name": "ns", + "start": 651, + "type": "Identifier", + }, + "property": Node { + "end": 667, + "loc": SourceLocation { + "end": Position { + "column": 38, + "line": 21, + }, + "identifierName": "currentTestId", + "start": Position { + "column": 25, + "line": 21, + }, + }, + "name": "currentTestId", + "start": 654, + "type": "Identifier", + }, + "start": 651, + "type": "MemberExpression", + }, + "start": 639, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 77, + "line": 21, + }, + "start": Position { + "column": 10, + "line": 21, + }, + }, + "operator": "=", + "right": Node { + "end": 706, + "left": Node { + "computed": true, + "end": 700, + "loc": SourceLocation { + "end": Position { + "column": 71, + "line": 21, + }, + "start": Position { + "column": 42, + "line": 21, + }, + }, + "object": Node { + "computed": false, + "end": 682, + "loc": SourceLocation { + "end": Position { + "column": 53, + "line": 21, + }, + "start": Position { + "column": 42, + "line": 21, + }, + }, + "object": Node { + "end": 674, + "loc": SourceLocation { + "end": Position { + "column": 45, + "line": 21, + }, + "identifierName": "cov", + "start": Position { + "column": 42, + "line": 21, + }, + }, + "name": "cov", + "start": 671, + "type": "Identifier", + }, + "property": Node { + "end": 682, + "loc": SourceLocation { + "end": Position { + "column": 53, + "line": 21, + }, + "identifierName": "perTest", + "start": Position { + "column": 46, + "line": 21, + }, + }, + "name": "perTest", + "start": 675, + "type": "Identifier", + }, + "start": 671, + "type": "MemberExpression", + }, + "property": Node { + "computed": false, + "end": 699, + "loc": SourceLocation { + "end": Position { + "column": 70, + "line": 21, + }, + "start": Position { + "column": 54, + "line": 21, + }, + }, + "object": Node { + "end": 685, + "loc": SourceLocation { + "end": Position { + "column": 56, + "line": 21, + }, + "identifierName": "ns", + "start": Position { + "column": 54, + "line": 21, + }, + }, + "name": "ns", + "start": 683, + "type": "Identifier", + }, + "property": Node { + "end": 699, + "loc": SourceLocation { + "end": Position { + "column": 70, + "line": 21, + }, + "identifierName": "currentTestId", + "start": Position { + "column": 57, + "line": 21, + }, + }, + "name": "currentTestId", + "start": 686, + "type": "Identifier", + }, + "start": 683, + "type": "MemberExpression", + }, + "start": 671, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 77, + "line": 21, + }, + "start": Position { + "column": 42, + "line": 21, + }, + }, + "operator": "||", + "right": Node { + "end": 706, + "loc": SourceLocation { + "end": Position { + "column": 77, + "line": 21, + }, + "start": Position { + "column": 75, + "line": 21, + }, + }, + "properties": Array [], + "start": 704, + "type": "ObjectExpression", + }, + "start": 671, + "type": "LogicalExpression", + }, + "start": 639, + "type": "AssignmentExpression", + }, + "start": 635, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 78, + "line": 21, + }, + "start": Position { + "column": 6, + "line": 21, + }, + }, + "start": 635, + "type": "ExpressionStatement", + }, + ], + "directives": Array [], + "end": 713, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 22, + }, + "start": Position { + "column": 26, + "line": 20, + }, + }, + "start": 627, + "type": "BlockStatement", + }, + "end": 713, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 22, + }, + "start": Position { + "column": 4, + "line": 20, + }, + }, + "start": 605, + "test": Node { + "computed": false, + "end": 625, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 20, + }, + "start": Position { + "column": 8, + "line": 20, + }, + }, + "object": Node { + "end": 611, + "loc": SourceLocation { + "end": Position { + "column": 10, + "line": 20, + }, + "identifierName": "ns", + "start": Position { + "column": 8, + "line": 20, + }, + }, + "name": "ns", + "start": 609, + "type": "Identifier", + }, + "property": Node { + "end": 625, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 20, + }, + "identifierName": "currentTestId", + "start": Position { + "column": 11, + "line": 20, + }, + }, + "name": "currentTestId", + "start": 612, + "type": "Identifier", + }, + "start": 609, + "type": "MemberExpression", + }, + "type": "IfStatement", + }, + Node { + "declarations": Array [ + Node { + "end": 735, + "id": Node { + "end": 723, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 23, + }, + "identifierName": "a", + "start": Position { + "column": 8, + "line": 23, + }, + }, + "name": "a", + "start": 722, + "type": "Identifier", + }, + "init": Node { + "end": 735, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 23, + }, + "identifierName": "arguments", + "start": Position { + "column": 12, + "line": 23, + }, + }, + "name": "arguments", + "start": 726, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 23, + }, + "start": Position { + "column": 8, + "line": 23, + }, + }, + "start": 722, + "type": "VariableDeclarator", + }, + ], + "end": 736, + "kind": "var", + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 23, + }, + "start": Position { + "column": 4, + "line": 23, + }, + }, + "start": 718, + "type": "VariableDeclaration", + }, + Node { + "body": Node { + "body": Array [ + Node { + "end": 809, + "expression": Node { + "end": 808, + "left": Node { + "computed": true, + "end": 787, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 25, + }, + "start": Position { + "column": 6, + "line": 25, + }, + }, + "object": Node { + "end": 781, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 25, + }, + "identifierName": "c", + "start": Position { + "column": 6, + "line": 25, + }, + }, + "name": "c", + "start": 780, + "type": "Identifier", + }, + "property": Node { + "computed": true, + "end": 786, + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 25, + }, + "start": Position { + "column": 8, + "line": 25, + }, + }, + "object": Node { + "end": 783, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 25, + }, + "identifierName": "a", + "start": Position { + "column": 8, + "line": 25, + }, + }, + "name": "a", + "start": 782, + "type": "Identifier", + }, + "property": Node { + "end": 785, + "loc": SourceLocation { + "end": Position { + "column": 11, + "line": 25, + }, + "identifierName": "i", + "start": Position { + "column": 10, + "line": 25, + }, + }, + "name": "i", + "start": 784, + "type": "Identifier", + }, + "start": 782, + "type": "MemberExpression", + }, + "start": 780, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 25, + }, + "start": Position { + "column": 6, + "line": 25, + }, + }, + "operator": "=", + "right": Node { + "end": 808, + "left": Node { + "end": 803, + "extra": Object { + "parenStart": 790, + "parenthesized": true, + }, + "left": Node { + "computed": true, + "end": 798, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 25, + }, + "start": Position { + "column": 17, + "line": 25, + }, + }, + "object": Node { + "end": 792, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 25, + }, + "identifierName": "c", + "start": Position { + "column": 17, + "line": 25, + }, + }, + "name": "c", + "start": 791, + "type": "Identifier", + }, + "property": Node { + "computed": true, + "end": 797, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 25, + }, + "start": Position { + "column": 19, + "line": 25, + }, + }, + "object": Node { + "end": 794, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 25, + }, + "identifierName": "a", + "start": Position { + "column": 19, + "line": 25, + }, + }, + "name": "a", + "start": 793, + "type": "Identifier", + }, + "property": Node { + "end": 796, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 25, + }, + "identifierName": "i", + "start": Position { + "column": 21, + "line": 25, + }, + }, + "name": "i", + "start": 795, + "type": "Identifier", + }, + "start": 793, + "type": "MemberExpression", + }, + "start": 791, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 25, + }, + "start": Position { + "column": 17, + "line": 25, + }, + }, + "operator": "||", + "right": Node { + "end": 803, + "extra": Object { + "raw": "0", + "rawValue": 0, + }, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 25, + }, + "start": Position { + "column": 28, + "line": 25, + }, + }, + "start": 802, + "type": "NumericLiteral", + "value": 0, + }, + "start": 791, + "type": "LogicalExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 25, + }, + "start": Position { + "column": 16, + "line": 25, + }, + }, + "operator": "+", + "right": Node { + "end": 808, + "extra": Object { + "raw": "1", + "rawValue": 1, + }, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 25, + }, + "start": Position { + "column": 33, + "line": 25, + }, + }, + "start": 807, + "type": "NumericLiteral", + "value": 1, + }, + "start": 790, + "type": "BinaryExpression", + }, + "start": 780, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 35, + "line": 25, + }, + "start": Position { + "column": 6, + "line": 25, + }, + }, + "start": 780, + "type": "ExpressionStatement", + }, + ], + "directives": Array [], + "end": 815, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 26, + }, + "start": Position { + "column": 35, + "line": 24, + }, + }, + "start": 772, + "type": "BlockStatement", + }, + "end": 815, + "init": Node { + "declarations": Array [ + Node { + "end": 752, + "id": Node { + "end": 750, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 24, + }, + "identifierName": "i", + "start": Position { + "column": 12, + "line": 24, + }, + }, + "name": "i", + "start": 749, + "type": "Identifier", + }, + "init": Node { + "end": 752, + "extra": Object { + "raw": "0", + "rawValue": 0, + }, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 24, + }, + "start": Position { + "column": 14, + "line": 24, + }, + }, + "start": 751, + "type": "NumericLiteral", + "value": 0, + }, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 24, + }, + "start": Position { + "column": 12, + "line": 24, + }, + }, + "start": 749, + "type": "VariableDeclarator", + }, + ], + "end": 752, + "kind": "var", + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 24, + }, + "start": Position { + "column": 8, + "line": 24, + }, + }, + "start": 745, + "type": "VariableDeclaration", + }, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 26, + }, + "start": Position { + "column": 4, + "line": 24, + }, + }, + "start": 741, + "test": Node { + "end": 766, + "left": Node { + "end": 755, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 24, + }, + "identifierName": "i", + "start": Position { + "column": 17, + "line": 24, + }, + }, + "name": "i", + "start": 754, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 24, + }, + "start": Position { + "column": 17, + "line": 24, + }, + }, + "operator": "<", + "right": Node { + "computed": false, + "end": 766, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 24, + }, + "start": Position { + "column": 21, + "line": 24, + }, + }, + "object": Node { + "end": 759, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 24, + }, + "identifierName": "a", + "start": Position { + "column": 21, + "line": 24, + }, + }, + "name": "a", + "start": 758, + "type": "Identifier", + }, + "property": Node { + "end": 766, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 24, + }, + "identifierName": "length", + "start": Position { + "column": 23, + "line": 24, + }, + }, + "name": "length", + "start": 760, + "type": "Identifier", + }, + "start": 758, + "type": "MemberExpression", + }, + "start": 754, + "type": "BinaryExpression", + }, + "type": "ForStatement", + "update": Node { + "argument": Node { + "end": 769, + "loc": SourceLocation { + "end": Position { + "column": 32, + "line": 24, + }, + "identifierName": "i", + "start": Position { + "column": 31, + "line": 24, + }, + }, + "name": "i", + "start": 768, + "type": "Identifier", + }, + "end": 771, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 24, + }, + "start": Position { + "column": 31, + "line": 24, + }, + }, + "operator": "++", + "prefix": false, + "start": 768, + "type": "UpdateExpression", + }, + }, + ], + "directives": Array [], + "end": 819, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 27, + }, + "start": Position { + "column": 19, + "line": 18, + }, + }, + "start": 575, + "type": "BlockStatement", + }, + "end": 819, + "generator": false, + "id": Node { + "end": 572, + "loc": SourceLocation { + "end": Position { + "column": 16, + "line": 18, + }, + "identifierName": "cover", + "start": Position { + "column": 11, + "line": 18, + }, + }, + "name": "cover", + "start": 567, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 27, + }, + "start": Position { + "column": 2, + "line": 18, + }, + }, + "params": Array [], + "start": 558, + "type": "FunctionDeclaration", + }, + Node { + "end": 844, + "expression": Node { + "end": 843, + "left": Node { + "end": 835, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 28, + }, + "identifierName": "stryCov_9fa48", + "start": Position { + "column": 2, + "line": 28, + }, + }, + "name": "stryCov_9fa48", + "start": 822, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 28, + }, + "start": Position { + "column": 2, + "line": 28, + }, + }, + "operator": "=", + "right": Node { + "end": 843, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 28, + }, + "identifierName": "cover", + "start": Position { + "column": 18, + "line": 28, + }, + }, + "name": "cover", + "start": 838, + "type": "Identifier", + }, + "start": 822, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 28, + }, + "start": Position { + "column": 2, + "line": 28, + }, + }, + "start": 822, + "type": "ExpressionStatement", + }, + Node { + "end": 876, + "expression": Node { + "arguments": Array [ + Node { + "end": 863, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 29, + }, + "start": Position { + "column": 14, + "line": 29, + }, + }, + "start": 859, + "type": "NullLiteral", + }, + Node { + "end": 874, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 29, + }, + "identifierName": "arguments", + "start": Position { + "column": 20, + "line": 29, + }, + }, + "name": "arguments", + "start": 865, + "type": "Identifier", + }, + ], + "callee": Node { + "computed": false, + "end": 858, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 29, + }, + "start": Position { + "column": 2, + "line": 29, + }, + }, + "object": Node { + "end": 852, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 29, + }, + "identifierName": "cover", + "start": Position { + "column": 2, + "line": 29, + }, + }, + "name": "cover", + "start": 847, + "type": "Identifier", + }, + "property": Node { + "end": 858, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 29, + }, + "identifierName": "apply", + "start": Position { + "column": 8, + "line": 29, + }, + }, + "name": "apply", + "start": 853, + "type": "Identifier", + }, + "start": 847, + "type": "MemberExpression", + }, + "end": 875, + "loc": SourceLocation { + "end": Position { + "column": 30, + "line": 29, + }, + "start": Position { + "column": 2, + "line": 29, + }, + }, + "start": 847, + "type": "CallExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 31, + "line": 29, + }, + "start": Position { + "column": 2, + "line": 29, + }, + }, + "start": 847, + "type": "ExpressionStatement", + }, + ], + "directives": Array [], + "end": 878, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 30, + }, + "start": Position { + "column": 25, + "line": 15, + }, + }, + "start": 443, + "type": "BlockStatement", + }, + "end": 878, + "generator": false, + "id": Node { + "end": 440, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 15, + }, + "identifierName": "stryCov_9fa48", + "start": Position { + "column": 9, + "line": 15, + }, + }, + "name": "stryCov_9fa48", + "start": 427, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 30, + }, + "start": Position { + "column": 0, + "line": 15, + }, + }, + "params": Array [], + "start": 418, + "type": "FunctionDeclaration", + }, + Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "declarations": Array [ + Node { + "end": 936, + "id": Node { + "end": 919, + "loc": SourceLocation { + "end": Position { + "column": 8, + "line": 32, + }, + "identifierName": "ns", + "start": Position { + "column": 6, + "line": 32, + }, + }, + "name": "ns", + "start": 917, + "type": "Identifier", + }, + "init": Node { + "arguments": Array [], + "callee": Node { + "end": 934, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 32, + }, + "identifierName": "stryNS_9fa48", + "start": Position { + "column": 11, + "line": 32, + }, + }, + "name": "stryNS_9fa48", + "start": 922, + "type": "Identifier", + }, + "end": 936, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 32, + }, + "start": Position { + "column": 11, + "line": 32, + }, + }, + "start": 922, + "type": "CallExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 32, + }, + "start": Position { + "column": 6, + "line": 32, + }, + }, + "start": 917, + "type": "VariableDeclarator", + }, + ], + "end": 937, + "kind": "var", + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 32, + }, + "start": Position { + "column": 2, + "line": 32, + }, + }, + "start": 913, + "type": "VariableDeclaration", + }, + Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "argument": Node { + "end": 997, + "left": Node { + "computed": false, + "end": 990, + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 34, + }, + "start": Position { + "column": 11, + "line": 34, + }, + }, + "object": Node { + "end": 977, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 34, + }, + "identifierName": "ns", + "start": Position { + "column": 11, + "line": 34, + }, + }, + "name": "ns", + "start": 975, + "type": "Identifier", + }, + "property": Node { + "end": 990, + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 34, + }, + "identifierName": "activeMutant", + "start": Position { + "column": 14, + "line": 34, + }, + }, + "name": "activeMutant", + "start": 978, + "type": "Identifier", + }, + "start": 975, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 33, + "line": 34, + }, + "start": Position { + "column": 11, + "line": 34, + }, + }, + "operator": "===", + "right": Node { + "end": 997, + "loc": SourceLocation { + "end": Position { + "column": 33, + "line": 34, + }, + "identifierName": "id", + "start": Position { + "column": 31, + "line": 34, + }, + }, + "name": "id", + "start": 995, + "type": "Identifier", + }, + "start": 975, + "type": "BinaryExpression", + }, + "end": 998, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 34, + }, + "start": Position { + "column": 4, + "line": 34, + }, + }, + "start": 968, + "type": "ReturnStatement", + }, + ], + "directives": Array [], + "end": 1002, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 35, + }, + "start": Position { + "column": 24, + "line": 33, + }, + }, + "start": 962, + "type": "BlockStatement", + }, + "end": 1002, + "generator": false, + "id": Node { + "end": 957, + "loc": SourceLocation { + "end": Position { + "column": 19, + "line": 33, + }, + "identifierName": "isActive", + "start": Position { + "column": 11, + "line": 33, + }, + }, + "name": "isActive", + "start": 949, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 35, + }, + "start": Position { + "column": 2, + "line": 33, + }, + }, + "params": Array [ + Node { + "end": 960, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 33, + }, + "identifierName": "id", + "start": Position { + "column": 20, + "line": 33, + }, + }, + "name": "id", + "start": 958, + "type": "Identifier", + }, + ], + "start": 940, + "type": "FunctionDeclaration", + }, + Node { + "end": 1033, + "expression": Node { + "end": 1032, + "left": Node { + "end": 1021, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 36, + }, + "identifierName": "stryMutAct_9fa48", + "start": Position { + "column": 2, + "line": 36, + }, + }, + "name": "stryMutAct_9fa48", + "start": 1005, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 36, + }, + "start": Position { + "column": 2, + "line": 36, + }, + }, + "operator": "=", + "right": Node { + "end": 1032, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 36, + }, + "identifierName": "isActive", + "start": Position { + "column": 21, + "line": 36, + }, + }, + "name": "isActive", + "start": 1024, + "type": "Identifier", + }, + "start": 1005, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 30, + "line": 36, + }, + "start": Position { + "column": 2, + "line": 36, + }, + }, + "start": 1005, + "type": "ExpressionStatement", + }, + Node { + "argument": Node { + "arguments": Array [ + Node { + "end": 1054, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 37, + }, + "identifierName": "id", + "start": Position { + "column": 18, + "line": 37, + }, + }, + "name": "id", + "start": 1052, + "type": "Identifier", + }, + ], + "callee": Node { + "end": 1051, + "loc": SourceLocation { + "end": Position { + "column": 17, + "line": 37, + }, + "identifierName": "isActive", + "start": Position { + "column": 9, + "line": 37, + }, + }, + "name": "isActive", + "start": 1043, + "type": "Identifier", + }, + "end": 1055, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 37, + }, + "start": Position { + "column": 9, + "line": 37, + }, + }, + "start": 1043, + "type": "CallExpression", + }, + "end": 1056, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 37, + }, + "start": Position { + "column": 2, + "line": 37, + }, + }, + "start": 1036, + "type": "ReturnStatement", + }, + ], + "directives": Array [], + "end": 1058, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 38, + }, + "start": Position { + "column": 30, + "line": 31, + }, + }, + "start": 909, + "type": "BlockStatement", + }, + "end": 1058, + "generator": false, + "id": Node { + "end": 904, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 31, + }, + "identifierName": "stryMutAct_9fa48", + "start": Position { + "column": 9, + "line": 31, + }, + }, + "name": "stryMutAct_9fa48", + "start": 888, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 38, + }, + "start": Position { + "column": 0, + "line": 31, + }, + }, + "params": Array [ + Node { + "end": 907, + "loc": SourceLocation { + "end": Position { + "column": 28, + "line": 31, + }, + "identifierName": "id", + "start": Position { + "column": 26, + "line": 31, + }, + }, + "name": "id", + "start": 905, + "type": "Identifier", + }, + ], + "start": 879, + "type": "FunctionDeclaration", + }, + Node { + "declarations": Array [ + Node { + "end": 18, + "id": Node { + "end": 9, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 1, + }, + "identifierName": "foo", + "start": Position { + "column": 6, + "line": 1, + }, + }, + "name": "foo", + "start": 6, + "type": "Identifier", + }, + "init": Object { + "alternate": Object { + "expressions": Array [ + Object { + "arguments": Array [ + Object { + "type": "NumericLiteral", + "value": 0, + }, + ], + "callee": Object { + "name": "stryCov_9fa48", + "type": "Identifier", + }, + "type": "CallExpression", + }, + Node { + "end": 18, + "innerComments": null, + "leadingComments": null, + "left": Node { + "end": 14, + "extra": Object { + "raw": "40", + "rawValue": 40, + }, + "loc": SourceLocation { + "end": Position { + "column": 14, + "line": 1, + }, + "start": Position { + "column": 12, + "line": 1, + }, + }, + "start": 12, + "type": "NumericLiteral", + "value": 40, + }, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 1, + }, + "start": Position { + "column": 12, + "line": 1, + }, + }, + "operator": "+", + "right": Node { + "end": 18, + "extra": Object { + "raw": "2", + "rawValue": 2, + }, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 1, + }, + "start": Position { + "column": 17, + "line": 1, + }, + }, + "start": 17, + "type": "NumericLiteral", + "value": 2, + }, + "start": 12, + "trailingComments": null, + "type": "BinaryExpression", + }, + ], + "innerComments": null, + "leadingComments": null, + "trailingComments": null, + "type": "SequenceExpression", + }, + "consequent": Object { + "end": 18, + "left": Node { + "end": 14, + "extra": Object { + "raw": "40", + "rawValue": 40, + }, + "loc": SourceLocation { + "end": Position { + "column": 14, + "line": 1, + }, + "start": Position { + "column": 12, + "line": 1, + }, + }, + "start": 12, + "type": "NumericLiteral", + "value": 40, + }, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 1, + }, + "start": Position { + "column": 12, + "line": 1, + }, + }, + "operator": "-", + "right": Node { + "end": 18, + "extra": Object { + "raw": "2", + "rawValue": 2, + }, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 1, + }, + "start": Position { + "column": 17, + "line": 1, + }, + }, + "start": 17, + "type": "NumericLiteral", + "value": 2, + }, + "start": 12, + "type": "BinaryExpression", + }, + "innerComments": Array [], + "leadingComments": Array [], + "test": Object { + "arguments": Array [ + Object { + "type": "NumericLiteral", + "value": 0, + }, + ], + "callee": Object { + "name": "stryMutAct_9fa48", + "type": "Identifier", + }, + "type": "CallExpression", + }, + "trailingComments": Array [], + "type": "ConditionalExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 1, + }, + "start": Position { + "column": 6, + "line": 1, + }, + }, + "start": 6, + "type": "VariableDeclarator", + }, + ], + "end": 18, + "kind": "const", + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 1, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "start": 0, + "type": "VariableDeclaration", + }, + ], + "directives": Array [], + "end": 18, + "interpreter": null, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 1, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "sourceType": "module", + "start": 0, + "type": "Program", + }, + "start": 0, + "type": "File", + }, +} +`; + +exports[`transformers integration should transform a ts file 1`] = ` +Object { + "format": "ts", + "originFileName": "example.ts", + "rawContent": "const foo: number = 40 + 2", + "root": Node { + "comments": Array [], + "end": 26, + "errors": Array [], + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 1, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "program": Node { + "body": Array [ + Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "declarations": Array [ + Node { + "end": 64, + "id": Node { + "end": 32, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 2, + }, + "identifierName": "g", + "start": Position { + "column": 6, + "line": 2, + }, + }, + "name": "g", + "start": 31, + "type": "Identifier", + }, + "init": Node { + "arguments": Array [], + "callee": Node { + "arguments": Array [ + Node { + "end": 61, + "extra": Object { + "raw": "\\"return this\\"", + "rawValue": "return this", + }, + "loc": SourceLocation { + "end": Position { + "column": 36, + "line": 2, + }, + "start": Position { + "column": 23, + "line": 2, + }, + }, + "start": 48, + "type": "StringLiteral", + "value": "return this", + }, + ], + "callee": Node { + "end": 47, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 2, + }, + "identifierName": "Function", + "start": Position { + "column": 14, + "line": 2, + }, + }, + "name": "Function", + "start": 39, + "type": "Identifier", + }, + "end": 62, + "loc": SourceLocation { + "end": Position { + "column": 37, + "line": 2, + }, + "start": Position { + "column": 10, + "line": 2, + }, + }, + "start": 35, + "type": "NewExpression", + }, + "end": 64, + "loc": SourceLocation { + "end": Position { + "column": 39, + "line": 2, + }, + "start": Position { + "column": 10, + "line": 2, + }, + }, + "start": 35, + "type": "CallExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 39, + "line": 2, + }, + "start": Position { + "column": 6, + "line": 2, + }, + }, + "start": 31, + "type": "VariableDeclarator", + }, + ], + "end": 65, + "kind": "var", + "loc": SourceLocation { + "end": Position { + "column": 40, + "line": 2, + }, + "start": Position { + "column": 2, + "line": 2, + }, + }, + "start": 27, + "type": "VariableDeclaration", + }, + Node { + "declarations": Array [ + Node { + "end": 114, + "id": Node { + "end": 74, + "loc": SourceLocation { + "end": Position { + "column": 8, + "line": 3, + }, + "identifierName": "ns", + "start": Position { + "column": 6, + "line": 3, + }, + }, + "name": "ns", + "start": 72, + "type": "Identifier", + }, + "init": Node { + "end": 114, + "left": Node { + "computed": false, + "end": 90, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 3, + }, + "start": Position { + "column": 11, + "line": 3, + }, + }, + "object": Node { + "end": 78, + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 3, + }, + "identifierName": "g", + "start": Position { + "column": 11, + "line": 3, + }, + }, + "name": "g", + "start": 77, + "type": "Identifier", + }, + "property": Node { + "end": 90, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 3, + }, + "identifierName": "__stryker__", + "start": Position { + "column": 13, + "line": 3, + }, + }, + "name": "__stryker__", + "start": 79, + "type": "Identifier", + }, + "start": 77, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 48, + "line": 3, + }, + "start": Position { + "column": 11, + "line": 3, + }, + }, + "operator": "||", + "right": Node { + "end": 113, + "extra": Object { + "parenStart": 94, + "parenthesized": true, + }, + "left": Node { + "computed": false, + "end": 108, + "loc": SourceLocation { + "end": Position { + "column": 42, + "line": 3, + }, + "start": Position { + "column": 29, + "line": 3, + }, + }, + "object": Node { + "end": 96, + "loc": SourceLocation { + "end": Position { + "column": 30, + "line": 3, + }, + "identifierName": "g", + "start": Position { + "column": 29, + "line": 3, + }, + }, + "name": "g", + "start": 95, + "type": "Identifier", + }, + "property": Node { + "end": 108, + "loc": SourceLocation { + "end": Position { + "column": 42, + "line": 3, + }, + "identifierName": "__stryker__", + "start": Position { + "column": 31, + "line": 3, + }, + }, + "name": "__stryker__", + "start": 97, + "type": "Identifier", + }, + "start": 95, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 47, + "line": 3, + }, + "start": Position { + "column": 29, + "line": 3, + }, + }, + "operator": "=", + "right": Node { + "end": 113, + "loc": SourceLocation { + "end": Position { + "column": 47, + "line": 3, + }, + "start": Position { + "column": 45, + "line": 3, + }, + }, + "properties": Array [], + "start": 111, + "type": "ObjectExpression", + }, + "start": 95, + "type": "AssignmentExpression", + }, + "start": 77, + "type": "LogicalExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 48, + "line": 3, + }, + "start": Position { + "column": 6, + "line": 3, + }, + }, + "start": 72, + "type": "VariableDeclarator", + }, + ], + "end": 115, + "kind": "var", + "loc": SourceLocation { + "end": Position { + "column": 49, + "line": 3, + }, + "start": Position { + "column": 2, + "line": 3, + }, + }, + "start": 68, + "type": "VariableDeclaration", + }, + Node { + "alternate": null, + "consequent": Node { + "body": Array [ + Node { + "end": 298, + "expression": Node { + "end": 297, + "left": Node { + "computed": false, + "end": 247, + "loc": SourceLocation { + "end": Position { + "column": 19, + "line": 5, + }, + "start": Position { + "column": 4, + "line": 5, + }, + }, + "object": Node { + "end": 234, + "loc": SourceLocation { + "end": Position { + "column": 6, + "line": 5, + }, + "identifierName": "ns", + "start": Position { + "column": 4, + "line": 5, + }, + }, + "name": "ns", + "start": 232, + "type": "Identifier", + }, + "property": Node { + "end": 247, + "loc": SourceLocation { + "end": Position { + "column": 19, + "line": 5, + }, + "identifierName": "activeMutant", + "start": Position { + "column": 7, + "line": 5, + }, + }, + "name": "activeMutant", + "start": 235, + "type": "Identifier", + }, + "start": 232, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 69, + "line": 5, + }, + "start": Position { + "column": 4, + "line": 5, + }, + }, + "operator": "=", + "right": Node { + "arguments": Array [ + Node { + "computed": false, + "end": 296, + "loc": SourceLocation { + "end": Position { + "column": 68, + "line": 5, + }, + "start": Position { + "column": 29, + "line": 5, + }, + }, + "object": Node { + "computed": false, + "end": 270, + "loc": SourceLocation { + "end": Position { + "column": 42, + "line": 5, + }, + "start": Position { + "column": 29, + "line": 5, + }, + }, + "object": Node { + "computed": false, + "end": 266, + "loc": SourceLocation { + "end": Position { + "column": 38, + "line": 5, + }, + "start": Position { + "column": 29, + "line": 5, + }, + }, + "object": Node { + "end": 258, + "loc": SourceLocation { + "end": Position { + "column": 30, + "line": 5, + }, + "identifierName": "g", + "start": Position { + "column": 29, + "line": 5, + }, + }, + "name": "g", + "start": 257, + "type": "Identifier", + }, + "property": Node { + "end": 266, + "loc": SourceLocation { + "end": Position { + "column": 38, + "line": 5, + }, + "identifierName": "process", + "start": Position { + "column": 31, + "line": 5, + }, + }, + "name": "process", + "start": 259, + "type": "Identifier", + }, + "start": 257, + "type": "MemberExpression", + }, + "property": Node { + "end": 270, + "loc": SourceLocation { + "end": Position { + "column": 42, + "line": 5, + }, + "identifierName": "env", + "start": Position { + "column": 39, + "line": 5, + }, + }, + "name": "env", + "start": 267, + "type": "Identifier", + }, + "start": 257, + "type": "MemberExpression", + }, + "property": Node { + "end": 296, + "loc": SourceLocation { + "end": Position { + "column": 68, + "line": 5, + }, + "identifierName": "__STRYKER_ACTIVE_MUTANT__", + "start": Position { + "column": 43, + "line": 5, + }, + }, + "name": "__STRYKER_ACTIVE_MUTANT__", + "start": 271, + "type": "Identifier", + }, + "start": 257, + "type": "MemberExpression", + }, + ], + "callee": Node { + "end": 256, + "loc": SourceLocation { + "end": Position { + "column": 28, + "line": 5, + }, + "identifierName": "Number", + "start": Position { + "column": 22, + "line": 5, + }, + }, + "name": "Number", + "start": 250, + "type": "Identifier", + }, + "end": 297, + "loc": SourceLocation { + "end": Position { + "column": 69, + "line": 5, + }, + "start": Position { + "column": 22, + "line": 5, + }, + }, + "start": 250, + "type": "CallExpression", + }, + "start": 232, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 70, + "line": 5, + }, + "start": Position { + "column": 4, + "line": 5, + }, + }, + "start": 232, + "type": "ExpressionStatement", + }, + ], + "directives": Array [], + "end": 302, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 6, + }, + "start": Position { + "column": 110, + "line": 4, + }, + }, + "start": 226, + "type": "BlockStatement", + }, + "end": 302, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 6, + }, + "start": Position { + "column": 2, + "line": 4, + }, + }, + "start": 118, + "test": Node { + "end": 224, + "left": Node { + "end": 181, + "left": Node { + "end": 164, + "left": Node { + "end": 151, + "left": Node { + "computed": false, + "end": 137, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 4, + }, + "start": Position { + "column": 6, + "line": 4, + }, + }, + "object": Node { + "end": 124, + "loc": SourceLocation { + "end": Position { + "column": 8, + "line": 4, + }, + "identifierName": "ns", + "start": Position { + "column": 6, + "line": 4, + }, + }, + "name": "ns", + "start": 122, + "type": "Identifier", + }, + "property": Node { + "end": 137, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 4, + }, + "identifierName": "activeMutant", + "start": Position { + "column": 9, + "line": 4, + }, + }, + "name": "activeMutant", + "start": 125, + "type": "Identifier", + }, + "start": 122, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 35, + "line": 4, + }, + "start": Position { + "column": 6, + "line": 4, + }, + }, + "operator": "===", + "right": Node { + "end": 151, + "loc": SourceLocation { + "end": Position { + "column": 35, + "line": 4, + }, + "identifierName": "undefined", + "start": Position { + "column": 26, + "line": 4, + }, + }, + "name": "undefined", + "start": 142, + "type": "Identifier", + }, + "start": 122, + "type": "BinaryExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 48, + "line": 4, + }, + "start": Position { + "column": 6, + "line": 4, + }, + }, + "operator": "&&", + "right": Node { + "computed": false, + "end": 164, + "loc": SourceLocation { + "end": Position { + "column": 48, + "line": 4, + }, + "start": Position { + "column": 39, + "line": 4, + }, + }, + "object": Node { + "end": 156, + "loc": SourceLocation { + "end": Position { + "column": 40, + "line": 4, + }, + "identifierName": "g", + "start": Position { + "column": 39, + "line": 4, + }, + }, + "name": "g", + "start": 155, + "type": "Identifier", + }, + "property": Node { + "end": 164, + "loc": SourceLocation { + "end": Position { + "column": 48, + "line": 4, + }, + "identifierName": "process", + "start": Position { + "column": 41, + "line": 4, + }, + }, + "name": "process", + "start": 157, + "type": "Identifier", + }, + "start": 155, + "type": "MemberExpression", + }, + "start": 122, + "type": "LogicalExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 65, + "line": 4, + }, + "start": Position { + "column": 6, + "line": 4, + }, + }, + "operator": "&&", + "right": Node { + "computed": false, + "end": 181, + "loc": SourceLocation { + "end": Position { + "column": 65, + "line": 4, + }, + "start": Position { + "column": 52, + "line": 4, + }, + }, + "object": Node { + "computed": false, + "end": 177, + "loc": SourceLocation { + "end": Position { + "column": 61, + "line": 4, + }, + "start": Position { + "column": 52, + "line": 4, + }, + }, + "object": Node { + "end": 169, + "loc": SourceLocation { + "end": Position { + "column": 53, + "line": 4, + }, + "identifierName": "g", + "start": Position { + "column": 52, + "line": 4, + }, + }, + "name": "g", + "start": 168, + "type": "Identifier", + }, + "property": Node { + "end": 177, + "loc": SourceLocation { + "end": Position { + "column": 61, + "line": 4, + }, + "identifierName": "process", + "start": Position { + "column": 54, + "line": 4, + }, + }, + "name": "process", + "start": 170, + "type": "Identifier", + }, + "start": 168, + "type": "MemberExpression", + }, + "property": Node { + "end": 181, + "loc": SourceLocation { + "end": Position { + "column": 65, + "line": 4, + }, + "identifierName": "env", + "start": Position { + "column": 62, + "line": 4, + }, + }, + "name": "env", + "start": 178, + "type": "Identifier", + }, + "start": 168, + "type": "MemberExpression", + }, + "start": 122, + "type": "LogicalExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 108, + "line": 4, + }, + "start": Position { + "column": 6, + "line": 4, + }, + }, + "operator": "&&", + "right": Node { + "computed": false, + "end": 224, + "loc": SourceLocation { + "end": Position { + "column": 108, + "line": 4, + }, + "start": Position { + "column": 69, + "line": 4, + }, + }, + "object": Node { + "computed": false, + "end": 198, + "loc": SourceLocation { + "end": Position { + "column": 82, + "line": 4, + }, + "start": Position { + "column": 69, + "line": 4, + }, + }, + "object": Node { + "computed": false, + "end": 194, + "loc": SourceLocation { + "end": Position { + "column": 78, + "line": 4, + }, + "start": Position { + "column": 69, + "line": 4, + }, + }, + "object": Node { + "end": 186, + "loc": SourceLocation { + "end": Position { + "column": 70, + "line": 4, + }, + "identifierName": "g", + "start": Position { + "column": 69, + "line": 4, + }, + }, + "name": "g", + "start": 185, + "type": "Identifier", + }, + "property": Node { + "end": 194, + "loc": SourceLocation { + "end": Position { + "column": 78, + "line": 4, + }, + "identifierName": "process", + "start": Position { + "column": 71, + "line": 4, + }, + }, + "name": "process", + "start": 187, + "type": "Identifier", + }, + "start": 185, + "type": "MemberExpression", + }, + "property": Node { + "end": 198, + "loc": SourceLocation { + "end": Position { + "column": 82, + "line": 4, + }, + "identifierName": "env", + "start": Position { + "column": 79, + "line": 4, + }, + }, + "name": "env", + "start": 195, + "type": "Identifier", + }, + "start": 185, + "type": "MemberExpression", + }, + "property": Node { + "end": 224, + "loc": SourceLocation { + "end": Position { + "column": 108, + "line": 4, + }, + "identifierName": "__STRYKER_ACTIVE_MUTANT__", + "start": Position { + "column": 83, + "line": 4, + }, + }, + "name": "__STRYKER_ACTIVE_MUTANT__", + "start": 199, + "type": "Identifier", + }, + "start": 185, + "type": "MemberExpression", + }, + "start": 122, + "type": "LogicalExpression", + }, + "type": "IfStatement", + }, + Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "argument": Node { + "end": 341, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 8, + }, + "identifierName": "ns", + "start": Position { + "column": 11, + "line": 8, + }, + }, + "name": "ns", + "start": 339, + "type": "Identifier", + }, + "end": 342, + "loc": SourceLocation { + "end": Position { + "column": 14, + "line": 8, + }, + "start": Position { + "column": 4, + "line": 8, + }, + }, + "start": 332, + "type": "ReturnStatement", + }, + ], + "directives": Array [], + "end": 346, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 9, + }, + "start": Position { + "column": 23, + "line": 7, + }, + }, + "start": 326, + "type": "BlockStatement", + }, + "end": 346, + "generator": false, + "id": Node { + "end": 324, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 7, + }, + "identifierName": "retrieveNS", + "start": Position { + "column": 11, + "line": 7, + }, + }, + "name": "retrieveNS", + "start": 314, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 9, + }, + "start": Position { + "column": 2, + "line": 7, + }, + }, + "params": Array [], + "start": 305, + "type": "FunctionDeclaration", + }, + Node { + "end": 375, + "expression": Node { + "end": 374, + "left": Node { + "end": 361, + "loc": SourceLocation { + "end": Position { + "column": 14, + "line": 10, + }, + "identifierName": "stryNS_9fa48", + "start": Position { + "column": 2, + "line": 10, + }, + }, + "name": "stryNS_9fa48", + "start": 349, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 27, + "line": 10, + }, + "start": Position { + "column": 2, + "line": 10, + }, + }, + "operator": "=", + "right": Node { + "end": 374, + "loc": SourceLocation { + "end": Position { + "column": 27, + "line": 10, + }, + "identifierName": "retrieveNS", + "start": Position { + "column": 17, + "line": 10, + }, + }, + "name": "retrieveNS", + "start": 364, + "type": "Identifier", + }, + "start": 349, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 28, + "line": 10, + }, + "start": Position { + "column": 2, + "line": 10, + }, + }, + "start": 349, + "type": "ExpressionStatement", + }, + Node { + "argument": Node { + "arguments": Array [], + "callee": Node { + "end": 395, + "loc": SourceLocation { + "end": Position { + "column": 19, + "line": 11, + }, + "identifierName": "retrieveNS", + "start": Position { + "column": 9, + "line": 11, + }, + }, + "name": "retrieveNS", + "start": 385, + "type": "Identifier", + }, + "end": 397, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 11, + }, + "start": Position { + "column": 9, + "line": 11, + }, + }, + "start": 385, + "type": "CallExpression", + }, + "end": 398, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 11, + }, + "start": Position { + "column": 2, + "line": 11, + }, + }, + "start": 378, + "type": "ReturnStatement", + }, + ], + "directives": Array [], + "end": 400, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 12, + }, + "start": Position { + "column": 23, + "line": 1, + }, + }, + "start": 23, + "type": "BlockStatement", + }, + "end": 400, + "generator": false, + "id": Node { + "end": 21, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 1, + }, + "identifierName": "stryNS_9fa48", + "start": Position { + "column": 9, + "line": 1, + }, + }, + "name": "stryNS_9fa48", + "start": 9, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 12, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "params": Array [], + "start": 0, + "type": "FunctionDeclaration", + }, + Node { + "end": 416, + "expression": Node { + "arguments": Array [], + "callee": Node { + "end": 413, + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 13, + }, + "identifierName": "stryNS_9fa48", + "start": Position { + "column": 0, + "line": 13, + }, + }, + "name": "stryNS_9fa48", + "start": 401, + "type": "Identifier", + }, + "end": 415, + "loc": SourceLocation { + "end": Position { + "column": 14, + "line": 13, + }, + "start": Position { + "column": 0, + "line": 13, + }, + }, + "start": 401, + "type": "CallExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 13, + }, + "start": Position { + "column": 0, + "line": 13, + }, + }, + "start": 401, + "type": "ExpressionStatement", + }, + Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "declarations": Array [ + Node { + "end": 470, + "id": Node { + "end": 453, + "loc": SourceLocation { + "end": Position { + "column": 8, + "line": 16, + }, + "identifierName": "ns", + "start": Position { + "column": 6, + "line": 16, + }, + }, + "name": "ns", + "start": 451, + "type": "Identifier", + }, + "init": Node { + "arguments": Array [], + "callee": Node { + "end": 468, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 16, + }, + "identifierName": "stryNS_9fa48", + "start": Position { + "column": 11, + "line": 16, + }, + }, + "name": "stryNS_9fa48", + "start": 456, + "type": "Identifier", + }, + "end": 470, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 16, + }, + "start": Position { + "column": 11, + "line": 16, + }, + }, + "start": 456, + "type": "CallExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 16, + }, + "start": Position { + "column": 6, + "line": 16, + }, + }, + "start": 451, + "type": "VariableDeclarator", + }, + ], + "end": 471, + "kind": "var", + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 16, + }, + "start": Position { + "column": 2, + "line": 16, + }, + }, + "start": 447, + "type": "VariableDeclaration", + }, + Node { + "declarations": Array [ + Node { + "end": 554, + "id": Node { + "end": 481, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 17, + }, + "identifierName": "cov", + "start": Position { + "column": 6, + "line": 17, + }, + }, + "name": "cov", + "start": 478, + "type": "Identifier", + }, + "init": Node { + "end": 554, + "left": Node { + "computed": false, + "end": 501, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 17, + }, + "start": Position { + "column": 12, + "line": 17, + }, + }, + "object": Node { + "end": 486, + "loc": SourceLocation { + "end": Position { + "column": 14, + "line": 17, + }, + "identifierName": "ns", + "start": Position { + "column": 12, + "line": 17, + }, + }, + "name": "ns", + "start": 484, + "type": "Identifier", + }, + "property": Node { + "end": 501, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 17, + }, + "identifierName": "mutantCoverage", + "start": Position { + "column": 15, + "line": 17, + }, + }, + "name": "mutantCoverage", + "start": 487, + "type": "Identifier", + }, + "start": 484, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 82, + "line": 17, + }, + "start": Position { + "column": 12, + "line": 17, + }, + }, + "operator": "||", + "right": Node { + "end": 553, + "extra": Object { + "parenStart": 505, + "parenthesized": true, + }, + "left": Node { + "computed": false, + "end": 523, + "loc": SourceLocation { + "end": Position { + "column": 51, + "line": 17, + }, + "start": Position { + "column": 34, + "line": 17, + }, + }, + "object": Node { + "end": 508, + "loc": SourceLocation { + "end": Position { + "column": 36, + "line": 17, + }, + "identifierName": "ns", + "start": Position { + "column": 34, + "line": 17, + }, + }, + "name": "ns", + "start": 506, + "type": "Identifier", + }, + "property": Node { + "end": 523, + "loc": SourceLocation { + "end": Position { + "column": 51, + "line": 17, + }, + "identifierName": "mutantCoverage", + "start": Position { + "column": 37, + "line": 17, + }, + }, + "name": "mutantCoverage", + "start": 509, + "type": "Identifier", + }, + "start": 506, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 81, + "line": 17, + }, + "start": Position { + "column": 34, + "line": 17, + }, + }, + "operator": "=", + "right": Node { + "end": 553, + "loc": SourceLocation { + "end": Position { + "column": 81, + "line": 17, + }, + "start": Position { + "column": 54, + "line": 17, + }, + }, + "properties": Array [ + Node { + "computed": false, + "end": 538, + "key": Node { + "end": 534, + "loc": SourceLocation { + "end": Position { + "column": 62, + "line": 17, + }, + "identifierName": "static", + "start": Position { + "column": 56, + "line": 17, + }, + }, + "name": "static", + "start": 528, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 66, + "line": 17, + }, + "start": Position { + "column": 56, + "line": 17, + }, + }, + "method": false, + "shorthand": false, + "start": 528, + "type": "ObjectProperty", + "value": Node { + "end": 538, + "loc": SourceLocation { + "end": Position { + "column": 66, + "line": 17, + }, + "start": Position { + "column": 64, + "line": 17, + }, + }, + "properties": Array [], + "start": 536, + "type": "ObjectExpression", + }, + }, + Node { + "computed": false, + "end": 551, + "key": Node { + "end": 547, + "loc": SourceLocation { + "end": Position { + "column": 75, + "line": 17, + }, + "identifierName": "perTest", + "start": Position { + "column": 68, + "line": 17, + }, + }, + "name": "perTest", + "start": 540, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 79, + "line": 17, + }, + "start": Position { + "column": 68, + "line": 17, + }, + }, + "method": false, + "shorthand": false, + "start": 540, + "type": "ObjectProperty", + "value": Node { + "end": 551, + "loc": SourceLocation { + "end": Position { + "column": 79, + "line": 17, + }, + "start": Position { + "column": 77, + "line": 17, + }, + }, + "properties": Array [], + "start": 549, + "type": "ObjectExpression", + }, + }, + ], + "start": 526, + "type": "ObjectExpression", + }, + "start": 506, + "type": "AssignmentExpression", + }, + "start": 484, + "type": "LogicalExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 82, + "line": 17, + }, + "start": Position { + "column": 6, + "line": 17, + }, + }, + "start": 478, + "type": "VariableDeclarator", + }, + ], + "end": 555, + "kind": "var", + "loc": SourceLocation { + "end": Position { + "column": 83, + "line": 17, + }, + "start": Position { + "column": 2, + "line": 17, + }, + }, + "start": 474, + "type": "VariableDeclaration", + }, + Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "declarations": Array [ + Node { + "end": 599, + "id": Node { + "end": 586, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 19, + }, + "identifierName": "c", + "start": Position { + "column": 8, + "line": 19, + }, + }, + "name": "c", + "start": 585, + "type": "Identifier", + }, + "init": Node { + "computed": false, + "end": 599, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 19, + }, + "start": Position { + "column": 12, + "line": 19, + }, + }, + "object": Node { + "end": 592, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 19, + }, + "identifierName": "cov", + "start": Position { + "column": 12, + "line": 19, + }, + }, + "name": "cov", + "start": 589, + "type": "Identifier", + }, + "property": Node { + "end": 599, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 19, + }, + "identifierName": "static", + "start": Position { + "column": 16, + "line": 19, + }, + }, + "name": "static", + "start": 593, + "type": "Identifier", + }, + "start": 589, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 19, + }, + "start": Position { + "column": 8, + "line": 19, + }, + }, + "start": 585, + "type": "VariableDeclarator", + }, + ], + "end": 600, + "kind": "var", + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 19, + }, + "start": Position { + "column": 4, + "line": 19, + }, + }, + "start": 581, + "type": "VariableDeclaration", + }, + Node { + "alternate": null, + "consequent": Node { + "body": Array [ + Node { + "end": 707, + "expression": Node { + "end": 706, + "left": Node { + "end": 636, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 21, + }, + "identifierName": "c", + "start": Position { + "column": 6, + "line": 21, + }, + }, + "name": "c", + "start": 635, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 77, + "line": 21, + }, + "start": Position { + "column": 6, + "line": 21, + }, + }, + "operator": "=", + "right": Node { + "end": 706, + "left": Node { + "computed": true, + "end": 668, + "loc": SourceLocation { + "end": Position { + "column": 39, + "line": 21, + }, + "start": Position { + "column": 10, + "line": 21, + }, + }, + "object": Node { + "computed": false, + "end": 650, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 21, + }, + "start": Position { + "column": 10, + "line": 21, + }, + }, + "object": Node { + "end": 642, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 21, + }, + "identifierName": "cov", + "start": Position { + "column": 10, + "line": 21, + }, + }, + "name": "cov", + "start": 639, + "type": "Identifier", + }, + "property": Node { + "end": 650, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 21, + }, + "identifierName": "perTest", + "start": Position { + "column": 14, + "line": 21, + }, + }, + "name": "perTest", + "start": 643, + "type": "Identifier", + }, + "start": 639, + "type": "MemberExpression", + }, + "property": Node { + "computed": false, + "end": 667, + "loc": SourceLocation { + "end": Position { + "column": 38, + "line": 21, + }, + "start": Position { + "column": 22, + "line": 21, + }, + }, + "object": Node { + "end": 653, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 21, + }, + "identifierName": "ns", + "start": Position { + "column": 22, + "line": 21, + }, + }, + "name": "ns", + "start": 651, + "type": "Identifier", + }, + "property": Node { + "end": 667, + "loc": SourceLocation { + "end": Position { + "column": 38, + "line": 21, + }, + "identifierName": "currentTestId", + "start": Position { + "column": 25, + "line": 21, + }, + }, + "name": "currentTestId", + "start": 654, + "type": "Identifier", + }, + "start": 651, + "type": "MemberExpression", + }, + "start": 639, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 77, + "line": 21, + }, + "start": Position { + "column": 10, + "line": 21, + }, + }, + "operator": "=", + "right": Node { + "end": 706, + "left": Node { + "computed": true, + "end": 700, + "loc": SourceLocation { + "end": Position { + "column": 71, + "line": 21, + }, + "start": Position { + "column": 42, + "line": 21, + }, + }, + "object": Node { + "computed": false, + "end": 682, + "loc": SourceLocation { + "end": Position { + "column": 53, + "line": 21, + }, + "start": Position { + "column": 42, + "line": 21, + }, + }, + "object": Node { + "end": 674, + "loc": SourceLocation { + "end": Position { + "column": 45, + "line": 21, + }, + "identifierName": "cov", + "start": Position { + "column": 42, + "line": 21, + }, + }, + "name": "cov", + "start": 671, + "type": "Identifier", + }, + "property": Node { + "end": 682, + "loc": SourceLocation { + "end": Position { + "column": 53, + "line": 21, + }, + "identifierName": "perTest", + "start": Position { + "column": 46, + "line": 21, + }, + }, + "name": "perTest", + "start": 675, + "type": "Identifier", + }, + "start": 671, + "type": "MemberExpression", + }, + "property": Node { + "computed": false, + "end": 699, + "loc": SourceLocation { + "end": Position { + "column": 70, + "line": 21, + }, + "start": Position { + "column": 54, + "line": 21, + }, + }, + "object": Node { + "end": 685, + "loc": SourceLocation { + "end": Position { + "column": 56, + "line": 21, + }, + "identifierName": "ns", + "start": Position { + "column": 54, + "line": 21, + }, + }, + "name": "ns", + "start": 683, + "type": "Identifier", + }, + "property": Node { + "end": 699, + "loc": SourceLocation { + "end": Position { + "column": 70, + "line": 21, + }, + "identifierName": "currentTestId", + "start": Position { + "column": 57, + "line": 21, + }, + }, + "name": "currentTestId", + "start": 686, + "type": "Identifier", + }, + "start": 683, + "type": "MemberExpression", + }, + "start": 671, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 77, + "line": 21, + }, + "start": Position { + "column": 42, + "line": 21, + }, + }, + "operator": "||", + "right": Node { + "end": 706, + "loc": SourceLocation { + "end": Position { + "column": 77, + "line": 21, + }, + "start": Position { + "column": 75, + "line": 21, + }, + }, + "properties": Array [], + "start": 704, + "type": "ObjectExpression", + }, + "start": 671, + "type": "LogicalExpression", + }, + "start": 639, + "type": "AssignmentExpression", + }, + "start": 635, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 78, + "line": 21, + }, + "start": Position { + "column": 6, + "line": 21, + }, + }, + "start": 635, + "type": "ExpressionStatement", + }, + ], + "directives": Array [], + "end": 713, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 22, + }, + "start": Position { + "column": 26, + "line": 20, + }, + }, + "start": 627, + "type": "BlockStatement", + }, + "end": 713, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 22, + }, + "start": Position { + "column": 4, + "line": 20, + }, + }, + "start": 605, + "test": Node { + "computed": false, + "end": 625, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 20, + }, + "start": Position { + "column": 8, + "line": 20, + }, + }, + "object": Node { + "end": 611, + "loc": SourceLocation { + "end": Position { + "column": 10, + "line": 20, + }, + "identifierName": "ns", + "start": Position { + "column": 8, + "line": 20, + }, + }, + "name": "ns", + "start": 609, + "type": "Identifier", + }, + "property": Node { + "end": 625, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 20, + }, + "identifierName": "currentTestId", + "start": Position { + "column": 11, + "line": 20, + }, + }, + "name": "currentTestId", + "start": 612, + "type": "Identifier", + }, + "start": 609, + "type": "MemberExpression", + }, + "type": "IfStatement", + }, + Node { + "declarations": Array [ + Node { + "end": 735, + "id": Node { + "end": 723, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 23, + }, + "identifierName": "a", + "start": Position { + "column": 8, + "line": 23, + }, + }, + "name": "a", + "start": 722, + "type": "Identifier", + }, + "init": Node { + "end": 735, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 23, + }, + "identifierName": "arguments", + "start": Position { + "column": 12, + "line": 23, + }, + }, + "name": "arguments", + "start": 726, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 23, + }, + "start": Position { + "column": 8, + "line": 23, + }, + }, + "start": 722, + "type": "VariableDeclarator", + }, + ], + "end": 736, + "kind": "var", + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 23, + }, + "start": Position { + "column": 4, + "line": 23, + }, + }, + "start": 718, + "type": "VariableDeclaration", + }, + Node { + "body": Node { + "body": Array [ + Node { + "end": 809, + "expression": Node { + "end": 808, + "left": Node { + "computed": true, + "end": 787, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 25, + }, + "start": Position { + "column": 6, + "line": 25, + }, + }, + "object": Node { + "end": 781, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 25, + }, + "identifierName": "c", + "start": Position { + "column": 6, + "line": 25, + }, + }, + "name": "c", + "start": 780, + "type": "Identifier", + }, + "property": Node { + "computed": true, + "end": 786, + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 25, + }, + "start": Position { + "column": 8, + "line": 25, + }, + }, + "object": Node { + "end": 783, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 25, + }, + "identifierName": "a", + "start": Position { + "column": 8, + "line": 25, + }, + }, + "name": "a", + "start": 782, + "type": "Identifier", + }, + "property": Node { + "end": 785, + "loc": SourceLocation { + "end": Position { + "column": 11, + "line": 25, + }, + "identifierName": "i", + "start": Position { + "column": 10, + "line": 25, + }, + }, + "name": "i", + "start": 784, + "type": "Identifier", + }, + "start": 782, + "type": "MemberExpression", + }, + "start": 780, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 25, + }, + "start": Position { + "column": 6, + "line": 25, + }, + }, + "operator": "=", + "right": Node { + "end": 808, + "left": Node { + "end": 803, + "extra": Object { + "parenStart": 790, + "parenthesized": true, + }, + "left": Node { + "computed": true, + "end": 798, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 25, + }, + "start": Position { + "column": 17, + "line": 25, + }, + }, + "object": Node { + "end": 792, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 25, + }, + "identifierName": "c", + "start": Position { + "column": 17, + "line": 25, + }, + }, + "name": "c", + "start": 791, + "type": "Identifier", + }, + "property": Node { + "computed": true, + "end": 797, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 25, + }, + "start": Position { + "column": 19, + "line": 25, + }, + }, + "object": Node { + "end": 794, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 25, + }, + "identifierName": "a", + "start": Position { + "column": 19, + "line": 25, + }, + }, + "name": "a", + "start": 793, + "type": "Identifier", + }, + "property": Node { + "end": 796, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 25, + }, + "identifierName": "i", + "start": Position { + "column": 21, + "line": 25, + }, + }, + "name": "i", + "start": 795, + "type": "Identifier", + }, + "start": 793, + "type": "MemberExpression", + }, + "start": 791, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 25, + }, + "start": Position { + "column": 17, + "line": 25, + }, + }, + "operator": "||", + "right": Node { + "end": 803, + "extra": Object { + "raw": "0", + "rawValue": 0, + }, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 25, + }, + "start": Position { + "column": 28, + "line": 25, + }, + }, + "start": 802, + "type": "NumericLiteral", + "value": 0, + }, + "start": 791, + "type": "LogicalExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 25, + }, + "start": Position { + "column": 16, + "line": 25, + }, + }, + "operator": "+", + "right": Node { + "end": 808, + "extra": Object { + "raw": "1", + "rawValue": 1, + }, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 25, + }, + "start": Position { + "column": 33, + "line": 25, + }, + }, + "start": 807, + "type": "NumericLiteral", + "value": 1, + }, + "start": 790, + "type": "BinaryExpression", + }, + "start": 780, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 35, + "line": 25, + }, + "start": Position { + "column": 6, + "line": 25, + }, + }, + "start": 780, + "type": "ExpressionStatement", + }, + ], + "directives": Array [], + "end": 815, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 26, + }, + "start": Position { + "column": 35, + "line": 24, + }, + }, + "start": 772, + "type": "BlockStatement", + }, + "end": 815, + "init": Node { + "declarations": Array [ + Node { + "end": 752, + "id": Node { + "end": 750, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 24, + }, + "identifierName": "i", + "start": Position { + "column": 12, + "line": 24, + }, + }, + "name": "i", + "start": 749, + "type": "Identifier", + }, + "init": Node { + "end": 752, + "extra": Object { + "raw": "0", + "rawValue": 0, + }, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 24, + }, + "start": Position { + "column": 14, + "line": 24, + }, + }, + "start": 751, + "type": "NumericLiteral", + "value": 0, + }, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 24, + }, + "start": Position { + "column": 12, + "line": 24, + }, + }, + "start": 749, + "type": "VariableDeclarator", + }, + ], + "end": 752, + "kind": "var", + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 24, + }, + "start": Position { + "column": 8, + "line": 24, + }, + }, + "start": 745, + "type": "VariableDeclaration", + }, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 26, + }, + "start": Position { + "column": 4, + "line": 24, + }, + }, + "start": 741, + "test": Node { + "end": 766, + "left": Node { + "end": 755, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 24, + }, + "identifierName": "i", + "start": Position { + "column": 17, + "line": 24, + }, + }, + "name": "i", + "start": 754, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 24, + }, + "start": Position { + "column": 17, + "line": 24, + }, + }, + "operator": "<", + "right": Node { + "computed": false, + "end": 766, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 24, + }, + "start": Position { + "column": 21, + "line": 24, + }, + }, + "object": Node { + "end": 759, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 24, + }, + "identifierName": "a", + "start": Position { + "column": 21, + "line": 24, + }, + }, + "name": "a", + "start": 758, + "type": "Identifier", + }, + "property": Node { + "end": 766, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 24, + }, + "identifierName": "length", + "start": Position { + "column": 23, + "line": 24, + }, + }, + "name": "length", + "start": 760, + "type": "Identifier", + }, + "start": 758, + "type": "MemberExpression", + }, + "start": 754, + "type": "BinaryExpression", + }, + "type": "ForStatement", + "update": Node { + "argument": Node { + "end": 769, + "loc": SourceLocation { + "end": Position { + "column": 32, + "line": 24, + }, + "identifierName": "i", + "start": Position { + "column": 31, + "line": 24, + }, + }, + "name": "i", + "start": 768, + "type": "Identifier", + }, + "end": 771, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 24, + }, + "start": Position { + "column": 31, + "line": 24, + }, + }, + "operator": "++", + "prefix": false, + "start": 768, + "type": "UpdateExpression", + }, + }, + ], + "directives": Array [], + "end": 819, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 27, + }, + "start": Position { + "column": 19, + "line": 18, + }, + }, + "start": 575, + "type": "BlockStatement", + }, + "end": 819, + "generator": false, + "id": Node { + "end": 572, + "loc": SourceLocation { + "end": Position { + "column": 16, + "line": 18, + }, + "identifierName": "cover", + "start": Position { + "column": 11, + "line": 18, + }, + }, + "name": "cover", + "start": 567, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 27, + }, + "start": Position { + "column": 2, + "line": 18, + }, + }, + "params": Array [], + "start": 558, + "type": "FunctionDeclaration", + }, + Node { + "end": 844, + "expression": Node { + "end": 843, + "left": Node { + "end": 835, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 28, + }, + "identifierName": "stryCov_9fa48", + "start": Position { + "column": 2, + "line": 28, + }, + }, + "name": "stryCov_9fa48", + "start": 822, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 28, + }, + "start": Position { + "column": 2, + "line": 28, + }, + }, + "operator": "=", + "right": Node { + "end": 843, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 28, + }, + "identifierName": "cover", + "start": Position { + "column": 18, + "line": 28, + }, + }, + "name": "cover", + "start": 838, + "type": "Identifier", + }, + "start": 822, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 28, + }, + "start": Position { + "column": 2, + "line": 28, + }, + }, + "start": 822, + "type": "ExpressionStatement", + }, + Node { + "end": 876, + "expression": Node { + "arguments": Array [ + Node { + "end": 863, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 29, + }, + "start": Position { + "column": 14, + "line": 29, + }, + }, + "start": 859, + "type": "NullLiteral", + }, + Node { + "end": 874, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 29, + }, + "identifierName": "arguments", + "start": Position { + "column": 20, + "line": 29, + }, + }, + "name": "arguments", + "start": 865, + "type": "Identifier", + }, + ], + "callee": Node { + "computed": false, + "end": 858, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 29, + }, + "start": Position { + "column": 2, + "line": 29, + }, + }, + "object": Node { + "end": 852, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 29, + }, + "identifierName": "cover", + "start": Position { + "column": 2, + "line": 29, + }, + }, + "name": "cover", + "start": 847, + "type": "Identifier", + }, + "property": Node { + "end": 858, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 29, + }, + "identifierName": "apply", + "start": Position { + "column": 8, + "line": 29, + }, + }, + "name": "apply", + "start": 853, + "type": "Identifier", + }, + "start": 847, + "type": "MemberExpression", + }, + "end": 875, + "loc": SourceLocation { + "end": Position { + "column": 30, + "line": 29, + }, + "start": Position { + "column": 2, + "line": 29, + }, + }, + "start": 847, + "type": "CallExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 31, + "line": 29, + }, + "start": Position { + "column": 2, + "line": 29, + }, + }, + "start": 847, + "type": "ExpressionStatement", + }, + ], + "directives": Array [], + "end": 878, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 30, + }, + "start": Position { + "column": 25, + "line": 15, + }, + }, + "start": 443, + "type": "BlockStatement", + }, + "end": 878, + "generator": false, + "id": Node { + "end": 440, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 15, + }, + "identifierName": "stryCov_9fa48", + "start": Position { + "column": 9, + "line": 15, + }, + }, + "name": "stryCov_9fa48", + "start": 427, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 30, + }, + "start": Position { + "column": 0, + "line": 15, + }, + }, + "params": Array [], + "start": 418, + "type": "FunctionDeclaration", + }, + Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "declarations": Array [ + Node { + "end": 936, + "id": Node { + "end": 919, + "loc": SourceLocation { + "end": Position { + "column": 8, + "line": 32, + }, + "identifierName": "ns", + "start": Position { + "column": 6, + "line": 32, + }, + }, + "name": "ns", + "start": 917, + "type": "Identifier", + }, + "init": Node { + "arguments": Array [], + "callee": Node { + "end": 934, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 32, + }, + "identifierName": "stryNS_9fa48", + "start": Position { + "column": 11, + "line": 32, + }, + }, + "name": "stryNS_9fa48", + "start": 922, + "type": "Identifier", + }, + "end": 936, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 32, + }, + "start": Position { + "column": 11, + "line": 32, + }, + }, + "start": 922, + "type": "CallExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 32, + }, + "start": Position { + "column": 6, + "line": 32, + }, + }, + "start": 917, + "type": "VariableDeclarator", + }, + ], + "end": 937, + "kind": "var", + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 32, + }, + "start": Position { + "column": 2, + "line": 32, + }, + }, + "start": 913, + "type": "VariableDeclaration", + }, + Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "argument": Node { + "end": 997, + "left": Node { + "computed": false, + "end": 990, + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 34, + }, + "start": Position { + "column": 11, + "line": 34, + }, + }, + "object": Node { + "end": 977, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 34, + }, + "identifierName": "ns", + "start": Position { + "column": 11, + "line": 34, + }, + }, + "name": "ns", + "start": 975, + "type": "Identifier", + }, + "property": Node { + "end": 990, + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 34, + }, + "identifierName": "activeMutant", + "start": Position { + "column": 14, + "line": 34, + }, + }, + "name": "activeMutant", + "start": 978, + "type": "Identifier", + }, + "start": 975, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 33, + "line": 34, + }, + "start": Position { + "column": 11, + "line": 34, + }, + }, + "operator": "===", + "right": Node { + "end": 997, + "loc": SourceLocation { + "end": Position { + "column": 33, + "line": 34, + }, + "identifierName": "id", + "start": Position { + "column": 31, + "line": 34, + }, + }, + "name": "id", + "start": 995, + "type": "Identifier", + }, + "start": 975, + "type": "BinaryExpression", + }, + "end": 998, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 34, + }, + "start": Position { + "column": 4, + "line": 34, + }, + }, + "start": 968, + "type": "ReturnStatement", + }, + ], + "directives": Array [], + "end": 1002, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 35, + }, + "start": Position { + "column": 24, + "line": 33, + }, + }, + "start": 962, + "type": "BlockStatement", + }, + "end": 1002, + "generator": false, + "id": Node { + "end": 957, + "loc": SourceLocation { + "end": Position { + "column": 19, + "line": 33, + }, + "identifierName": "isActive", + "start": Position { + "column": 11, + "line": 33, + }, + }, + "name": "isActive", + "start": 949, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 35, + }, + "start": Position { + "column": 2, + "line": 33, + }, + }, + "params": Array [ + Node { + "end": 960, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 33, + }, + "identifierName": "id", + "start": Position { + "column": 20, + "line": 33, + }, + }, + "name": "id", + "start": 958, + "type": "Identifier", + }, + ], + "start": 940, + "type": "FunctionDeclaration", + }, + Node { + "end": 1033, + "expression": Node { + "end": 1032, + "left": Node { + "end": 1021, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 36, + }, + "identifierName": "stryMutAct_9fa48", + "start": Position { + "column": 2, + "line": 36, + }, + }, + "name": "stryMutAct_9fa48", + "start": 1005, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 36, + }, + "start": Position { + "column": 2, + "line": 36, + }, + }, + "operator": "=", + "right": Node { + "end": 1032, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 36, + }, + "identifierName": "isActive", + "start": Position { + "column": 21, + "line": 36, + }, + }, + "name": "isActive", + "start": 1024, + "type": "Identifier", + }, + "start": 1005, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 30, + "line": 36, + }, + "start": Position { + "column": 2, + "line": 36, + }, + }, + "start": 1005, + "type": "ExpressionStatement", + }, + Node { + "argument": Node { + "arguments": Array [ + Node { + "end": 1054, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 37, + }, + "identifierName": "id", + "start": Position { + "column": 18, + "line": 37, + }, + }, + "name": "id", + "start": 1052, + "type": "Identifier", + }, + ], + "callee": Node { + "end": 1051, + "loc": SourceLocation { + "end": Position { + "column": 17, + "line": 37, + }, + "identifierName": "isActive", + "start": Position { + "column": 9, + "line": 37, + }, + }, + "name": "isActive", + "start": 1043, + "type": "Identifier", + }, + "end": 1055, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 37, + }, + "start": Position { + "column": 9, + "line": 37, + }, + }, + "start": 1043, + "type": "CallExpression", + }, + "end": 1056, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 37, + }, + "start": Position { + "column": 2, + "line": 37, + }, + }, + "start": 1036, + "type": "ReturnStatement", + }, + ], + "directives": Array [], + "end": 1058, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 38, + }, + "start": Position { + "column": 30, + "line": 31, + }, + }, + "start": 909, + "type": "BlockStatement", + }, + "end": 1058, + "generator": false, + "id": Node { + "end": 904, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 31, + }, + "identifierName": "stryMutAct_9fa48", + "start": Position { + "column": 9, + "line": 31, + }, + }, + "name": "stryMutAct_9fa48", + "start": 888, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 38, + }, + "start": Position { + "column": 0, + "line": 31, + }, + }, + "params": Array [ + Node { + "end": 907, + "loc": SourceLocation { + "end": Position { + "column": 28, + "line": 31, + }, + "identifierName": "id", + "start": Position { + "column": 26, + "line": 31, + }, + }, + "name": "id", + "start": 905, + "type": "Identifier", + }, + ], + "start": 879, + "type": "FunctionDeclaration", + }, + Node { + "declarations": Array [ + Node { + "end": 26, + "id": Node { + "end": 17, + "loc": SourceLocation { + "end": Position { + "column": 17, + "line": 1, + }, + "identifierName": "foo", + "start": Position { + "column": 6, + "line": 1, + }, + }, + "name": "foo", + "start": 6, + "type": "Identifier", + "typeAnnotation": Node { + "end": 17, + "loc": SourceLocation { + "end": Position { + "column": 17, + "line": 1, + }, + "start": Position { + "column": 9, + "line": 1, + }, + }, + "start": 9, + "type": "TSTypeAnnotation", + "typeAnnotation": Node { + "end": 17, + "loc": SourceLocation { + "end": Position { + "column": 17, + "line": 1, + }, + "start": Position { + "column": 11, + "line": 1, + }, + }, + "start": 11, + "type": "TSNumberKeyword", + }, + }, + }, + "init": Object { + "alternate": Object { + "expressions": Array [ + Object { + "arguments": Array [ + Object { + "type": "NumericLiteral", + "value": 0, + }, + ], + "callee": Object { + "name": "stryCov_9fa48", + "type": "Identifier", + }, + "type": "CallExpression", + }, + Node { + "end": 26, + "innerComments": null, + "leadingComments": null, + "left": Node { + "end": 22, + "extra": Object { + "raw": "40", + "rawValue": 40, + }, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 1, + }, + "start": Position { + "column": 20, + "line": 1, + }, + }, + "start": 20, + "type": "NumericLiteral", + "value": 40, + }, + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 1, + }, + "start": Position { + "column": 20, + "line": 1, + }, + }, + "operator": "+", + "right": Node { + "end": 26, + "extra": Object { + "raw": "2", + "rawValue": 2, + }, + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 1, + }, + "start": Position { + "column": 25, + "line": 1, + }, + }, + "start": 25, + "type": "NumericLiteral", + "value": 2, + }, + "start": 20, + "trailingComments": null, + "type": "BinaryExpression", + }, + ], + "innerComments": null, + "leadingComments": null, + "trailingComments": null, + "type": "SequenceExpression", + }, + "consequent": Object { + "end": 26, + "left": Node { + "end": 22, + "extra": Object { + "raw": "40", + "rawValue": 40, + }, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 1, + }, + "start": Position { + "column": 20, + "line": 1, + }, + }, + "start": 20, + "type": "NumericLiteral", + "value": 40, + }, + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 1, + }, + "start": Position { + "column": 20, + "line": 1, + }, + }, + "operator": "-", + "right": Node { + "end": 26, + "extra": Object { + "raw": "2", + "rawValue": 2, + }, + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 1, + }, + "start": Position { + "column": 25, + "line": 1, + }, + }, + "start": 25, + "type": "NumericLiteral", + "value": 2, + }, + "start": 20, + "type": "BinaryExpression", + }, + "innerComments": Array [], + "leadingComments": Array [], + "test": Object { + "arguments": Array [ + Object { + "type": "NumericLiteral", + "value": 0, + }, + ], + "callee": Object { + "name": "stryMutAct_9fa48", + "type": "Identifier", + }, + "type": "CallExpression", + }, + "trailingComments": Array [], + "type": "ConditionalExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 1, + }, + "start": Position { + "column": 6, + "line": 1, + }, + }, + "start": 6, + "type": "VariableDeclarator", + }, + ], + "end": 26, + "kind": "const", + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 1, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "start": 0, + "type": "VariableDeclaration", + }, + ], + "directives": Array [], + "end": 26, + "interpreter": null, + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 1, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "sourceType": "module", + "start": 0, + "type": "Program", + }, + "start": 0, + "type": "File", + }, +} +`; + +exports[`transformers integration should transform an html file 1`] = ` +Object { + "format": "html", + "originFileName": "example.html", + "rawContent": "", + "root": Object { + "scripts": Array [ + Object { + "format": "js", + "originFileName": "example.js", + "rawContent": "const foo = 40 + 2", + "root": Node { + "comments": Array [], + "end": 18, + "errors": Array [], + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 1, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "program": Node { + "body": Array [ + Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "declarations": Array [ + Node { + "end": 64, + "id": Node { + "end": 32, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 2, + }, + "identifierName": "g", + "start": Position { + "column": 6, + "line": 2, + }, + }, + "name": "g", + "start": 31, + "type": "Identifier", + }, + "init": Node { + "arguments": Array [], + "callee": Node { + "arguments": Array [ + Node { + "end": 61, + "extra": Object { + "raw": "\\"return this\\"", + "rawValue": "return this", + }, + "loc": SourceLocation { + "end": Position { + "column": 36, + "line": 2, + }, + "start": Position { + "column": 23, + "line": 2, + }, + }, + "start": 48, + "type": "StringLiteral", + "value": "return this", + }, + ], + "callee": Node { + "end": 47, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 2, + }, + "identifierName": "Function", + "start": Position { + "column": 14, + "line": 2, + }, + }, + "name": "Function", + "start": 39, + "type": "Identifier", + }, + "end": 62, + "loc": SourceLocation { + "end": Position { + "column": 37, + "line": 2, + }, + "start": Position { + "column": 10, + "line": 2, + }, + }, + "start": 35, + "type": "NewExpression", + }, + "end": 64, + "loc": SourceLocation { + "end": Position { + "column": 39, + "line": 2, + }, + "start": Position { + "column": 10, + "line": 2, + }, + }, + "start": 35, + "type": "CallExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 39, + "line": 2, + }, + "start": Position { + "column": 6, + "line": 2, + }, + }, + "start": 31, + "type": "VariableDeclarator", + }, + ], + "end": 65, + "kind": "var", + "loc": SourceLocation { + "end": Position { + "column": 40, + "line": 2, + }, + "start": Position { + "column": 2, + "line": 2, + }, + }, + "start": 27, + "type": "VariableDeclaration", + }, + Node { + "declarations": Array [ + Node { + "end": 114, + "id": Node { + "end": 74, + "loc": SourceLocation { + "end": Position { + "column": 8, + "line": 3, + }, + "identifierName": "ns", + "start": Position { + "column": 6, + "line": 3, + }, + }, + "name": "ns", + "start": 72, + "type": "Identifier", + }, + "init": Node { + "end": 114, + "left": Node { + "computed": false, + "end": 90, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 3, + }, + "start": Position { + "column": 11, + "line": 3, + }, + }, + "object": Node { + "end": 78, + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 3, + }, + "identifierName": "g", + "start": Position { + "column": 11, + "line": 3, + }, + }, + "name": "g", + "start": 77, + "type": "Identifier", + }, + "property": Node { + "end": 90, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 3, + }, + "identifierName": "__stryker__", + "start": Position { + "column": 13, + "line": 3, + }, + }, + "name": "__stryker__", + "start": 79, + "type": "Identifier", + }, + "start": 77, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 48, + "line": 3, + }, + "start": Position { + "column": 11, + "line": 3, + }, + }, + "operator": "||", + "right": Node { + "end": 113, + "extra": Object { + "parenStart": 94, + "parenthesized": true, + }, + "left": Node { + "computed": false, + "end": 108, + "loc": SourceLocation { + "end": Position { + "column": 42, + "line": 3, + }, + "start": Position { + "column": 29, + "line": 3, + }, + }, + "object": Node { + "end": 96, + "loc": SourceLocation { + "end": Position { + "column": 30, + "line": 3, + }, + "identifierName": "g", + "start": Position { + "column": 29, + "line": 3, + }, + }, + "name": "g", + "start": 95, + "type": "Identifier", + }, + "property": Node { + "end": 108, + "loc": SourceLocation { + "end": Position { + "column": 42, + "line": 3, + }, + "identifierName": "__stryker__", + "start": Position { + "column": 31, + "line": 3, + }, + }, + "name": "__stryker__", + "start": 97, + "type": "Identifier", + }, + "start": 95, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 47, + "line": 3, + }, + "start": Position { + "column": 29, + "line": 3, + }, + }, + "operator": "=", + "right": Node { + "end": 113, + "loc": SourceLocation { + "end": Position { + "column": 47, + "line": 3, + }, + "start": Position { + "column": 45, + "line": 3, + }, + }, + "properties": Array [], + "start": 111, + "type": "ObjectExpression", + }, + "start": 95, + "type": "AssignmentExpression", + }, + "start": 77, + "type": "LogicalExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 48, + "line": 3, + }, + "start": Position { + "column": 6, + "line": 3, + }, + }, + "start": 72, + "type": "VariableDeclarator", + }, + ], + "end": 115, + "kind": "var", + "loc": SourceLocation { + "end": Position { + "column": 49, + "line": 3, + }, + "start": Position { + "column": 2, + "line": 3, + }, + }, + "start": 68, + "type": "VariableDeclaration", + }, + Node { + "alternate": null, + "consequent": Node { + "body": Array [ + Node { + "end": 298, + "expression": Node { + "end": 297, + "left": Node { + "computed": false, + "end": 247, + "loc": SourceLocation { + "end": Position { + "column": 19, + "line": 5, + }, + "start": Position { + "column": 4, + "line": 5, + }, + }, + "object": Node { + "end": 234, + "loc": SourceLocation { + "end": Position { + "column": 6, + "line": 5, + }, + "identifierName": "ns", + "start": Position { + "column": 4, + "line": 5, + }, + }, + "name": "ns", + "start": 232, + "type": "Identifier", + }, + "property": Node { + "end": 247, + "loc": SourceLocation { + "end": Position { + "column": 19, + "line": 5, + }, + "identifierName": "activeMutant", + "start": Position { + "column": 7, + "line": 5, + }, + }, + "name": "activeMutant", + "start": 235, + "type": "Identifier", + }, + "start": 232, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 69, + "line": 5, + }, + "start": Position { + "column": 4, + "line": 5, + }, + }, + "operator": "=", + "right": Node { + "arguments": Array [ + Node { + "computed": false, + "end": 296, + "loc": SourceLocation { + "end": Position { + "column": 68, + "line": 5, + }, + "start": Position { + "column": 29, + "line": 5, + }, + }, + "object": Node { + "computed": false, + "end": 270, + "loc": SourceLocation { + "end": Position { + "column": 42, + "line": 5, + }, + "start": Position { + "column": 29, + "line": 5, + }, + }, + "object": Node { + "computed": false, + "end": 266, + "loc": SourceLocation { + "end": Position { + "column": 38, + "line": 5, + }, + "start": Position { + "column": 29, + "line": 5, + }, + }, + "object": Node { + "end": 258, + "loc": SourceLocation { + "end": Position { + "column": 30, + "line": 5, + }, + "identifierName": "g", + "start": Position { + "column": 29, + "line": 5, + }, + }, + "name": "g", + "start": 257, + "type": "Identifier", + }, + "property": Node { + "end": 266, + "loc": SourceLocation { + "end": Position { + "column": 38, + "line": 5, + }, + "identifierName": "process", + "start": Position { + "column": 31, + "line": 5, + }, + }, + "name": "process", + "start": 259, + "type": "Identifier", + }, + "start": 257, + "type": "MemberExpression", + }, + "property": Node { + "end": 270, + "loc": SourceLocation { + "end": Position { + "column": 42, + "line": 5, + }, + "identifierName": "env", + "start": Position { + "column": 39, + "line": 5, + }, + }, + "name": "env", + "start": 267, + "type": "Identifier", + }, + "start": 257, + "type": "MemberExpression", + }, + "property": Node { + "end": 296, + "loc": SourceLocation { + "end": Position { + "column": 68, + "line": 5, + }, + "identifierName": "__STRYKER_ACTIVE_MUTANT__", + "start": Position { + "column": 43, + "line": 5, + }, + }, + "name": "__STRYKER_ACTIVE_MUTANT__", + "start": 271, + "type": "Identifier", + }, + "start": 257, + "type": "MemberExpression", + }, + ], + "callee": Node { + "end": 256, + "loc": SourceLocation { + "end": Position { + "column": 28, + "line": 5, + }, + "identifierName": "Number", + "start": Position { + "column": 22, + "line": 5, + }, + }, + "name": "Number", + "start": 250, + "type": "Identifier", + }, + "end": 297, + "loc": SourceLocation { + "end": Position { + "column": 69, + "line": 5, + }, + "start": Position { + "column": 22, + "line": 5, + }, + }, + "start": 250, + "type": "CallExpression", + }, + "start": 232, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 70, + "line": 5, + }, + "start": Position { + "column": 4, + "line": 5, + }, + }, + "start": 232, + "type": "ExpressionStatement", + }, + ], + "directives": Array [], + "end": 302, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 6, + }, + "start": Position { + "column": 110, + "line": 4, + }, + }, + "start": 226, + "type": "BlockStatement", + }, + "end": 302, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 6, + }, + "start": Position { + "column": 2, + "line": 4, + }, + }, + "start": 118, + "test": Node { + "end": 224, + "left": Node { + "end": 181, + "left": Node { + "end": 164, + "left": Node { + "end": 151, + "left": Node { + "computed": false, + "end": 137, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 4, + }, + "start": Position { + "column": 6, + "line": 4, + }, + }, + "object": Node { + "end": 124, + "loc": SourceLocation { + "end": Position { + "column": 8, + "line": 4, + }, + "identifierName": "ns", + "start": Position { + "column": 6, + "line": 4, + }, + }, + "name": "ns", + "start": 122, + "type": "Identifier", + }, + "property": Node { + "end": 137, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 4, + }, + "identifierName": "activeMutant", + "start": Position { + "column": 9, + "line": 4, + }, + }, + "name": "activeMutant", + "start": 125, + "type": "Identifier", + }, + "start": 122, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 35, + "line": 4, + }, + "start": Position { + "column": 6, + "line": 4, + }, + }, + "operator": "===", + "right": Node { + "end": 151, + "loc": SourceLocation { + "end": Position { + "column": 35, + "line": 4, + }, + "identifierName": "undefined", + "start": Position { + "column": 26, + "line": 4, + }, + }, + "name": "undefined", + "start": 142, + "type": "Identifier", + }, + "start": 122, + "type": "BinaryExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 48, + "line": 4, + }, + "start": Position { + "column": 6, + "line": 4, + }, + }, + "operator": "&&", + "right": Node { + "computed": false, + "end": 164, + "loc": SourceLocation { + "end": Position { + "column": 48, + "line": 4, + }, + "start": Position { + "column": 39, + "line": 4, + }, + }, + "object": Node { + "end": 156, + "loc": SourceLocation { + "end": Position { + "column": 40, + "line": 4, + }, + "identifierName": "g", + "start": Position { + "column": 39, + "line": 4, + }, + }, + "name": "g", + "start": 155, + "type": "Identifier", + }, + "property": Node { + "end": 164, + "loc": SourceLocation { + "end": Position { + "column": 48, + "line": 4, + }, + "identifierName": "process", + "start": Position { + "column": 41, + "line": 4, + }, + }, + "name": "process", + "start": 157, + "type": "Identifier", + }, + "start": 155, + "type": "MemberExpression", + }, + "start": 122, + "type": "LogicalExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 65, + "line": 4, + }, + "start": Position { + "column": 6, + "line": 4, + }, + }, + "operator": "&&", + "right": Node { + "computed": false, + "end": 181, + "loc": SourceLocation { + "end": Position { + "column": 65, + "line": 4, + }, + "start": Position { + "column": 52, + "line": 4, + }, + }, + "object": Node { + "computed": false, + "end": 177, + "loc": SourceLocation { + "end": Position { + "column": 61, + "line": 4, + }, + "start": Position { + "column": 52, + "line": 4, + }, + }, + "object": Node { + "end": 169, + "loc": SourceLocation { + "end": Position { + "column": 53, + "line": 4, + }, + "identifierName": "g", + "start": Position { + "column": 52, + "line": 4, + }, + }, + "name": "g", + "start": 168, + "type": "Identifier", + }, + "property": Node { + "end": 177, + "loc": SourceLocation { + "end": Position { + "column": 61, + "line": 4, + }, + "identifierName": "process", + "start": Position { + "column": 54, + "line": 4, + }, + }, + "name": "process", + "start": 170, + "type": "Identifier", + }, + "start": 168, + "type": "MemberExpression", + }, + "property": Node { + "end": 181, + "loc": SourceLocation { + "end": Position { + "column": 65, + "line": 4, + }, + "identifierName": "env", + "start": Position { + "column": 62, + "line": 4, + }, + }, + "name": "env", + "start": 178, + "type": "Identifier", + }, + "start": 168, + "type": "MemberExpression", + }, + "start": 122, + "type": "LogicalExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 108, + "line": 4, + }, + "start": Position { + "column": 6, + "line": 4, + }, + }, + "operator": "&&", + "right": Node { + "computed": false, + "end": 224, + "loc": SourceLocation { + "end": Position { + "column": 108, + "line": 4, + }, + "start": Position { + "column": 69, + "line": 4, + }, + }, + "object": Node { + "computed": false, + "end": 198, + "loc": SourceLocation { + "end": Position { + "column": 82, + "line": 4, + }, + "start": Position { + "column": 69, + "line": 4, + }, + }, + "object": Node { + "computed": false, + "end": 194, + "loc": SourceLocation { + "end": Position { + "column": 78, + "line": 4, + }, + "start": Position { + "column": 69, + "line": 4, + }, + }, + "object": Node { + "end": 186, + "loc": SourceLocation { + "end": Position { + "column": 70, + "line": 4, + }, + "identifierName": "g", + "start": Position { + "column": 69, + "line": 4, + }, + }, + "name": "g", + "start": 185, + "type": "Identifier", + }, + "property": Node { + "end": 194, + "loc": SourceLocation { + "end": Position { + "column": 78, + "line": 4, + }, + "identifierName": "process", + "start": Position { + "column": 71, + "line": 4, + }, + }, + "name": "process", + "start": 187, + "type": "Identifier", + }, + "start": 185, + "type": "MemberExpression", + }, + "property": Node { + "end": 198, + "loc": SourceLocation { + "end": Position { + "column": 82, + "line": 4, + }, + "identifierName": "env", + "start": Position { + "column": 79, + "line": 4, + }, + }, + "name": "env", + "start": 195, + "type": "Identifier", + }, + "start": 185, + "type": "MemberExpression", + }, + "property": Node { + "end": 224, + "loc": SourceLocation { + "end": Position { + "column": 108, + "line": 4, + }, + "identifierName": "__STRYKER_ACTIVE_MUTANT__", + "start": Position { + "column": 83, + "line": 4, + }, + }, + "name": "__STRYKER_ACTIVE_MUTANT__", + "start": 199, + "type": "Identifier", + }, + "start": 185, + "type": "MemberExpression", + }, + "start": 122, + "type": "LogicalExpression", + }, + "type": "IfStatement", + }, + Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "argument": Node { + "end": 341, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 8, + }, + "identifierName": "ns", + "start": Position { + "column": 11, + "line": 8, + }, + }, + "name": "ns", + "start": 339, + "type": "Identifier", + }, + "end": 342, + "loc": SourceLocation { + "end": Position { + "column": 14, + "line": 8, + }, + "start": Position { + "column": 4, + "line": 8, + }, + }, + "start": 332, + "type": "ReturnStatement", + }, + ], + "directives": Array [], + "end": 346, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 9, + }, + "start": Position { + "column": 23, + "line": 7, + }, + }, + "start": 326, + "type": "BlockStatement", + }, + "end": 346, + "generator": false, + "id": Node { + "end": 324, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 7, + }, + "identifierName": "retrieveNS", + "start": Position { + "column": 11, + "line": 7, + }, + }, + "name": "retrieveNS", + "start": 314, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 9, + }, + "start": Position { + "column": 2, + "line": 7, + }, + }, + "params": Array [], + "start": 305, + "type": "FunctionDeclaration", + }, + Node { + "end": 375, + "expression": Node { + "end": 374, + "left": Node { + "end": 361, + "loc": SourceLocation { + "end": Position { + "column": 14, + "line": 10, + }, + "identifierName": "stryNS_9fa48", + "start": Position { + "column": 2, + "line": 10, + }, + }, + "name": "stryNS_9fa48", + "start": 349, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 27, + "line": 10, + }, + "start": Position { + "column": 2, + "line": 10, + }, + }, + "operator": "=", + "right": Node { + "end": 374, + "loc": SourceLocation { + "end": Position { + "column": 27, + "line": 10, + }, + "identifierName": "retrieveNS", + "start": Position { + "column": 17, + "line": 10, + }, + }, + "name": "retrieveNS", + "start": 364, + "type": "Identifier", + }, + "start": 349, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 28, + "line": 10, + }, + "start": Position { + "column": 2, + "line": 10, + }, + }, + "start": 349, + "type": "ExpressionStatement", + }, + Node { + "argument": Node { + "arguments": Array [], + "callee": Node { + "end": 395, + "loc": SourceLocation { + "end": Position { + "column": 19, + "line": 11, + }, + "identifierName": "retrieveNS", + "start": Position { + "column": 9, + "line": 11, + }, + }, + "name": "retrieveNS", + "start": 385, + "type": "Identifier", + }, + "end": 397, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 11, + }, + "start": Position { + "column": 9, + "line": 11, + }, + }, + "start": 385, + "type": "CallExpression", + }, + "end": 398, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 11, + }, + "start": Position { + "column": 2, + "line": 11, + }, + }, + "start": 378, + "type": "ReturnStatement", + }, + ], + "directives": Array [], + "end": 400, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 12, + }, + "start": Position { + "column": 23, + "line": 1, + }, + }, + "start": 23, + "type": "BlockStatement", + }, + "end": 400, + "generator": false, + "id": Node { + "end": 21, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 1, + }, + "identifierName": "stryNS_9fa48", + "start": Position { + "column": 9, + "line": 1, + }, + }, + "name": "stryNS_9fa48", + "start": 9, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 12, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "params": Array [], + "start": 0, + "type": "FunctionDeclaration", + }, + Node { + "end": 416, + "expression": Node { + "arguments": Array [], + "callee": Node { + "end": 413, + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 13, + }, + "identifierName": "stryNS_9fa48", + "start": Position { + "column": 0, + "line": 13, + }, + }, + "name": "stryNS_9fa48", + "start": 401, + "type": "Identifier", + }, + "end": 415, + "loc": SourceLocation { + "end": Position { + "column": 14, + "line": 13, + }, + "start": Position { + "column": 0, + "line": 13, + }, + }, + "start": 401, + "type": "CallExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 13, + }, + "start": Position { + "column": 0, + "line": 13, + }, + }, + "start": 401, + "type": "ExpressionStatement", + }, + Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "declarations": Array [ + Node { + "end": 470, + "id": Node { + "end": 453, + "loc": SourceLocation { + "end": Position { + "column": 8, + "line": 16, + }, + "identifierName": "ns", + "start": Position { + "column": 6, + "line": 16, + }, + }, + "name": "ns", + "start": 451, + "type": "Identifier", + }, + "init": Node { + "arguments": Array [], + "callee": Node { + "end": 468, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 16, + }, + "identifierName": "stryNS_9fa48", + "start": Position { + "column": 11, + "line": 16, + }, + }, + "name": "stryNS_9fa48", + "start": 456, + "type": "Identifier", + }, + "end": 470, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 16, + }, + "start": Position { + "column": 11, + "line": 16, + }, + }, + "start": 456, + "type": "CallExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 16, + }, + "start": Position { + "column": 6, + "line": 16, + }, + }, + "start": 451, + "type": "VariableDeclarator", + }, + ], + "end": 471, + "kind": "var", + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 16, + }, + "start": Position { + "column": 2, + "line": 16, + }, + }, + "start": 447, + "type": "VariableDeclaration", + }, + Node { + "declarations": Array [ + Node { + "end": 554, + "id": Node { + "end": 481, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 17, + }, + "identifierName": "cov", + "start": Position { + "column": 6, + "line": 17, + }, + }, + "name": "cov", + "start": 478, + "type": "Identifier", + }, + "init": Node { + "end": 554, + "left": Node { + "computed": false, + "end": 501, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 17, + }, + "start": Position { + "column": 12, + "line": 17, + }, + }, + "object": Node { + "end": 486, + "loc": SourceLocation { + "end": Position { + "column": 14, + "line": 17, + }, + "identifierName": "ns", + "start": Position { + "column": 12, + "line": 17, + }, + }, + "name": "ns", + "start": 484, + "type": "Identifier", + }, + "property": Node { + "end": 501, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 17, + }, + "identifierName": "mutantCoverage", + "start": Position { + "column": 15, + "line": 17, + }, + }, + "name": "mutantCoverage", + "start": 487, + "type": "Identifier", + }, + "start": 484, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 82, + "line": 17, + }, + "start": Position { + "column": 12, + "line": 17, + }, + }, + "operator": "||", + "right": Node { + "end": 553, + "extra": Object { + "parenStart": 505, + "parenthesized": true, + }, + "left": Node { + "computed": false, + "end": 523, + "loc": SourceLocation { + "end": Position { + "column": 51, + "line": 17, + }, + "start": Position { + "column": 34, + "line": 17, + }, + }, + "object": Node { + "end": 508, + "loc": SourceLocation { + "end": Position { + "column": 36, + "line": 17, + }, + "identifierName": "ns", + "start": Position { + "column": 34, + "line": 17, + }, + }, + "name": "ns", + "start": 506, + "type": "Identifier", + }, + "property": Node { + "end": 523, + "loc": SourceLocation { + "end": Position { + "column": 51, + "line": 17, + }, + "identifierName": "mutantCoverage", + "start": Position { + "column": 37, + "line": 17, + }, + }, + "name": "mutantCoverage", + "start": 509, + "type": "Identifier", + }, + "start": 506, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 81, + "line": 17, + }, + "start": Position { + "column": 34, + "line": 17, + }, + }, + "operator": "=", + "right": Node { + "end": 553, + "loc": SourceLocation { + "end": Position { + "column": 81, + "line": 17, + }, + "start": Position { + "column": 54, + "line": 17, + }, + }, + "properties": Array [ + Node { + "computed": false, + "end": 538, + "key": Node { + "end": 534, + "loc": SourceLocation { + "end": Position { + "column": 62, + "line": 17, + }, + "identifierName": "static", + "start": Position { + "column": 56, + "line": 17, + }, + }, + "name": "static", + "start": 528, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 66, + "line": 17, + }, + "start": Position { + "column": 56, + "line": 17, + }, + }, + "method": false, + "shorthand": false, + "start": 528, + "type": "ObjectProperty", + "value": Node { + "end": 538, + "loc": SourceLocation { + "end": Position { + "column": 66, + "line": 17, + }, + "start": Position { + "column": 64, + "line": 17, + }, + }, + "properties": Array [], + "start": 536, + "type": "ObjectExpression", + }, + }, + Node { + "computed": false, + "end": 551, + "key": Node { + "end": 547, + "loc": SourceLocation { + "end": Position { + "column": 75, + "line": 17, + }, + "identifierName": "perTest", + "start": Position { + "column": 68, + "line": 17, + }, + }, + "name": "perTest", + "start": 540, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 79, + "line": 17, + }, + "start": Position { + "column": 68, + "line": 17, + }, + }, + "method": false, + "shorthand": false, + "start": 540, + "type": "ObjectProperty", + "value": Node { + "end": 551, + "loc": SourceLocation { + "end": Position { + "column": 79, + "line": 17, + }, + "start": Position { + "column": 77, + "line": 17, + }, + }, + "properties": Array [], + "start": 549, + "type": "ObjectExpression", + }, + }, + ], + "start": 526, + "type": "ObjectExpression", + }, + "start": 506, + "type": "AssignmentExpression", + }, + "start": 484, + "type": "LogicalExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 82, + "line": 17, + }, + "start": Position { + "column": 6, + "line": 17, + }, + }, + "start": 478, + "type": "VariableDeclarator", + }, + ], + "end": 555, + "kind": "var", + "loc": SourceLocation { + "end": Position { + "column": 83, + "line": 17, + }, + "start": Position { + "column": 2, + "line": 17, + }, + }, + "start": 474, + "type": "VariableDeclaration", + }, + Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "declarations": Array [ + Node { + "end": 599, + "id": Node { + "end": 586, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 19, + }, + "identifierName": "c", + "start": Position { + "column": 8, + "line": 19, + }, + }, + "name": "c", + "start": 585, + "type": "Identifier", + }, + "init": Node { + "computed": false, + "end": 599, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 19, + }, + "start": Position { + "column": 12, + "line": 19, + }, + }, + "object": Node { + "end": 592, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 19, + }, + "identifierName": "cov", + "start": Position { + "column": 12, + "line": 19, + }, + }, + "name": "cov", + "start": 589, + "type": "Identifier", + }, + "property": Node { + "end": 599, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 19, + }, + "identifierName": "static", + "start": Position { + "column": 16, + "line": 19, + }, + }, + "name": "static", + "start": 593, + "type": "Identifier", + }, + "start": 589, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 19, + }, + "start": Position { + "column": 8, + "line": 19, + }, + }, + "start": 585, + "type": "VariableDeclarator", + }, + ], + "end": 600, + "kind": "var", + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 19, + }, + "start": Position { + "column": 4, + "line": 19, + }, + }, + "start": 581, + "type": "VariableDeclaration", + }, + Node { + "alternate": null, + "consequent": Node { + "body": Array [ + Node { + "end": 707, + "expression": Node { + "end": 706, + "left": Node { + "end": 636, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 21, + }, + "identifierName": "c", + "start": Position { + "column": 6, + "line": 21, + }, + }, + "name": "c", + "start": 635, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 77, + "line": 21, + }, + "start": Position { + "column": 6, + "line": 21, + }, + }, + "operator": "=", + "right": Node { + "end": 706, + "left": Node { + "computed": true, + "end": 668, + "loc": SourceLocation { + "end": Position { + "column": 39, + "line": 21, + }, + "start": Position { + "column": 10, + "line": 21, + }, + }, + "object": Node { + "computed": false, + "end": 650, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 21, + }, + "start": Position { + "column": 10, + "line": 21, + }, + }, + "object": Node { + "end": 642, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 21, + }, + "identifierName": "cov", + "start": Position { + "column": 10, + "line": 21, + }, + }, + "name": "cov", + "start": 639, + "type": "Identifier", + }, + "property": Node { + "end": 650, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 21, + }, + "identifierName": "perTest", + "start": Position { + "column": 14, + "line": 21, + }, + }, + "name": "perTest", + "start": 643, + "type": "Identifier", + }, + "start": 639, + "type": "MemberExpression", + }, + "property": Node { + "computed": false, + "end": 667, + "loc": SourceLocation { + "end": Position { + "column": 38, + "line": 21, + }, + "start": Position { + "column": 22, + "line": 21, + }, + }, + "object": Node { + "end": 653, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 21, + }, + "identifierName": "ns", + "start": Position { + "column": 22, + "line": 21, + }, + }, + "name": "ns", + "start": 651, + "type": "Identifier", + }, + "property": Node { + "end": 667, + "loc": SourceLocation { + "end": Position { + "column": 38, + "line": 21, + }, + "identifierName": "currentTestId", + "start": Position { + "column": 25, + "line": 21, + }, + }, + "name": "currentTestId", + "start": 654, + "type": "Identifier", + }, + "start": 651, + "type": "MemberExpression", + }, + "start": 639, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 77, + "line": 21, + }, + "start": Position { + "column": 10, + "line": 21, + }, + }, + "operator": "=", + "right": Node { + "end": 706, + "left": Node { + "computed": true, + "end": 700, + "loc": SourceLocation { + "end": Position { + "column": 71, + "line": 21, + }, + "start": Position { + "column": 42, + "line": 21, + }, + }, + "object": Node { + "computed": false, + "end": 682, + "loc": SourceLocation { + "end": Position { + "column": 53, + "line": 21, + }, + "start": Position { + "column": 42, + "line": 21, + }, + }, + "object": Node { + "end": 674, + "loc": SourceLocation { + "end": Position { + "column": 45, + "line": 21, + }, + "identifierName": "cov", + "start": Position { + "column": 42, + "line": 21, + }, + }, + "name": "cov", + "start": 671, + "type": "Identifier", + }, + "property": Node { + "end": 682, + "loc": SourceLocation { + "end": Position { + "column": 53, + "line": 21, + }, + "identifierName": "perTest", + "start": Position { + "column": 46, + "line": 21, + }, + }, + "name": "perTest", + "start": 675, + "type": "Identifier", + }, + "start": 671, + "type": "MemberExpression", + }, + "property": Node { + "computed": false, + "end": 699, + "loc": SourceLocation { + "end": Position { + "column": 70, + "line": 21, + }, + "start": Position { + "column": 54, + "line": 21, + }, + }, + "object": Node { + "end": 685, + "loc": SourceLocation { + "end": Position { + "column": 56, + "line": 21, + }, + "identifierName": "ns", + "start": Position { + "column": 54, + "line": 21, + }, + }, + "name": "ns", + "start": 683, + "type": "Identifier", + }, + "property": Node { + "end": 699, + "loc": SourceLocation { + "end": Position { + "column": 70, + "line": 21, + }, + "identifierName": "currentTestId", + "start": Position { + "column": 57, + "line": 21, + }, + }, + "name": "currentTestId", + "start": 686, + "type": "Identifier", + }, + "start": 683, + "type": "MemberExpression", + }, + "start": 671, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 77, + "line": 21, + }, + "start": Position { + "column": 42, + "line": 21, + }, + }, + "operator": "||", + "right": Node { + "end": 706, + "loc": SourceLocation { + "end": Position { + "column": 77, + "line": 21, + }, + "start": Position { + "column": 75, + "line": 21, + }, + }, + "properties": Array [], + "start": 704, + "type": "ObjectExpression", + }, + "start": 671, + "type": "LogicalExpression", + }, + "start": 639, + "type": "AssignmentExpression", + }, + "start": 635, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 78, + "line": 21, + }, + "start": Position { + "column": 6, + "line": 21, + }, + }, + "start": 635, + "type": "ExpressionStatement", + }, + ], + "directives": Array [], + "end": 713, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 22, + }, + "start": Position { + "column": 26, + "line": 20, + }, + }, + "start": 627, + "type": "BlockStatement", + }, + "end": 713, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 22, + }, + "start": Position { + "column": 4, + "line": 20, + }, + }, + "start": 605, + "test": Node { + "computed": false, + "end": 625, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 20, + }, + "start": Position { + "column": 8, + "line": 20, + }, + }, + "object": Node { + "end": 611, + "loc": SourceLocation { + "end": Position { + "column": 10, + "line": 20, + }, + "identifierName": "ns", + "start": Position { + "column": 8, + "line": 20, + }, + }, + "name": "ns", + "start": 609, + "type": "Identifier", + }, + "property": Node { + "end": 625, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 20, + }, + "identifierName": "currentTestId", + "start": Position { + "column": 11, + "line": 20, + }, + }, + "name": "currentTestId", + "start": 612, + "type": "Identifier", + }, + "start": 609, + "type": "MemberExpression", + }, + "type": "IfStatement", + }, + Node { + "declarations": Array [ + Node { + "end": 735, + "id": Node { + "end": 723, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 23, + }, + "identifierName": "a", + "start": Position { + "column": 8, + "line": 23, + }, + }, + "name": "a", + "start": 722, + "type": "Identifier", + }, + "init": Node { + "end": 735, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 23, + }, + "identifierName": "arguments", + "start": Position { + "column": 12, + "line": 23, + }, + }, + "name": "arguments", + "start": 726, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 23, + }, + "start": Position { + "column": 8, + "line": 23, + }, + }, + "start": 722, + "type": "VariableDeclarator", + }, + ], + "end": 736, + "kind": "var", + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 23, + }, + "start": Position { + "column": 4, + "line": 23, + }, + }, + "start": 718, + "type": "VariableDeclaration", + }, + Node { + "body": Node { + "body": Array [ + Node { + "end": 809, + "expression": Node { + "end": 808, + "left": Node { + "computed": true, + "end": 787, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 25, + }, + "start": Position { + "column": 6, + "line": 25, + }, + }, + "object": Node { + "end": 781, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 25, + }, + "identifierName": "c", + "start": Position { + "column": 6, + "line": 25, + }, + }, + "name": "c", + "start": 780, + "type": "Identifier", + }, + "property": Node { + "computed": true, + "end": 786, + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 25, + }, + "start": Position { + "column": 8, + "line": 25, + }, + }, + "object": Node { + "end": 783, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 25, + }, + "identifierName": "a", + "start": Position { + "column": 8, + "line": 25, + }, + }, + "name": "a", + "start": 782, + "type": "Identifier", + }, + "property": Node { + "end": 785, + "loc": SourceLocation { + "end": Position { + "column": 11, + "line": 25, + }, + "identifierName": "i", + "start": Position { + "column": 10, + "line": 25, + }, + }, + "name": "i", + "start": 784, + "type": "Identifier", + }, + "start": 782, + "type": "MemberExpression", + }, + "start": 780, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 25, + }, + "start": Position { + "column": 6, + "line": 25, + }, + }, + "operator": "=", + "right": Node { + "end": 808, + "left": Node { + "end": 803, + "extra": Object { + "parenStart": 790, + "parenthesized": true, + }, + "left": Node { + "computed": true, + "end": 798, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 25, + }, + "start": Position { + "column": 17, + "line": 25, + }, + }, + "object": Node { + "end": 792, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 25, + }, + "identifierName": "c", + "start": Position { + "column": 17, + "line": 25, + }, + }, + "name": "c", + "start": 791, + "type": "Identifier", + }, + "property": Node { + "computed": true, + "end": 797, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 25, + }, + "start": Position { + "column": 19, + "line": 25, + }, + }, + "object": Node { + "end": 794, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 25, + }, + "identifierName": "a", + "start": Position { + "column": 19, + "line": 25, + }, + }, + "name": "a", + "start": 793, + "type": "Identifier", + }, + "property": Node { + "end": 796, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 25, + }, + "identifierName": "i", + "start": Position { + "column": 21, + "line": 25, + }, + }, + "name": "i", + "start": 795, + "type": "Identifier", + }, + "start": 793, + "type": "MemberExpression", + }, + "start": 791, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 25, + }, + "start": Position { + "column": 17, + "line": 25, + }, + }, + "operator": "||", + "right": Node { + "end": 803, + "extra": Object { + "raw": "0", + "rawValue": 0, + }, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 25, + }, + "start": Position { + "column": 28, + "line": 25, + }, + }, + "start": 802, + "type": "NumericLiteral", + "value": 0, + }, + "start": 791, + "type": "LogicalExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 25, + }, + "start": Position { + "column": 16, + "line": 25, + }, + }, + "operator": "+", + "right": Node { + "end": 808, + "extra": Object { + "raw": "1", + "rawValue": 1, + }, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 25, + }, + "start": Position { + "column": 33, + "line": 25, + }, + }, + "start": 807, + "type": "NumericLiteral", + "value": 1, + }, + "start": 790, + "type": "BinaryExpression", + }, + "start": 780, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 35, + "line": 25, + }, + "start": Position { + "column": 6, + "line": 25, + }, + }, + "start": 780, + "type": "ExpressionStatement", + }, + ], + "directives": Array [], + "end": 815, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 26, + }, + "start": Position { + "column": 35, + "line": 24, + }, + }, + "start": 772, + "type": "BlockStatement", + }, + "end": 815, + "init": Node { + "declarations": Array [ + Node { + "end": 752, + "id": Node { + "end": 750, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 24, + }, + "identifierName": "i", + "start": Position { + "column": 12, + "line": 24, + }, + }, + "name": "i", + "start": 749, + "type": "Identifier", + }, + "init": Node { + "end": 752, + "extra": Object { + "raw": "0", + "rawValue": 0, + }, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 24, + }, + "start": Position { + "column": 14, + "line": 24, + }, + }, + "start": 751, + "type": "NumericLiteral", + "value": 0, + }, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 24, + }, + "start": Position { + "column": 12, + "line": 24, + }, + }, + "start": 749, + "type": "VariableDeclarator", + }, + ], + "end": 752, + "kind": "var", + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 24, + }, + "start": Position { + "column": 8, + "line": 24, + }, + }, + "start": 745, + "type": "VariableDeclaration", + }, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 26, + }, + "start": Position { + "column": 4, + "line": 24, + }, + }, + "start": 741, + "test": Node { + "end": 766, + "left": Node { + "end": 755, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 24, + }, + "identifierName": "i", + "start": Position { + "column": 17, + "line": 24, + }, + }, + "name": "i", + "start": 754, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 24, + }, + "start": Position { + "column": 17, + "line": 24, + }, + }, + "operator": "<", + "right": Node { + "computed": false, + "end": 766, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 24, + }, + "start": Position { + "column": 21, + "line": 24, + }, + }, + "object": Node { + "end": 759, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 24, + }, + "identifierName": "a", + "start": Position { + "column": 21, + "line": 24, + }, + }, + "name": "a", + "start": 758, + "type": "Identifier", + }, + "property": Node { + "end": 766, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 24, + }, + "identifierName": "length", + "start": Position { + "column": 23, + "line": 24, + }, + }, + "name": "length", + "start": 760, + "type": "Identifier", + }, + "start": 758, + "type": "MemberExpression", + }, + "start": 754, + "type": "BinaryExpression", + }, + "type": "ForStatement", + "update": Node { + "argument": Node { + "end": 769, + "loc": SourceLocation { + "end": Position { + "column": 32, + "line": 24, + }, + "identifierName": "i", + "start": Position { + "column": 31, + "line": 24, + }, + }, + "name": "i", + "start": 768, + "type": "Identifier", + }, + "end": 771, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 24, + }, + "start": Position { + "column": 31, + "line": 24, + }, + }, + "operator": "++", + "prefix": false, + "start": 768, + "type": "UpdateExpression", + }, + }, + ], + "directives": Array [], + "end": 819, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 27, + }, + "start": Position { + "column": 19, + "line": 18, + }, + }, + "start": 575, + "type": "BlockStatement", + }, + "end": 819, + "generator": false, + "id": Node { + "end": 572, + "loc": SourceLocation { + "end": Position { + "column": 16, + "line": 18, + }, + "identifierName": "cover", + "start": Position { + "column": 11, + "line": 18, + }, + }, + "name": "cover", + "start": 567, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 27, + }, + "start": Position { + "column": 2, + "line": 18, + }, + }, + "params": Array [], + "start": 558, + "type": "FunctionDeclaration", + }, + Node { + "end": 844, + "expression": Node { + "end": 843, + "left": Node { + "end": 835, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 28, + }, + "identifierName": "stryCov_9fa48", + "start": Position { + "column": 2, + "line": 28, + }, + }, + "name": "stryCov_9fa48", + "start": 822, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 28, + }, + "start": Position { + "column": 2, + "line": 28, + }, + }, + "operator": "=", + "right": Node { + "end": 843, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 28, + }, + "identifierName": "cover", + "start": Position { + "column": 18, + "line": 28, + }, + }, + "name": "cover", + "start": 838, + "type": "Identifier", + }, + "start": 822, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 28, + }, + "start": Position { + "column": 2, + "line": 28, + }, + }, + "start": 822, + "type": "ExpressionStatement", + }, + Node { + "end": 876, + "expression": Node { + "arguments": Array [ + Node { + "end": 863, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 29, + }, + "start": Position { + "column": 14, + "line": 29, + }, + }, + "start": 859, + "type": "NullLiteral", + }, + Node { + "end": 874, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 29, + }, + "identifierName": "arguments", + "start": Position { + "column": 20, + "line": 29, + }, + }, + "name": "arguments", + "start": 865, + "type": "Identifier", + }, + ], + "callee": Node { + "computed": false, + "end": 858, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 29, + }, + "start": Position { + "column": 2, + "line": 29, + }, + }, + "object": Node { + "end": 852, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 29, + }, + "identifierName": "cover", + "start": Position { + "column": 2, + "line": 29, + }, + }, + "name": "cover", + "start": 847, + "type": "Identifier", + }, + "property": Node { + "end": 858, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 29, + }, + "identifierName": "apply", + "start": Position { + "column": 8, + "line": 29, + }, + }, + "name": "apply", + "start": 853, + "type": "Identifier", + }, + "start": 847, + "type": "MemberExpression", + }, + "end": 875, + "loc": SourceLocation { + "end": Position { + "column": 30, + "line": 29, + }, + "start": Position { + "column": 2, + "line": 29, + }, + }, + "start": 847, + "type": "CallExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 31, + "line": 29, + }, + "start": Position { + "column": 2, + "line": 29, + }, + }, + "start": 847, + "type": "ExpressionStatement", + }, + ], + "directives": Array [], + "end": 878, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 30, + }, + "start": Position { + "column": 25, + "line": 15, + }, + }, + "start": 443, + "type": "BlockStatement", + }, + "end": 878, + "generator": false, + "id": Node { + "end": 440, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 15, + }, + "identifierName": "stryCov_9fa48", + "start": Position { + "column": 9, + "line": 15, + }, + }, + "name": "stryCov_9fa48", + "start": 427, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 30, + }, + "start": Position { + "column": 0, + "line": 15, + }, + }, + "params": Array [], + "start": 418, + "type": "FunctionDeclaration", + }, + Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "declarations": Array [ + Node { + "end": 936, + "id": Node { + "end": 919, + "loc": SourceLocation { + "end": Position { + "column": 8, + "line": 32, + }, + "identifierName": "ns", + "start": Position { + "column": 6, + "line": 32, + }, + }, + "name": "ns", + "start": 917, + "type": "Identifier", + }, + "init": Node { + "arguments": Array [], + "callee": Node { + "end": 934, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 32, + }, + "identifierName": "stryNS_9fa48", + "start": Position { + "column": 11, + "line": 32, + }, + }, + "name": "stryNS_9fa48", + "start": 922, + "type": "Identifier", + }, + "end": 936, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 32, + }, + "start": Position { + "column": 11, + "line": 32, + }, + }, + "start": 922, + "type": "CallExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 32, + }, + "start": Position { + "column": 6, + "line": 32, + }, + }, + "start": 917, + "type": "VariableDeclarator", + }, + ], + "end": 937, + "kind": "var", + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 32, + }, + "start": Position { + "column": 2, + "line": 32, + }, + }, + "start": 913, + "type": "VariableDeclaration", + }, + Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "argument": Node { + "end": 997, + "left": Node { + "computed": false, + "end": 990, + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 34, + }, + "start": Position { + "column": 11, + "line": 34, + }, + }, + "object": Node { + "end": 977, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 34, + }, + "identifierName": "ns", + "start": Position { + "column": 11, + "line": 34, + }, + }, + "name": "ns", + "start": 975, + "type": "Identifier", + }, + "property": Node { + "end": 990, + "loc": SourceLocation { + "end": Position { + "column": 26, + "line": 34, + }, + "identifierName": "activeMutant", + "start": Position { + "column": 14, + "line": 34, + }, + }, + "name": "activeMutant", + "start": 978, + "type": "Identifier", + }, + "start": 975, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 33, + "line": 34, + }, + "start": Position { + "column": 11, + "line": 34, + }, + }, + "operator": "===", + "right": Node { + "end": 997, + "loc": SourceLocation { + "end": Position { + "column": 33, + "line": 34, + }, + "identifierName": "id", + "start": Position { + "column": 31, + "line": 34, + }, + }, + "name": "id", + "start": 995, + "type": "Identifier", + }, + "start": 975, + "type": "BinaryExpression", + }, + "end": 998, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 34, + }, + "start": Position { + "column": 4, + "line": 34, + }, + }, + "start": 968, + "type": "ReturnStatement", + }, + ], + "directives": Array [], + "end": 1002, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 35, + }, + "start": Position { + "column": 24, + "line": 33, + }, + }, + "start": 962, + "type": "BlockStatement", + }, + "end": 1002, + "generator": false, + "id": Node { + "end": 957, + "loc": SourceLocation { + "end": Position { + "column": 19, + "line": 33, + }, + "identifierName": "isActive", + "start": Position { + "column": 11, + "line": 33, + }, + }, + "name": "isActive", + "start": 949, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 35, + }, + "start": Position { + "column": 2, + "line": 33, + }, + }, + "params": Array [ + Node { + "end": 960, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 33, + }, + "identifierName": "id", + "start": Position { + "column": 20, + "line": 33, + }, + }, + "name": "id", + "start": 958, + "type": "Identifier", + }, + ], + "start": 940, + "type": "FunctionDeclaration", + }, + Node { + "end": 1033, + "expression": Node { + "end": 1032, + "left": Node { + "end": 1021, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 36, + }, + "identifierName": "stryMutAct_9fa48", + "start": Position { + "column": 2, + "line": 36, + }, + }, + "name": "stryMutAct_9fa48", + "start": 1005, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 36, + }, + "start": Position { + "column": 2, + "line": 36, + }, + }, + "operator": "=", + "right": Node { + "end": 1032, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 36, + }, + "identifierName": "isActive", + "start": Position { + "column": 21, + "line": 36, + }, + }, + "name": "isActive", + "start": 1024, + "type": "Identifier", + }, + "start": 1005, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 30, + "line": 36, + }, + "start": Position { + "column": 2, + "line": 36, + }, + }, + "start": 1005, + "type": "ExpressionStatement", + }, + Node { + "argument": Node { + "arguments": Array [ + Node { + "end": 1054, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 37, + }, + "identifierName": "id", + "start": Position { + "column": 18, + "line": 37, + }, + }, + "name": "id", + "start": 1052, + "type": "Identifier", + }, + ], + "callee": Node { + "end": 1051, + "loc": SourceLocation { + "end": Position { + "column": 17, + "line": 37, + }, + "identifierName": "isActive", + "start": Position { + "column": 9, + "line": 37, + }, + }, + "name": "isActive", + "start": 1043, + "type": "Identifier", + }, + "end": 1055, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 37, + }, + "start": Position { + "column": 9, + "line": 37, + }, + }, + "start": 1043, + "type": "CallExpression", + }, + "end": 1056, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 37, + }, + "start": Position { + "column": 2, + "line": 37, + }, + }, + "start": 1036, + "type": "ReturnStatement", + }, + ], + "directives": Array [], + "end": 1058, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 38, + }, + "start": Position { + "column": 30, + "line": 31, + }, + }, + "start": 909, + "type": "BlockStatement", + }, + "end": 1058, + "generator": false, + "id": Node { + "end": 904, + "loc": SourceLocation { + "end": Position { + "column": 25, + "line": 31, + }, + "identifierName": "stryMutAct_9fa48", + "start": Position { + "column": 9, + "line": 31, + }, + }, + "name": "stryMutAct_9fa48", + "start": 888, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 38, + }, + "start": Position { + "column": 0, + "line": 31, + }, + }, + "params": Array [ + Node { + "end": 907, + "loc": SourceLocation { + "end": Position { + "column": 28, + "line": 31, + }, + "identifierName": "id", + "start": Position { + "column": 26, + "line": 31, + }, + }, + "name": "id", + "start": 905, + "type": "Identifier", + }, + ], + "start": 879, + "type": "FunctionDeclaration", + }, + Node { + "declarations": Array [ + Node { + "end": 18, + "id": Node { + "end": 9, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 1, + }, + "identifierName": "foo", + "start": Position { + "column": 6, + "line": 1, + }, + }, + "name": "foo", + "start": 6, + "type": "Identifier", + }, + "init": Object { + "alternate": Object { + "expressions": Array [ + Object { + "arguments": Array [ + Object { + "type": "NumericLiteral", + "value": 0, + }, + ], + "callee": Object { + "name": "stryCov_9fa48", + "type": "Identifier", + }, + "type": "CallExpression", + }, + Node { + "end": 18, + "innerComments": null, + "leadingComments": null, + "left": Node { + "end": 14, + "extra": Object { + "raw": "40", + "rawValue": 40, + }, + "loc": SourceLocation { + "end": Position { + "column": 14, + "line": 1, + }, + "start": Position { + "column": 12, + "line": 1, + }, + }, + "start": 12, + "type": "NumericLiteral", + "value": 40, + }, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 1, + }, + "start": Position { + "column": 12, + "line": 1, + }, + }, + "operator": "+", + "right": Node { + "end": 18, + "extra": Object { + "raw": "2", + "rawValue": 2, + }, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 1, + }, + "start": Position { + "column": 17, + "line": 1, + }, + }, + "start": 17, + "type": "NumericLiteral", + "value": 2, + }, + "start": 12, + "trailingComments": null, + "type": "BinaryExpression", + }, + ], + "innerComments": null, + "leadingComments": null, + "trailingComments": null, + "type": "SequenceExpression", + }, + "consequent": Object { + "end": 18, + "left": Node { + "end": 14, + "extra": Object { + "raw": "40", + "rawValue": 40, + }, + "loc": SourceLocation { + "end": Position { + "column": 14, + "line": 1, + }, + "start": Position { + "column": 12, + "line": 1, + }, + }, + "start": 12, + "type": "NumericLiteral", + "value": 40, + }, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 1, + }, + "start": Position { + "column": 12, + "line": 1, + }, + }, + "operator": "-", + "right": Node { + "end": 18, + "extra": Object { + "raw": "2", + "rawValue": 2, + }, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 1, + }, + "start": Position { + "column": 17, + "line": 1, + }, + }, + "start": 17, + "type": "NumericLiteral", + "value": 2, + }, + "start": 12, + "type": "BinaryExpression", + }, + "innerComments": Array [], + "leadingComments": Array [], + "test": Object { + "arguments": Array [ + Object { + "type": "NumericLiteral", + "value": 0, + }, + ], + "callee": Object { + "name": "stryMutAct_9fa48", + "type": "Identifier", + }, + "type": "CallExpression", + }, + "trailingComments": Array [], + "type": "ConditionalExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 1, + }, + "start": Position { + "column": 6, + "line": 1, + }, + }, + "start": 6, + "type": "VariableDeclarator", + }, + ], + "end": 18, + "kind": "const", + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 1, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "start": 0, + "type": "VariableDeclaration", + }, + ], + "directives": Array [], + "end": 18, + "interpreter": null, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 1, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "sourceType": "module", + "start": 0, + "type": "Program", + }, + "start": 0, + "type": "File", + }, + }, + ], + }, +} +`; + +exports[`transformers integration should transform html files 1`] = ` +Object { + "format": "html", + "originFileName": "example.html", + "rawContent": "", + "root": Object { + "scripts": Array [ + Object { + "format": "js", + "originFileName": "example.js", + "rawContent": "const foo = 40 + 2", + "root": Node { + "comments": Array [], + "end": 18, + "errors": Array [], + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 1, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "program": Node { + "body": Array [ + Node { + "declarations": Array [ + Node { + "end": 449, + "id": Node { + "end": 19, + "loc": SourceLocation { + "end": Position { + "column": 19, + "line": 1, + }, + "identifierName": "__global_69fa48", + "start": Position { + "column": 4, + "line": 1, + }, + }, + "name": "__global_69fa48", + "start": 4, + "type": "Identifier", + }, + "init": Node { + "arguments": Array [ + Node { + "arguments": Array [], + "callee": Node { + "arguments": Array [ + Node { + "end": 445, + "extra": Object { + "raw": "\\"return this\\"", + "rawValue": "return this", + }, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 14, + }, + "start": Position { + "column": 16, + "line": 14, + }, + }, + "start": 432, + "type": "StringLiteral", + "value": "return this", + }, + ], + "callee": Node { + "end": 431, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 14, + }, + "identifierName": "Function", + "start": Position { + "column": 7, + "line": 14, + }, + }, + "name": "Function", + "start": 423, + "type": "Identifier", + }, + "end": 446, + "loc": SourceLocation { + "end": Position { + "column": 30, + "line": 14, + }, + "start": Position { + "column": 3, + "line": 14, + }, + }, + "start": 419, + "type": "NewExpression", + }, + "end": 448, + "loc": SourceLocation { + "end": Position { + "column": 32, + "line": 14, + }, + "start": Position { + "column": 3, + "line": 14, + }, + }, + "start": 419, + "type": "CallExpression", + }, + ], + "callee": Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "end": 104, + "expression": Node { + "end": 103, + "left": Node { + "computed": false, + "end": 60, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 2, + }, + "start": Position { + "column": 2, + "line": 2, + }, + }, + "object": Node { + "end": 39, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 2, + }, + "identifierName": "g", + "start": Position { + "column": 2, + "line": 2, + }, + }, + "name": "g", + "start": 38, + "type": "Identifier", + }, + "property": Node { + "end": 60, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 2, + }, + "identifierName": "__mutationCoverage__", + "start": Position { + "column": 4, + "line": 2, + }, + }, + "name": "__mutationCoverage__", + "start": 40, + "type": "Identifier", + }, + "start": 38, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 67, + "line": 2, + }, + "start": Position { + "column": 2, + "line": 2, + }, + }, + "operator": "=", + "right": Node { + "end": 103, + "left": Node { + "computed": false, + "end": 85, + "loc": SourceLocation { + "end": Position { + "column": 49, + "line": 2, + }, + "start": Position { + "column": 27, + "line": 2, + }, + }, + "object": Node { + "end": 64, + "loc": SourceLocation { + "end": Position { + "column": 28, + "line": 2, + }, + "identifierName": "g", + "start": Position { + "column": 27, + "line": 2, + }, + }, + "name": "g", + "start": 63, + "type": "Identifier", + }, + "property": Node { + "end": 85, + "loc": SourceLocation { + "end": Position { + "column": 49, + "line": 2, + }, + "identifierName": "__mutationCoverage__", + "start": Position { + "column": 29, + "line": 2, + }, + }, + "name": "__mutationCoverage__", + "start": 65, + "type": "Identifier", + }, + "start": 63, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 67, + "line": 2, + }, + "start": Position { + "column": 27, + "line": 2, + }, + }, + "operator": "||", + "right": Node { + "end": 103, + "loc": SourceLocation { + "end": Position { + "column": 67, + "line": 2, + }, + "start": Position { + "column": 53, + "line": 2, + }, + }, + "properties": Array [ + Node { + "computed": false, + "end": 101, + "key": Node { + "end": 97, + "loc": SourceLocation { + "end": Position { + "column": 61, + "line": 2, + }, + "identifierName": "static", + "start": Position { + "column": 55, + "line": 2, + }, + }, + "name": "static", + "start": 91, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 65, + "line": 2, + }, + "start": Position { + "column": 55, + "line": 2, + }, + }, + "method": false, + "shorthand": false, + "start": 91, + "type": "ObjectProperty", + "value": Node { + "end": 101, + "loc": SourceLocation { + "end": Position { + "column": 65, + "line": 2, + }, + "start": Position { + "column": 63, + "line": 2, + }, + }, + "properties": Array [], + "start": 99, + "type": "ObjectExpression", + }, + }, + ], + "start": 89, + "type": "ObjectExpression", + }, + "start": 63, + "type": "LogicalExpression", + }, + "start": 38, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 68, + "line": 2, + }, + "start": Position { + "column": 2, + "line": 2, + }, + }, + "start": 38, + "type": "ExpressionStatement", + }, + Node { + "end": 403, + "expression": Node { + "end": 402, + "left": Node { + "computed": false, + "end": 124, + "loc": SourceLocation { + "end": Position { + "column": 19, + "line": 3, + }, + "start": Position { + "column": 2, + "line": 3, + }, + }, + "object": Node { + "end": 108, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 3, + }, + "identifierName": "g", + "start": Position { + "column": 2, + "line": 3, + }, + }, + "name": "g", + "start": 107, + "type": "Identifier", + }, + "property": Node { + "end": 124, + "loc": SourceLocation { + "end": Position { + "column": 19, + "line": 3, + }, + "identifierName": "__coverMutant__", + "start": Position { + "column": 4, + "line": 3, + }, + }, + "name": "__coverMutant__", + "start": 109, + "type": "Identifier", + }, + "start": 107, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 12, + }, + "start": Position { + "column": 2, + "line": 3, + }, + }, + "operator": "=", + "right": Node { + "end": 402, + "left": Node { + "computed": false, + "end": 144, + "loc": SourceLocation { + "end": Position { + "column": 39, + "line": 3, + }, + "start": Position { + "column": 22, + "line": 3, + }, + }, + "object": Node { + "end": 128, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 3, + }, + "identifierName": "g", + "start": Position { + "column": 22, + "line": 3, + }, + }, + "name": "g", + "start": 127, + "type": "Identifier", + }, + "property": Node { + "end": 144, + "loc": SourceLocation { + "end": Position { + "column": 39, + "line": 3, + }, + "identifierName": "__coverMutant__", + "start": Position { + "column": 24, + "line": 3, + }, + }, + "name": "__coverMutant__", + "start": 129, + "type": "Identifier", + }, + "start": 127, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 12, + }, + "start": Position { + "column": 22, + "line": 3, + }, + }, + "operator": "||", + "right": Node { + "async": false, + "body": Node { + "body": Array [ + Node { + "declarations": Array [ + Node { + "end": 203, + "id": Node { + "end": 171, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 4, + }, + "identifierName": "c", + "start": Position { + "column": 8, + "line": 4, + }, + }, + "name": "c", + "start": 170, + "type": "Identifier", + }, + "init": Node { + "computed": false, + "end": 203, + "loc": SourceLocation { + "end": Position { + "column": 41, + "line": 4, + }, + "start": Position { + "column": 12, + "line": 4, + }, + }, + "object": Node { + "computed": false, + "end": 196, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 4, + }, + "start": Position { + "column": 12, + "line": 4, + }, + }, + "object": Node { + "end": 175, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 4, + }, + "identifierName": "g", + "start": Position { + "column": 12, + "line": 4, + }, + }, + "name": "g", + "start": 174, + "type": "Identifier", + }, + "property": Node { + "end": 196, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 4, + }, + "identifierName": "__mutationCoverage__", + "start": Position { + "column": 14, + "line": 4, + }, + }, + "name": "__mutationCoverage__", + "start": 176, + "type": "Identifier", + }, + "start": 174, + "type": "MemberExpression", + }, + "property": Node { + "end": 203, + "loc": SourceLocation { + "end": Position { + "column": 41, + "line": 4, + }, + "identifierName": "static", + "start": Position { + "column": 35, + "line": 4, + }, + }, + "name": "static", + "start": 197, + "type": "Identifier", + }, + "start": 174, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 41, + "line": 4, + }, + "start": Position { + "column": 8, + "line": 4, + }, + }, + "start": 170, + "type": "VariableDeclarator", + }, + ], + "end": 204, + "kind": "var", + "loc": SourceLocation { + "end": Position { + "column": 42, + "line": 4, + }, + "start": Position { + "column": 4, + "line": 4, + }, + }, + "start": 166, + "type": "VariableDeclaration", + }, + Node { + "alternate": null, + "consequent": Node { + "body": Array [ + Node { + "end": 290, + "expression": Node { + "end": 289, + "left": Node { + "end": 243, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 6, + }, + "identifierName": "c", + "start": Position { + "column": 6, + "line": 6, + }, + }, + "name": "c", + "start": 242, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 53, + "line": 6, + }, + "start": Position { + "column": 6, + "line": 6, + }, + }, + "operator": "=", + "right": Node { + "computed": true, + "end": 289, + "loc": SourceLocation { + "end": Position { + "column": 53, + "line": 6, + }, + "start": Position { + "column": 10, + "line": 6, + }, + }, + "object": Node { + "computed": false, + "end": 268, + "loc": SourceLocation { + "end": Position { + "column": 32, + "line": 6, + }, + "start": Position { + "column": 10, + "line": 6, + }, + }, + "object": Node { + "end": 247, + "loc": SourceLocation { + "end": Position { + "column": 11, + "line": 6, + }, + "identifierName": "g", + "start": Position { + "column": 10, + "line": 6, + }, + }, + "name": "g", + "start": 246, + "type": "Identifier", + }, + "property": Node { + "end": 268, + "loc": SourceLocation { + "end": Position { + "column": 32, + "line": 6, + }, + "identifierName": "__mutationCoverage__", + "start": Position { + "column": 12, + "line": 6, + }, + }, + "name": "__mutationCoverage__", + "start": 248, + "type": "Identifier", + }, + "start": 246, + "type": "MemberExpression", + }, + "property": Node { + "computed": false, + "end": 288, + "loc": SourceLocation { + "end": Position { + "column": 52, + "line": 6, + }, + "start": Position { + "column": 33, + "line": 6, + }, + }, + "object": Node { + "end": 270, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 6, + }, + "identifierName": "g", + "start": Position { + "column": 33, + "line": 6, + }, + }, + "name": "g", + "start": 269, + "type": "Identifier", + }, + "property": Node { + "end": 288, + "loc": SourceLocation { + "end": Position { + "column": 52, + "line": 6, + }, + "identifierName": "__currentTestId__", + "start": Position { + "column": 35, + "line": 6, + }, + }, + "name": "__currentTestId__", + "start": 271, + "type": "Identifier", + }, + "start": 269, + "type": "MemberExpression", + }, + "start": 246, + "type": "MemberExpression", + }, + "start": 242, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 54, + "line": 6, + }, + "start": Position { + "column": 6, + "line": 6, + }, + }, + "start": 242, + "type": "ExpressionStatement", + }, + ], + "directives": Array [], + "end": 296, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 7, + }, + "start": Position { + "column": 29, + "line": 5, + }, + }, + "start": 234, + "type": "BlockStatement", + }, + "end": 296, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 7, + }, + "start": Position { + "column": 4, + "line": 5, + }, + }, + "start": 209, + "test": Node { + "computed": false, + "end": 232, + "loc": SourceLocation { + "end": Position { + "column": 27, + "line": 5, + }, + "start": Position { + "column": 8, + "line": 5, + }, + }, + "object": Node { + "end": 214, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 5, + }, + "identifierName": "g", + "start": Position { + "column": 8, + "line": 5, + }, + }, + "name": "g", + "start": 213, + "type": "Identifier", + }, + "property": Node { + "end": 232, + "loc": SourceLocation { + "end": Position { + "column": 27, + "line": 5, + }, + "identifierName": "__currentTestId__", + "start": Position { + "column": 10, + "line": 5, + }, + }, + "name": "__currentTestId__", + "start": 215, + "type": "Identifier", + }, + "start": 213, + "type": "MemberExpression", + }, + "type": "IfStatement", + }, + Node { + "declarations": Array [ + Node { + "end": 318, + "id": Node { + "end": 306, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 8, + }, + "identifierName": "a", + "start": Position { + "column": 8, + "line": 8, + }, + }, + "name": "a", + "start": 305, + "type": "Identifier", + }, + "init": Node { + "end": 318, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 8, + }, + "identifierName": "arguments", + "start": Position { + "column": 12, + "line": 8, + }, + }, + "name": "arguments", + "start": 309, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 21, + "line": 8, + }, + "start": Position { + "column": 8, + "line": 8, + }, + }, + "start": 305, + "type": "VariableDeclarator", + }, + ], + "end": 319, + "kind": "var", + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 8, + }, + "start": Position { + "column": 4, + "line": 8, + }, + }, + "start": 301, + "type": "VariableDeclaration", + }, + Node { + "body": Node { + "body": Array [ + Node { + "end": 392, + "expression": Node { + "end": 391, + "left": Node { + "computed": true, + "end": 370, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 10, + }, + "start": Position { + "column": 6, + "line": 10, + }, + }, + "object": Node { + "end": 364, + "loc": SourceLocation { + "end": Position { + "column": 7, + "line": 10, + }, + "identifierName": "c", + "start": Position { + "column": 6, + "line": 10, + }, + }, + "name": "c", + "start": 363, + "type": "Identifier", + }, + "property": Node { + "computed": true, + "end": 369, + "loc": SourceLocation { + "end": Position { + "column": 12, + "line": 10, + }, + "start": Position { + "column": 8, + "line": 10, + }, + }, + "object": Node { + "end": 366, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 10, + }, + "identifierName": "a", + "start": Position { + "column": 8, + "line": 10, + }, + }, + "name": "a", + "start": 365, + "type": "Identifier", + }, + "property": Node { + "end": 368, + "loc": SourceLocation { + "end": Position { + "column": 11, + "line": 10, + }, + "identifierName": "i", + "start": Position { + "column": 10, + "line": 10, + }, + }, + "name": "i", + "start": 367, + "type": "Identifier", + }, + "start": 365, + "type": "MemberExpression", + }, + "start": 363, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 10, + }, + "start": Position { + "column": 6, + "line": 10, + }, + }, + "operator": "=", + "right": Node { + "end": 391, + "left": Node { + "end": 386, + "extra": Object { + "parenStart": 373, + "parenthesized": true, + }, + "left": Node { + "computed": true, + "end": 381, + "loc": SourceLocation { + "end": Position { + "column": 24, + "line": 10, + }, + "start": Position { + "column": 17, + "line": 10, + }, + }, + "object": Node { + "end": 375, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 10, + }, + "identifierName": "c", + "start": Position { + "column": 17, + "line": 10, + }, + }, + "name": "c", + "start": 374, + "type": "Identifier", + }, + "property": Node { + "computed": true, + "end": 380, + "loc": SourceLocation { + "end": Position { + "column": 23, + "line": 10, + }, + "start": Position { + "column": 19, + "line": 10, + }, + }, + "object": Node { + "end": 377, + "loc": SourceLocation { + "end": Position { + "column": 20, + "line": 10, + }, + "identifierName": "a", + "start": Position { + "column": 19, + "line": 10, + }, + }, + "name": "a", + "start": 376, + "type": "Identifier", + }, + "property": Node { + "end": 379, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 10, + }, + "identifierName": "i", + "start": Position { + "column": 21, + "line": 10, + }, + }, + "name": "i", + "start": 378, + "type": "Identifier", + }, + "start": 376, + "type": "MemberExpression", + }, + "start": 374, + "type": "MemberExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 10, + }, + "start": Position { + "column": 17, + "line": 10, + }, + }, + "operator": "||", + "right": Node { + "end": 386, + "extra": Object { + "raw": "0", + "rawValue": 0, + }, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 10, + }, + "start": Position { + "column": 28, + "line": 10, + }, + }, + "start": 385, + "type": "NumericLiteral", + "value": 0, + }, + "start": 374, + "type": "LogicalExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 10, + }, + "start": Position { + "column": 16, + "line": 10, + }, + }, + "operator": "+", + "right": Node { + "end": 391, + "extra": Object { + "raw": "1", + "rawValue": 1, + }, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 10, + }, + "start": Position { + "column": 33, + "line": 10, + }, + }, + "start": 390, + "type": "NumericLiteral", + "value": 1, + }, + "start": 373, + "type": "BinaryExpression", + }, + "start": 363, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 35, + "line": 10, + }, + "start": Position { + "column": 6, + "line": 10, + }, + }, + "start": 363, + "type": "ExpressionStatement", + }, + ], + "directives": Array [], + "end": 398, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 11, + }, + "start": Position { + "column": 35, + "line": 9, + }, + }, + "start": 355, + "type": "BlockStatement", + }, + "end": 398, + "init": Node { + "declarations": Array [ + Node { + "end": 335, + "id": Node { + "end": 333, + "loc": SourceLocation { + "end": Position { + "column": 13, + "line": 9, + }, + "identifierName": "i", + "start": Position { + "column": 12, + "line": 9, + }, + }, + "name": "i", + "start": 332, + "type": "Identifier", + }, + "init": Node { + "end": 335, + "extra": Object { + "raw": "0", + "rawValue": 0, + }, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 9, + }, + "start": Position { + "column": 14, + "line": 9, + }, + }, + "start": 334, + "type": "NumericLiteral", + "value": 0, + }, + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 9, + }, + "start": Position { + "column": 12, + "line": 9, + }, + }, + "start": 332, + "type": "VariableDeclarator", + }, + ], + "end": 335, + "kind": "var", + "loc": SourceLocation { + "end": Position { + "column": 15, + "line": 9, + }, + "start": Position { + "column": 8, + "line": 9, + }, + }, + "start": 328, + "type": "VariableDeclaration", + }, + "loc": SourceLocation { + "end": Position { + "column": 5, + "line": 11, + }, + "start": Position { + "column": 4, + "line": 9, + }, + }, + "start": 324, + "test": Node { + "end": 349, + "left": Node { + "end": 338, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 9, + }, + "identifierName": "i", + "start": Position { + "column": 17, + "line": 9, + }, + }, + "name": "i", + "start": 337, + "type": "Identifier", + }, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 9, + }, + "start": Position { + "column": 17, + "line": 9, + }, + }, + "operator": "<", + "right": Node { + "computed": false, + "end": 349, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 9, + }, + "start": Position { + "column": 21, + "line": 9, + }, + }, + "object": Node { + "end": 342, + "loc": SourceLocation { + "end": Position { + "column": 22, + "line": 9, + }, + "identifierName": "a", + "start": Position { + "column": 21, + "line": 9, + }, + }, + "name": "a", + "start": 341, + "type": "Identifier", + }, + "property": Node { + "end": 349, + "loc": SourceLocation { + "end": Position { + "column": 29, + "line": 9, + }, + "identifierName": "length", + "start": Position { + "column": 23, + "line": 9, + }, + }, + "name": "length", + "start": 343, + "type": "Identifier", + }, + "start": 341, + "type": "MemberExpression", + }, + "start": 337, + "type": "BinaryExpression", + }, + "type": "ForStatement", + "update": Node { + "argument": Node { + "end": 352, + "loc": SourceLocation { + "end": Position { + "column": 32, + "line": 9, + }, + "identifierName": "i", + "start": Position { + "column": 31, + "line": 9, + }, + }, + "name": "i", + "start": 351, + "type": "Identifier", + }, + "end": 354, + "loc": SourceLocation { + "end": Position { + "column": 34, + "line": 9, + }, + "start": Position { + "column": 31, + "line": 9, + }, + }, + "operator": "++", + "prefix": false, + "start": 351, + "type": "UpdateExpression", + }, + }, + ], + "directives": Array [], + "end": 402, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 12, + }, + "start": Position { + "column": 55, + "line": 3, + }, + }, + "start": 160, + "type": "BlockStatement", + }, + "end": 402, + "generator": false, + "id": null, + "loc": SourceLocation { + "end": Position { + "column": 3, + "line": 12, + }, + "start": Position { + "column": 43, + "line": 3, + }, + }, + "params": Array [], + "start": 148, + "type": "FunctionExpression", + }, + "start": 127, + "type": "LogicalExpression", + }, + "start": 107, + "type": "AssignmentExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 4, + "line": 12, + }, + "start": Position { + "column": 2, + "line": 3, + }, + }, + "start": 107, + "type": "ExpressionStatement", + }, + Node { + "argument": Node { + "end": 414, + "loc": SourceLocation { + "end": Position { + "column": 10, + "line": 13, + }, + "identifierName": "g", + "start": Position { + "column": 9, + "line": 13, + }, + }, + "name": "g", + "start": 413, + "type": "Identifier", + }, + "end": 415, + "loc": SourceLocation { + "end": Position { + "column": 11, + "line": 13, + }, + "start": Position { + "column": 2, + "line": 13, + }, + }, + "start": 406, + "type": "ReturnStatement", + }, + ], + "directives": Array [], + "end": 417, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 14, + }, + "start": Position { + "column": 34, + "line": 1, + }, + }, + "start": 34, + "type": "BlockStatement", + }, + "end": 417, + "extra": Object { + "parenStart": 22, + "parenthesized": true, + }, + "generator": false, + "id": null, + "loc": SourceLocation { + "end": Position { + "column": 1, + "line": 14, + }, + "start": Position { + "column": 23, + "line": 1, + }, + }, + "params": Array [ + Node { + "end": 33, + "loc": SourceLocation { + "end": Position { + "column": 33, + "line": 1, + }, + "identifierName": "g", + "start": Position { + "column": 32, + "line": 1, + }, + }, + "name": "g", + "start": 32, + "type": "Identifier", + }, + ], + "start": 23, + "type": "FunctionExpression", + }, + "end": 449, + "loc": SourceLocation { + "end": Position { + "column": 33, + "line": 14, + }, + "start": Position { + "column": 22, + "line": 1, + }, + }, + "start": 22, + "type": "CallExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 33, + "line": 14, + }, + "start": Position { + "column": 4, + "line": 1, + }, + }, + "start": 4, + "type": "VariableDeclarator", + }, + ], + "end": 449, + "kind": "var", + "loc": SourceLocation { + "end": Position { + "column": 33, + "line": 14, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "start": 0, + "type": "VariableDeclaration", + }, + Node { + "declarations": Array [ + Node { + "end": 18, + "id": Node { + "end": 9, + "loc": SourceLocation { + "end": Position { + "column": 9, + "line": 1, + }, + "identifierName": "foo", + "start": Position { + "column": 6, + "line": 1, + }, + }, + "name": "foo", + "start": 6, + "type": "Identifier", + }, + "init": Object { + "alternate": Object { + "expressions": Array [ + Object { + "arguments": Array [ + Object { + "type": "NumericLiteral", + "value": 0, + }, + ], + "callee": Object { + "computed": false, + "object": Object { + "name": "__global_69fa48", + "type": "Identifier", + }, + "optional": null, + "property": Object { + "name": "__coverMutant__", + "type": "Identifier", + }, + "type": "MemberExpression", + }, + "type": "CallExpression", + }, + Node { + "end": 18, + "innerComments": null, + "leadingComments": null, + "left": Node { + "end": 14, + "extra": Object { + "raw": "40", + "rawValue": 40, + }, + "loc": SourceLocation { + "end": Position { + "column": 14, + "line": 1, + }, + "start": Position { + "column": 12, + "line": 1, + }, + }, + "start": 12, + "type": "NumericLiteral", + "value": 40, + }, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 1, + }, + "start": Position { + "column": 12, + "line": 1, + }, + }, + "operator": "+", + "right": Node { + "end": 18, + "extra": Object { + "raw": "2", + "rawValue": 2, + }, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 1, + }, + "start": Position { + "column": 17, + "line": 1, + }, + }, + "start": 17, + "type": "NumericLiteral", + "value": 2, + }, + "start": 12, + "trailingComments": null, + "type": "BinaryExpression", + }, + ], + "innerComments": null, + "leadingComments": null, + "trailingComments": null, + "type": "SequenceExpression", + }, + "consequent": Object { + "end": 18, + "left": Node { + "end": 14, + "extra": Object { + "raw": "40", + "rawValue": 40, + }, + "loc": SourceLocation { + "end": Position { + "column": 14, + "line": 1, + }, + "start": Position { + "column": 12, + "line": 1, + }, + }, + "start": 12, + "type": "NumericLiteral", + "value": 40, + }, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 1, + }, + "start": Position { + "column": 12, + "line": 1, + }, + }, + "operator": "-", + "right": Node { + "end": 18, + "extra": Object { + "raw": "2", + "rawValue": 2, + }, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 1, + }, + "start": Position { + "column": 17, + "line": 1, + }, + }, + "start": 17, + "type": "NumericLiteral", + "value": 2, + }, + "start": 12, + "type": "BinaryExpression", + }, + "innerComments": Array [], + "leadingComments": Array [], + "test": Object { + "left": Object { + "computed": false, + "object": Object { + "name": "__global_69fa48", + "type": "Identifier", + }, + "optional": null, + "property": Object { + "name": "activeMutant", + "type": "Identifier", + }, + "type": "MemberExpression", + }, + "operator": "===", + "right": Object { + "type": "NumericLiteral", + "value": 0, + }, + "type": "BinaryExpression", + }, + "trailingComments": Array [], + "type": "ConditionalExpression", + }, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 1, + }, + "start": Position { + "column": 6, + "line": 1, + }, + }, + "start": 6, + "type": "VariableDeclarator", + }, + ], + "end": 18, + "kind": "const", + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 1, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "start": 0, + "type": "VariableDeclaration", + }, + ], + "directives": Array [], + "end": 18, + "interpreter": null, + "loc": SourceLocation { + "end": Position { + "column": 18, + "line": 1, + }, + "start": Position { + "column": 0, + "line": 1, + }, + }, + "sourceType": "module", + "start": 0, + "type": "Program", + }, + "start": 0, + "type": "File", + }, + }, + ], + }, +} +`; diff --git a/packages/instrumenter/test/integration/transformers.it.spec.ts b/packages/instrumenter/test/integration/transformers.it.spec.ts new file mode 100644 index 0000000000..ca67e85bfd --- /dev/null +++ b/packages/instrumenter/test/integration/transformers.it.spec.ts @@ -0,0 +1,30 @@ +import { expect } from 'chai'; + +import { createHtmlAst, createJSAst, createTransformerOptions, createTSAst } from '../helpers/factories'; +import { transform } from '../../src/transformers'; +import { MutantCollector } from '../../src/transformers/mutant-collector'; + +describe('transformers integration', () => { + it('should transform an html file', () => { + const htmlAst = createHtmlAst(); + htmlAst.root.scripts.push(createJSAst({ rawContent: 'const foo = 40 + 2' })); + const mutantCollector = new MutantCollector(); + transform(htmlAst, mutantCollector, { options: createTransformerOptions() }); + expect(mutantCollector.mutants).lengthOf(1); + expect(htmlAst).matchSnapshot(); + }); + it('should transform a js file', () => { + const jsAst = createJSAst({ rawContent: 'const foo = 40 + 2' }); + const mutantCollector = new MutantCollector(); + transform(jsAst, mutantCollector, { options: createTransformerOptions() }); + expect(mutantCollector.mutants).lengthOf(1); + expect(jsAst).matchSnapshot(); + }); + it('should transform a ts file', () => { + const tsAst = createTSAst({ rawContent: 'const foo: number = 40 + 2' }); + const mutantCollector = new MutantCollector(); + transform(tsAst, mutantCollector, { options: createTransformerOptions() }); + expect(mutantCollector.mutants).lengthOf(1); + expect(tsAst).matchSnapshot(); + }); +}); diff --git a/packages/instrumenter/test/setup.ts b/packages/instrumenter/test/setup.ts new file mode 100644 index 0000000000..77bd5cf4d9 --- /dev/null +++ b/packages/instrumenter/test/setup.ts @@ -0,0 +1,34 @@ +import 'source-map-support/register'; +import { sep } from 'path'; + +import chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import sinonChai from 'sinon-chai'; +import sinon from 'sinon'; +import { testInjector } from '@stryker-mutator/test-helpers'; +import chaiJestSnapshot from 'chai-jest-snapshot'; +import type { Context } from 'mocha'; + +chai.use(sinonChai); +chai.use(chaiAsPromised); +chai.use(chaiJestSnapshot); + +let originalCwd: string; + +export const mochaHooks = { + afterEach() { + sinon.restore(); + testInjector.reset(); + process.chdir(originalCwd); + }, + + before() { + chaiJestSnapshot.resetSnapshotRegistry(); + }, + + beforeEach(this: Context) { + originalCwd = process.cwd(); + chaiJestSnapshot.configureUsingMochaContext(this); + chaiJestSnapshot.setFilename(this.currentTest!.file!.replace(`${sep}dist`, '') + '.snap'); + }, +}; diff --git a/packages/instrumenter/test/tsconfig.json b/packages/instrumenter/test/tsconfig.json new file mode 100644 index 0000000000..c3f30c9d6a --- /dev/null +++ b/packages/instrumenter/test/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "../../../tsconfig.settings.json", + "compilerOptions": { + "outDir": "../dist/test", + "rootDir": ".", + "esModuleInterop": true, + "types": [ + "mocha", + "node" + ] + }, + "references": [ + { + "path": "../src" + }, + { + "path": "../../test-helpers/tsconfig.src.json" + } + ] +} diff --git a/packages/instrumenter/test/unit/disable-type-checks.spec.ts b/packages/instrumenter/test/unit/disable-type-checks.spec.ts new file mode 100644 index 0000000000..9396d1224a --- /dev/null +++ b/packages/instrumenter/test/unit/disable-type-checks.spec.ts @@ -0,0 +1,132 @@ +import { File } from '@stryker-mutator/api/core'; +import { assertions } from '@stryker-mutator/test-helpers'; +import sinon from 'sinon'; +import { expect } from 'chai'; + +import * as parsers from '../../src/parsers'; +import { disableTypeChecks } from '../../src'; + +describe(disableTypeChecks.name, () => { + describe('with TS or JS AST format', () => { + it('should prefix the file with `// @ts-nocheck`', async () => { + const inputFile = new File('foo.js', 'foo.bar();'); + const actual = await disableTypeChecks(inputFile, { plugins: null }); + assertions.expectTextFileEqual(actual, new File('foo.js', '// @ts-nocheck\nfoo.bar();')); + }); + + describe('with shebang (`#!/usr/bin/env node`)', () => { + it('should insert `// @ts-nocheck` after the new line', async () => { + const inputFile = new File('foo.js', '#!/usr/bin/env node\nfoo.bar();'); + const actual = await disableTypeChecks(inputFile, { plugins: null }); + assertions.expectTextFileEqual(actual, new File('foo.js', '#!/usr/bin/env node\n// @ts-nocheck\nfoo.bar();')); + }); + it('should not insert if there is no code', async () => { + const inputFile = new File('foo.js', '#!/usr/bin/env node'); + const actual = await disableTypeChecks(inputFile, { plugins: null }); + assertions.expectTextFileEqual(actual, new File('foo.js', '#!/usr/bin/env node')); + }); + }); + + it('should not even parse the file if "@ts-" can\'t be found anywhere in the file (performance optimization)', async () => { + const createParserSpy = sinon.spy(parsers, 'createParser'); + const inputFile = new File('foo.js', 'foo.bar();'); + await disableTypeChecks(inputFile, { plugins: null }); + expect(createParserSpy).not.called; + }); + + it('should remove @ts directives from a JS file', async () => { + const inputFile = new File('foo.js', '// @ts-check\nfoo.bar();'); + const actual = await disableTypeChecks(inputFile, { plugins: null }); + assertions.expectTextFileEqual(actual, new File('foo.js', '// @ts-nocheck\n// \nfoo.bar();')); + }); + + it('should remove @ts directives from a TS file', async () => { + const inputFile = new File('foo.ts', '// @ts-check\nfoo.bar();'); + const actual = await disableTypeChecks(inputFile, { plugins: null }); + assertions.expectTextFileEqual(actual, new File('foo.ts', '// @ts-nocheck\n// \nfoo.bar();')); + }); + + it('should remove @ts directive from single line', async () => { + await arrangeActAssert('// @ts-check\nfoo.bar();', '// \nfoo.bar();'); + }); + + it('should not remove @ts comments which occur later on the comment line (since then they are not considered a directive)', async () => { + await arrangeActAssert('// this should be ignored: @ts-expect-error\nfoo.bar();'); + }); + + it('should remove @ts directive from multiline', async () => { + await arrangeActAssert('/* @ts-expect-error */\nfoo.bar();', '/* */\nfoo.bar();'); + }); + + describe('with string', () => { + it('should not remove @ts directive in double quoted string', async () => { + await arrangeActAssert('foo.bar("/* @ts-expect-error */")'); + }); + + it('should not remove @ts directive in double quoted string after escaped double quote', async () => { + await arrangeActAssert('foo.bar("foo \\"/* @ts-expect-error */")'); + }); + + it('should remove @ts directive after a string', async () => { + await arrangeActAssert('foo.bar("foo \\" bar "/* @ts-expect-error */,\nbaz.qux())', 'foo.bar("foo \\" bar "/* */,\nbaz.qux())'); + }); + + it('should not remove @ts directive in single quoted string', async () => { + await arrangeActAssert("foo.bar('/* @ts-expect-error */')"); + }); + }); + + describe('with regex literals', () => { + it('should not remove @ts directive inside the regex', async () => { + await arrangeActAssert('const regex = / \\/*@ts-check */'); + }); + + it('should remove @ts directives just after a regex', async () => { + await arrangeActAssert('const regex = / \\/*@ts-check */// @ts-expect-error\nfoo.bar()', 'const regex = / \\/*@ts-check */// \nfoo.bar()'); + }); + + it('should allow escape sequence inside the regex', async () => { + await arrangeActAssert('const regex = / \\/ /; // @ts-expect-error', 'const regex = / \\/ /; // '); + }); + + it('should allow `/` inside a character class', async () => { + await arrangeActAssert('const regex = / [/] /; // @ts-check', 'const regex = / [/] /; // '); + }); + }); + + describe('with template strings', () => { + it('should not remove @ts directive inside the literal', async () => { + await arrangeActAssert('const foo = `/*@ts-check */`'); + }); + }); + + async function arrangeActAssert(input: string, expectedOutput = input) { + const inputFile = new File('foo.tsx', input); + const actual = await disableTypeChecks(inputFile, { plugins: null }); + assertions.expectTextFileEqual(actual, new File('foo.tsx', `// @ts-nocheck\n${expectedOutput}`)); + } + }); + + describe('with HTML ast format', () => { + it('should prefix the script tags with `// @ts-nocheck`', async () => { + const inputFile = new File('foo.vue', ''); + const actual = await disableTypeChecks(inputFile, { plugins: null }); + assertions.expectTextFileEqual(actual, new File('foo.vue', '')); + }); + + it('should remove `// @ts` directives from script tags', async () => { + const inputFile = new File('foo.html', ''); + const actual = await disableTypeChecks(inputFile, { plugins: null }); + assertions.expectTextFileEqual( + actual, + new File('foo.html', '') + ); + }); + + it('should not remove `// @ts` from the html itself', async () => { + const inputFile = new File('foo.vue', ''); + const actual = await disableTypeChecks(inputFile, { plugins: null }); + assertions.expectTextFileEqual(actual, new File('foo.vue', '')); + }); + }); +}); diff --git a/packages/instrumenter/test/unit/instrumenter.spec.ts b/packages/instrumenter/test/unit/instrumenter.spec.ts new file mode 100644 index 0000000000..1b622d4765 --- /dev/null +++ b/packages/instrumenter/test/unit/instrumenter.spec.ts @@ -0,0 +1,83 @@ +import { expect } from 'chai'; +import sinon from 'sinon'; +import { testInjector } from '@stryker-mutator/test-helpers'; +import { File } from '@stryker-mutator/api/core'; + +import { Instrumenter } from '../../src'; +import * as parsers from '../../src/parsers'; +import * as transformers from '../../src/transformers'; +import * as printers from '../../src/printers'; +import { createJSAst, createTSAst, createNamedNodeMutation, createInstrumenterOptions } from '../helpers/factories'; + +describe(Instrumenter.name, () => { + let sut: Instrumenter; + + class Helper { + public parserStub = sinon.stub(); + public createParserStub = sinon.stub(parsers, 'createParser').returns(this.parserStub); + public transformerStub = sinon.stub(transformers, 'transform'); + public printerStub = sinon.stub(printers, 'print'); + } + let helper: Helper; + + beforeEach(() => { + helper = new Helper(); + sut = testInjector.injector.injectClass(Instrumenter); + }); + + it('should parse, transform and print each file', async () => { + // Arrange + const { input, output } = arrangeTwoFiles(); + + // Act + const actualResult = await sut.instrument(input, createInstrumenterOptions()); + + // Assert + expect(actualResult.files).deep.eq([new File('foo.js', output[0]), new File('bar.ts', output[1])]); + }); + + it('should log about instrumenting', async () => { + await sut.instrument([new File('b.js', 'foo'), new File('a.js', 'bar')], createInstrumenterOptions()); + expect(testInjector.logger.debug).calledWith('Instrumenting %d source files with mutants', 2); + }); + + it('should log about the result', async () => { + helper.transformerStub.callsFake((_, collector: transformers.MutantCollector) => { + collector.add('foo.js', createNamedNodeMutation()); + }); + await sut.instrument([new File('b.js', 'foo'), new File('a.js', 'bar')], createInstrumenterOptions()); + expect(testInjector.logger.info).calledWith('Instrumented %d source file(s) with %d mutant(s)', 2, 2); + }); + + it('should log between each file', async () => { + // Arrange + testInjector.logger.isDebugEnabled.returns(true); + const { input, asts } = arrangeTwoFiles(); + const fakeTransform: typeof transformers.transform = (ast, collector) => { + if (ast === asts[0]) { + collector.add('foo.js', createNamedNodeMutation()); + } + if (ast === asts[1]) { + collector.add('foo.js', createNamedNodeMutation()); + collector.add('foo.js', createNamedNodeMutation()); + } + }; + helper.transformerStub.callsFake(fakeTransform); + + // Act + await sut.instrument(input, createInstrumenterOptions()); + + // Assert + expect(testInjector.logger.debug).calledWith('Instrumented foo.js (1 mutant(s))'); + expect(testInjector.logger.debug).calledWith('Instrumented bar.ts (2 mutant(s))'); + }); + + function arrangeTwoFiles() { + const input = [new File('foo.js', 'foo'), new File('bar.ts', 'bar')]; + const asts = [createJSAst(), createTSAst()]; + const output = ['instrumented js', 'instrumented ts']; + helper.parserStub.withArgs(input[0].textContent).resolves(asts[0]).withArgs(input[1].textContent).resolves(asts[1]); + helper.printerStub.withArgs(asts[0]).returns(output[0]).withArgs(asts[1]).returns(output[1]); + return { input, asts, output }; + } +}); diff --git a/packages/instrumenter/test/unit/mutant-placers/expression-mutant-placer.spec.ts b/packages/instrumenter/test/unit/mutant-placers/expression-mutant-placer.spec.ts new file mode 100644 index 0000000000..3322f445f3 --- /dev/null +++ b/packages/instrumenter/test/unit/mutant-placers/expression-mutant-placer.spec.ts @@ -0,0 +1,173 @@ +import { expect } from 'chai'; +import { types, NodePath } from '@babel/core'; +import { normalizeWhitespaces } from '@stryker-mutator/util'; +import generate from '@babel/generator'; + +import { expressionMutantPlacer } from '../../../src/mutant-placers/expression-mutant-placer'; +import { findNodePath, parseJS } from '../../helpers/syntax-test-helpers'; +import { Mutant } from '../../../src/mutant'; +import { createMutant } from '../../helpers/factories'; + +describe(expressionMutantPlacer.name, () => { + it('should have the correct name', () => { + expect(expressionMutantPlacer.name).eq('expressionMutantPlacer'); + }); + + it('should not place when the parent is tagged template expression', () => { + // A templateLiteral is considered an expression, while it is not save to place a mutant there! + const templateLiteral = findNodePath(parseJS('html`

`'), (p) => p.isTemplateLiteral()); + expect(expressionMutantPlacer(templateLiteral, [])).false; + }); + + function arrangeSingleMutant() { + const ast = parseJS('const foo = a + b'); + const binaryExpression = findNodePath(ast, (p) => p.isBinaryExpression()); + const mutant = new Mutant(1, 'file.js', { + original: binaryExpression.node, + replacement: types.binaryExpression('>>>', types.identifier('bar'), types.identifier('baz')), + mutatorName: 'fooMutator', + }); + return { binaryExpression, mutant, ast }; + } + + it('should be able to place a mutant on an expression', () => { + // Arrange + const { binaryExpression, mutant, ast } = arrangeSingleMutant(); + + // Act + const actual = expressionMutantPlacer(binaryExpression, [mutant]); + const actualCode = normalizeWhitespaces(generate(ast).code); + + // Assert + expect(actual).true; + expect(actualCode).contains('const foo = stryMutAct_9fa48(1) ? bar >>> baz'); + }); + + it('should place the original code as the alternative', () => { + const { binaryExpression, mutant, ast } = arrangeSingleMutant(); + expressionMutantPlacer(binaryExpression, [mutant]); + const actualAlternative = findNodePath(ast, (p) => p.isConditionalExpression()).node.alternate; + const actualAlternativeCode = generate(actualAlternative).code; + expect(actualAlternativeCode.endsWith('a + b'), `${actualAlternativeCode} did not end with "a + b"`).true; + }); + + it('should add mutant coverage syntax', () => { + const { binaryExpression, mutant, ast } = arrangeSingleMutant(); + expressionMutantPlacer(binaryExpression, [mutant]); + const actualAlternative = findNodePath(ast, (p) => p.isConditionalExpression()).node.alternate; + const actualAlternativeCode = generate(actualAlternative).code; + const expected = 'stryCov_9fa48(1), a + b'; + expect(actualAlternativeCode.startsWith(expected), `${actualAlternativeCode} did not start with "${expected}"`).true; + }); + + it('should be able to place multiple mutants', () => { + // Arrange + const ast = parseJS('const foo = a + b'); + const binaryExpression = findNodePath(ast, (p) => p.isBinaryExpression()); + const mutants = [ + createMutant({ + id: 52, + original: binaryExpression.node, + replacement: types.binaryExpression('-', types.identifier('bar'), types.identifier('baz')), + }), + createMutant({ + id: 659, + original: binaryExpression.node, + replacement: types.identifier('bar'), + }), + ]; + + // Act + expressionMutantPlacer(binaryExpression, mutants); + const actualCode = normalizeWhitespaces(generate(ast).code); + + // Assert + expect(actualCode).contains('const foo = stryMutAct_9fa48(659) ? bar : stryMutAct_9fa48(52) ? bar - baz'); + }); + + describe('object literals', () => { + it('should not place when the expression is a key', () => { + // A stringLiteral is considered an expression, while it is not save to place a mutant there! + const stringLiteral = findNodePath(parseJS("const foo = { 'foo': bar }"), (p) => p.isStringLiteral()); + expect(expressionMutantPlacer(stringLiteral, [])).false; + }); + + it('should place when the expression is the value', () => { + // A stringLiteral is considered an expression, while it is not save to place a mutant there! + const stringLiteral = findNodePath(parseJS("const foo = { 'foo': bar }"), (p) => p.isIdentifier() && p.node.name === 'bar'); + expect(expressionMutantPlacer(stringLiteral, [])).true; + }); + }); + + /** + * This describe has tests for anonymous classes and functions. + * @see https://github.com/stryker-mutator/stryker/issues/2362 + */ + describe('anonymous expressions', () => { + function arrangeActAssert(ast: types.File, expression: NodePath, expectedMatch: RegExp) { + const mutants = [ + createMutant({ + id: 4, + original: expression.node, + replacement: types.identifier('bar'), + }), + ]; + + // Act + expressionMutantPlacer(expression, mutants); + const actualCode = normalizeWhitespaces(generate(ast).code); + + // Assert + expect(actualCode).matches(expectedMatch); + } + + it('should set the name of an anonymous function expression', () => { + // Arrange + const ast = parseJS('const foo = function () { }'); + const functionExpression = findNodePath(ast, (p) => p.isFunctionExpression()); + arrangeActAssert(ast, functionExpression, /const foo =.*function foo\(\) {}/); + }); + + it('should set the name of an anonymous method expression', () => { + // Arrange + const ast = parseJS('const foo = { bar: function () { } }'); + const functionExpression = findNodePath(ast, (p) => p.isFunctionExpression()); + arrangeActAssert(ast, functionExpression, /const foo =.*bar:.*function bar\(\) {}/); + }); + + it('should not set the name if the statement is not a variable declaration', () => { + // Arrange + const ast = parseJS('foo.bar = function () { }'); + const functionExpression = findNodePath(ast, (p) => p.isFunctionExpression()); + arrangeActAssert(ast, functionExpression, /foo\.bar =.*function \(\) {}/); + }); + + it('should not set the name of a named function expression', () => { + // Arrange + const ast = parseJS('const foo = function bar () { }'); + const functionExpression = findNodePath(ast, (p) => p.isFunctionExpression()); + arrangeActAssert(ast, functionExpression, /const foo =.*function bar\(\) {}/); + }); + + it('should set the name of an anonymous class expression', () => { + // Arrange + const ast = parseJS('const Foo = class { }'); + const classExpression = findNodePath(ast, (p) => p.isClassExpression()); + arrangeActAssert(ast, classExpression, /const Foo =.*class Foo {}/); + }); + + it('should not override the name of a named class expression', () => { + // Arrange + const ast = parseJS('const Foo = class Bar { }'); + const classExpression = findNodePath(ast, (p) => p.isClassExpression()); + arrangeActAssert(ast, classExpression, /const Foo =.*class Bar {}/); + }); + + it('should set the name of an anonymous arrow function', () => { + // Arrange + const ast = parseJS('const bar = () => {}'); + const functionExpression = findNodePath(ast, (p) => p.isArrowFunctionExpression()); + arrangeActAssert(ast, functionExpression, /const bar =.*\(\(\) => { const bar = \(\) => {}; return bar; }\)\(\)/); + }); + }); +}); diff --git a/packages/instrumenter/test/unit/mutant-placers/index.spec.ts b/packages/instrumenter/test/unit/mutant-placers/index.spec.ts new file mode 100644 index 0000000000..7c98676d29 --- /dev/null +++ b/packages/instrumenter/test/unit/mutant-placers/index.spec.ts @@ -0,0 +1,57 @@ +import sinon from 'sinon'; +import { NodePath } from '@babel/core'; +import { expect } from 'chai'; + +import { placeMutants, MutantPlacer } from '../../../src/mutant-placers'; +import { findNodePath, parseJS } from '../../helpers/syntax-test-helpers'; +import { createMutant } from '../../helpers/factories'; + +describe(placeMutants.name, () => { + let mutantPlacers: Array>; + let path: NodePath; + + beforeEach(() => { + mutantPlacers = [sinon.stub(), sinon.stub()]; + path = findNodePath(parseJS('f = 0'), (p) => p.isProgram()); + }); + + it('should not place mutants when the mutant array is empty', () => { + const actual = placeMutants(path, [], 'foo.js', mutantPlacers); + expect(actual).false; + expect(mutantPlacers[0]).not.called; + expect(mutantPlacers[1]).not.called; + }); + + it('should stop placing mutants if the first mutant placer could place it', () => { + mutantPlacers[0].returns(true); + const mutants = [createMutant()]; + const actual = placeMutants(path, mutants, 'foo.js', mutantPlacers); + expect(actual).true; + expect(mutantPlacers[0]).calledWith(path, mutants); + expect(mutantPlacers[1]).not.called; + }); + + it('should return false if mutants could not be placed', () => { + mutantPlacers[0].returns(false); + mutantPlacers[1].returns(false); + const mutants = [createMutant()]; + const actual = placeMutants(path, mutants, 'foo.js', mutantPlacers); + expect(actual).false; + expect(mutantPlacers[0]).calledWith(path, mutants); + expect(mutantPlacers[1]).calledWith(path, mutants); + }); + + it('should throw an error if mutant placing gave a error', () => { + const expectedError = new Error('expectedError'); + const fooPlacer: MutantPlacer = () => { + throw expectedError; + }; + path.node.loc = { start: { column: 3, line: 2 }, end: { column: 5, line: 4 } }; + mutantPlacers[0].throws(expectedError); + const mutants = [createMutant()]; + expect(() => placeMutants(path, mutants, 'foo.js', [fooPlacer])).throws( + SyntaxError, + 'foo.js:2:3 fooPlacer could not place mutants with type(s): "fooMutator". Either remove this file from the list of files to be mutated, or ignore the mutators. Please report this issue at https://github.com/stryker-mutator/stryker/issues/new' + ); + }); +}); diff --git a/packages/instrumenter/test/unit/mutant-placers/statement-mutant-placer.spec.ts b/packages/instrumenter/test/unit/mutant-placers/statement-mutant-placer.spec.ts new file mode 100644 index 0000000000..af90c1b02c --- /dev/null +++ b/packages/instrumenter/test/unit/mutant-placers/statement-mutant-placer.spec.ts @@ -0,0 +1,117 @@ +import { expect } from 'chai'; +import { types } from '@babel/core'; +import generate from '@babel/generator'; +import { normalizeWhitespaces } from '@stryker-mutator/util'; + +import { statementMutantPlacer } from '../../../src/mutant-placers/statement-mutant-placer'; +import { findNodePath, parseJS } from '../../helpers/syntax-test-helpers'; +import { Mutant } from '../../../src/mutant'; +import { createMutant } from '../../helpers/factories'; + +describe(statementMutantPlacer.name, () => { + it('should have the correct name', () => { + expect(statementMutantPlacer.name).eq('statementMutantPlacer'); + }); + + it("shouldn't place mutants on anything but a statement", () => { + [ + findNodePath(parseJS('foo + bar'), (p) => p.isBinaryExpression()), + findNodePath(parseJS('foo = bar'), (p) => p.isAssignmentExpression()), + findNodePath(parseJS('foo.bar()'), (p) => p.isCallExpression()), + ].forEach((node) => { + expect(statementMutantPlacer(node, [])).false; + }); + }); + + function arrangeSingleMutant() { + const ast = parseJS('const foo = a + b'); + const statement = findNodePath(ast, (p) => p.isVariableDeclaration()); + const nodeToMutate = findNodePath(ast, (p) => p.isBinaryExpression()); + const mutant = new Mutant(1, 'file.js', { + original: nodeToMutate.node, + replacement: types.binaryExpression('>>>', types.identifier('bar'), types.identifier('baz')), + mutatorName: 'fooMutator', + }); + return { statement, mutant, ast }; + } + + it('should be able to place a mutant in a statement', () => { + // Arrange + const { statement, mutant, ast } = arrangeSingleMutant(); + + // Act + const actual = statementMutantPlacer(statement, [mutant]); + const actualCode = normalizeWhitespaces(generate(ast).code); + + // Assert + expect(actual).true; + expect(actualCode).contains(normalizeWhitespaces('if (stryMutAct_9fa48(1)) { const foo = bar >>> baz; } else ')); + }); + + it('should keep block statements in tact', () => { + // Arrange + const ast = parseJS('function add(a, b) { return a + b; }'); + const statement = findNodePath(ast, (p) => p.isBlockStatement()); + const originalNodePath = findNodePath(ast, (p) => p.isBinaryExpression()); + const mutant = createMutant({ + original: originalNodePath.node, + replacement: types.binaryExpression('>>>', types.identifier('a'), types.identifier('b')), + }); + + // Act + const actual = statementMutantPlacer(statement, [mutant]); + const actualCode = normalizeWhitespaces(generate(ast).code); + + // Assert + expect(actual).true; + expect(actualCode).matches(/function\s*add\s*\(a,\s*b\)\s*{.*}/); + }); + + it('should place the original code as alternative (inside `else`)', () => { + const { ast, mutant, statement } = arrangeSingleMutant(); + statementMutantPlacer(statement, [mutant]); + const actualCode = normalizeWhitespaces(generate(ast).code); + expect(actualCode).matches(/else\s*{.*const foo = a \+ b;\s*\}/); + }); + + it('should add mutant coverage syntax', () => { + const { ast, mutant, statement } = arrangeSingleMutant(); + statementMutantPlacer(statement, [mutant]); + const actualCode = normalizeWhitespaces(generate(ast).code); + expect(actualCode).matches(/else\s*{\s*stryCov_9fa48\(1\)/); + }); + + it('should be able to place multiple mutants', () => { + // Arrange + const ast = parseJS('const foo = a + b'); + const statement = findNodePath(ast, (p) => p.isVariableDeclaration()); + const binaryExpression = findNodePath(ast, (p) => p.isBinaryExpression()); + const fooIdentifier = findNodePath(ast, (p) => p.isIdentifier()); + const mutants = [ + new Mutant(52, 'file.js', { + original: binaryExpression.node, + replacement: types.binaryExpression('>>>', types.identifier('bar'), types.identifier('baz')), + mutatorName: 'fooMutator', + }), + new Mutant(659, 'file.js', { + original: fooIdentifier.node, + replacement: types.identifier('bar'), + mutatorName: 'fooMutator', + }), + ]; + + // Act + statementMutantPlacer(statement, mutants); + const actualCode = normalizeWhitespaces(generate(ast).code); + + // Assert + expect(actualCode).contains( + normalizeWhitespaces(`if (stryMutAct_9fa48(659)) { + const bar = a + b; + } else if (stryMutAct_9fa48(52)) { + const foo = bar >>> baz; + } else { + stryCov_9fa48(52, 659)`) + ); + }); +}); diff --git a/packages/instrumenter/test/unit/mutant-placers/switch-case-mutant-placer.spec.ts b/packages/instrumenter/test/unit/mutant-placers/switch-case-mutant-placer.spec.ts new file mode 100644 index 0000000000..013d88ef60 --- /dev/null +++ b/packages/instrumenter/test/unit/mutant-placers/switch-case-mutant-placer.spec.ts @@ -0,0 +1,103 @@ +import { NodePath, types } from '@babel/core'; +import generate from '@babel/generator'; +import { normalizeWhitespaces } from '@stryker-mutator/util'; +import { expect } from 'chai'; + +import { switchCaseMutantPlacer as sut } from '../../../src/mutant-placers/switch-case-mutant-placer'; +import { createMutant } from '../../helpers/factories'; +import { findNodePath, parseJS } from '../../helpers/syntax-test-helpers'; + +describe(sut.name, () => { + it('should have the correct name', () => { + expect(sut.name).eq('switchCaseMutantPlacer'); + }); + + it('should not place mutants on non-switch-case nodes', () => { + [ + findNodePath(parseJS('foo + bar'), (p) => p.isBinaryExpression()), + findNodePath(parseJS('switch(foo) { }'), (p) => p.isSwitchStatement()), + ].forEach((node) => { + expect(sut(node, [])).false; + }); + }); + + it('should only place SwitchCase nodes', () => { + const switchCase = findNodePath(parseJS('switch(foo) { case "bar": console.log("bar"); break; }'), (p) => p.isSwitchCase()); + const mutant = createMutant({ original: switchCase.node, replacement: types.stringLiteral('foo') }); + expect(() => sut(switchCase, [mutant])).throws('switchCaseMutantPlacer can only place SwitchCase syntax'); + }); + + describe('given a SwitchCase node', () => { + let ast: types.File; + let switchCase: NodePath; + + beforeEach(() => { + ast = parseJS('switch(foo) { case "bar": console.log("bar"); break; }'); + switchCase = findNodePath(ast, (p) => p.isSwitchCase()); + }); + + it('should place a mutant in the "consequent" part of a switch-case', () => { + // Arrange + const mutant = createMutant({ id: 42, original: switchCase.node, replacement: types.switchCase(types.stringLiteral('bar'), []) }); + + // Act + const actual = sut(switchCase, [mutant]); + const actualCode = normalizeWhitespaces(generate(ast).code); + + // Assert + expect(actual).true; + expect(actualCode).contains(normalizeWhitespaces('switch (foo) { case "bar": if (stryMutAct_9fa48(42))')); + }); + + it('should place the original code as alternative (inside `else`)', () => { + // Arrange + const mutant = createMutant({ id: 42, original: switchCase.node, replacement: types.switchCase(types.stringLiteral('bar'), []) }); + + // Act + const actual = sut(switchCase, [mutant]); + const actualCode = normalizeWhitespaces(generate(ast).code); + + // Assert + expect(actual).true; + expect(actualCode).matches(/else {.* console\.log\("bar"\); break; }/); + }); + + it('should add mutant coverage syntax', () => { + // Arrange + const mutant = createMutant({ id: 42, original: switchCase.node, replacement: types.switchCase(types.stringLiteral('bar'), []) }); + + // Act + const actual = sut(switchCase, [mutant]); + const actualCode = normalizeWhitespaces(generate(ast).code); + + // Assert + expect(actual).true; + expect(actualCode).matches(/else\s*{\s*stryCov_9fa48\(42\)/); + }); + + it('should be able to place multiple mutants', () => { + // Arrange + const mutants = [ + createMutant({ id: 42, original: switchCase.node, replacement: types.switchCase(types.stringLiteral('bar'), []) }), + createMutant({ + id: 156, + original: switchCase.node, + replacement: types.switchCase(types.stringLiteral('bar'), [types.expressionStatement(types.callExpression(types.identifier('foo'), []))]), + }), + ]; + + // Act + sut(switchCase, mutants); + const actualCode = normalizeWhitespaces(generate(ast).code); + + // Assert + expect(actualCode).contains( + normalizeWhitespaces(`if (stryMutAct_9fa48(156)) { + foo(); + } else if (stryMutAct_9fa48(42)) {} + else { + stryCov_9fa48(42, 156)`) + ); + }); + }); +}); diff --git a/packages/instrumenter/test/unit/mutant.spec.ts b/packages/instrumenter/test/unit/mutant.spec.ts new file mode 100644 index 0000000000..08756bac0b --- /dev/null +++ b/packages/instrumenter/test/unit/mutant.spec.ts @@ -0,0 +1,61 @@ +import { types } from '@babel/core'; + +import { Mutant as MutantApi } from '@stryker-mutator/api/core'; + +import { expect } from 'chai'; + +import { Mutant } from '../../src/mutant'; +import { parseJS, findNodePath } from '../helpers/syntax-test-helpers'; + +describe(Mutant.name, () => { + describe('constructor', () => { + it('should print the replacement code (so it cannot change later)', () => { + // Since babel ASTs are mutable, and we ARE mutating the ast, the code will change. + // We need to make sure that we print the mutated code before that can happen. + // Arrange + const original = types.binaryExpression('+', types.numericLiteral(40), types.numericLiteral(2)); + const replacement = types.binaryExpression('-', types.numericLiteral(40), types.numericLiteral(2)); + const mutant = new Mutant(2, 'file.js', { original, replacement, mutatorName: 'fooMutator' }); + + // Act + replacement.operator = '%'; + + // Assert + expect(mutant.replacementCode).eq('40 - 2'); + }); + }); + + describe(Mutant.prototype.toApiMutant.name, () => { + it('should map all properties as expected', () => { + const mutant = new Mutant(2, 'file.js', { + original: types.stringLiteral(''), + replacement: types.stringLiteral('Stryker was here!'), + mutatorName: 'fooMutator', + ignoreReason: 'ignore', + }); + mutant.original.loc = { start: { column: 0, line: 0 }, end: { column: 0, line: 0 } }; + const expected: Partial = { + fileName: 'file.js', + id: 2, + mutatorName: 'fooMutator', + replacement: '"Stryker was here!"', + ignoreReason: 'ignore', + }; + expect(mutant.toApiMutant()).deep.include(expected); + }); + + it('should offset location correctly', () => { + // Arrange + const lt = findNodePath(parseJS('if(a < b) { console.log("hello world"); }'), (p) => p.isBinaryExpression()).node; + const lte = types.binaryExpression('<=', lt.left, lt.right); + const mutant = new Mutant(1, 'bar.js', { original: lt, replacement: lte, mutatorName: 'barMutator' }); + + // Act + const actual = mutant.toApiMutant(); + + // Assert + expect(actual.location).deep.eq({ start: { line: 0, column: 3 }, end: { line: 0, column: 8 } }); + expect(actual.range).deep.eq([3, 8]); + }); + }); +}); diff --git a/packages/instrumenter/test/unit/mutators/arithmatic-operator-mutator.spec.ts b/packages/instrumenter/test/unit/mutators/arithmatic-operator-mutator.spec.ts new file mode 100644 index 0000000000..da30176a11 --- /dev/null +++ b/packages/instrumenter/test/unit/mutators/arithmatic-operator-mutator.spec.ts @@ -0,0 +1,26 @@ +import { expect } from 'chai'; + +import { ArithmeticOperatorMutator } from '../../../src/mutators/arithmetic-operator-mutator'; +import { expectJSMutation } from '../../helpers/expect-mutation'; + +describe(ArithmeticOperatorMutator.name, () => { + let sut: ArithmeticOperatorMutator; + beforeEach(() => { + sut = new ArithmeticOperatorMutator(); + }); + + it('should have name "ArithmeticOperator"', () => { + expect(sut.name).eq('ArithmeticOperator'); + }); + + it('should mutate + and -', () => { + expectJSMutation(sut, 'a + b', 'a - b'); + expectJSMutation(sut, 'a - b', 'a + b'); + }); + + it('should mutate *, % and /', () => { + expectJSMutation(sut, 'a * b', 'a / b'); + expectJSMutation(sut, 'a / b', 'a * b'); + expectJSMutation(sut, 'a % b', 'a * b'); + }); +}); diff --git a/packages/instrumenter/test/unit/mutators/array-declaration-mutator.spec.ts b/packages/instrumenter/test/unit/mutators/array-declaration-mutator.spec.ts new file mode 100644 index 0000000000..c6bd1a29c7 --- /dev/null +++ b/packages/instrumenter/test/unit/mutators/array-declaration-mutator.spec.ts @@ -0,0 +1,46 @@ +import { expect } from 'chai'; + +import { ArrayDeclarationMutator } from '../../../src/mutators/array-declaration-mutator'; +import { expectJSMutation } from '../../helpers/expect-mutation'; + +describe(ArrayDeclarationMutator.name, () => { + let sut: ArrayDeclarationMutator; + beforeEach(() => { + sut = new ArrayDeclarationMutator(); + }); + + it('should have name "ArrayDeclaration"', () => { + expect(sut.name).eq('ArrayDeclaration'); + }); + + it('should mutate filled array literals as empty arrays', () => { + expectJSMutation(sut, '[a, 1 + 1]', '[]'); + expectJSMutation(sut, "['val']", '[]'); + }); + + it('should mutate empty array literals as a filled array', () => { + expectJSMutation(sut, '[]', '["Stryker was here"]'); + }); + + it('should mutate filled Array constructor calls as empty arrays', () => { + expectJSMutation(sut, 'new Array(a, 1 + 1)', 'new Array()'); + expectJSMutation(sut, "new Array('val')", 'new Array()'); + expectJSMutation(sut, "Array('val')", 'Array()'); + expectJSMutation(sut, 'Array(a, 1 + 1)', 'Array()'); + }); + + it('should not mutate other new expressions', () => { + expectJSMutation(sut, 'new Object(21, 2)'); + expectJSMutation(sut, 'new Arrays(21, 2)'); + }); + + it('should mutate empty array constructor call as a filled array', () => { + expectJSMutation(sut, 'new Array()', 'new Array([])'); + expectJSMutation(sut, 'Array()', 'Array([])'); + }); + + it('should not mutate other function call expressions', () => { + expectJSMutation(sut, 'window.Array(21, 2)'); + expectJSMutation(sut, 'window["Array"](21, 2)'); + }); +}); diff --git a/packages/instrumenter/test/unit/mutators/arrow-function-mutator.spec.ts b/packages/instrumenter/test/unit/mutators/arrow-function-mutator.spec.ts new file mode 100644 index 0000000000..ab6faa6702 --- /dev/null +++ b/packages/instrumenter/test/unit/mutators/arrow-function-mutator.spec.ts @@ -0,0 +1,27 @@ +import { expect } from 'chai'; + +import { ArrowFunctionMutator } from '../../../src/mutators/arrow-function-mutator'; +import { expectJSMutation } from '../../helpers/expect-mutation'; + +describe(ArrowFunctionMutator.name, () => { + let sut: ArrowFunctionMutator; + beforeEach(() => { + sut = new ArrowFunctionMutator(); + }); + + it('should have name "ArrowFunction"', () => { + expect(sut.name).eq('ArrowFunction'); + }); + + it('should mutate an anonymous function with an inline return', () => { + expectJSMutation(sut, 'const b = () => 4;', 'const b = () => undefined;'); + }); + + it('should not mutate an anonymous function with a block as a body', () => { + expectJSMutation(sut, 'const b = () => { return 4; }'); + }); + + it('should not mutate an anonymous function with undefined as a body', () => { + expectJSMutation(sut, 'const b = () => undefined'); + }); +}); diff --git a/packages/instrumenter/test/unit/mutators/block-statement-mutator.spec.ts b/packages/instrumenter/test/unit/mutators/block-statement-mutator.spec.ts new file mode 100644 index 0000000000..874011770e --- /dev/null +++ b/packages/instrumenter/test/unit/mutators/block-statement-mutator.spec.ts @@ -0,0 +1,79 @@ +import { expect } from 'chai'; + +import { BlockStatementMutator } from '../../../src/mutators/block-statement-mutator'; +import { expectJSMutation } from '../../helpers/expect-mutation'; + +describe(BlockStatementMutator.name, () => { + let sut: BlockStatementMutator; + beforeEach(() => { + sut = new BlockStatementMutator(); + }); + + it('should have name "BlockStatement"', () => { + expect(sut.name).eq('BlockStatement'); + }); + + describe('blocks', () => { + it('should mutate a single block', () => { + expectJSMutation(sut, 'const a = 3; { const b = a; }', 'const a = 3; {}'); + }); + + it('should not mutate an object declaration, as not a block', () => { + expectJSMutation(sut, 'const o = { foo: "bar" }'); + }); + }); + + describe('functions', () => { + it('should mutate the block of a function into an empty block', () => { + expectJSMutation(sut, '(function() { return 4; })', '(function() {})'); + }); + it('should not mutate an already empty block', () => { + expectJSMutation(sut, '(function() { })'); + }); + it('should mutate the body of an anonymous function if defined as a block', () => { + expectJSMutation(sut, 'const b = () => { return 4; }', 'const b = () => {}'); + }); + + it('should not mutate the body of an anonymous function if not defined as a block', () => { + expectJSMutation(sut, 'const b = () => 4;'); + }); + }); + + describe('switch/case', () => { + it('should not mutate the body of a switch or case statement, as not a block', () => { + expectJSMutation(sut, 'switch (v) { case 42: a = "spam"; break; }'); + }); + + it('should mutate the body of a case statement if defined as a block', () => { + expectJSMutation(sut, 'switch (v) { case 42: { a = "spam"; break; } }', 'switch (v) { case 42: {} }'); + }); + }); + + describe('classes', () => { + it('should mutate a constructor', () => { + expectJSMutation(sut, 'class Foo { constructor() { bar(); } }', 'class Foo { constructor() {} }'); + }); + + it('should mutate a constructor with (typescript) parameter properties', () => { + expectJSMutation(sut, 'class Foo { constructor(private baz: string) { bar(); } }', 'class Foo { constructor(private baz: string) {} }'); + }); + + it('should mutate a constructor with a super call', () => { + expectJSMutation(sut, 'class Foo extends Bar { constructor(baz) { super(baz); } }', 'class Foo extends Bar { constructor(baz) {} }'); + }); + + /** + * @see https://github.com/stryker-mutator/stryker/issues/2314 + */ + it('should not mutate a constructor containing a super call and has (typescript) parameter properties', () => { + expectJSMutation(sut, 'class Foo extends Bar { constructor(private baz: string) { super(); } }'); + }); + + /** + * @see https://github.com/stryker-mutator/stryker/issues/2474 + */ + it('should not mutate a constructor containing a super call and contains initialized properties', () => { + expectJSMutation(sut, 'class Foo extends Bar { private baz = "qux"; constructor() { super(); } }'); + }); + }); +}); diff --git a/packages/instrumenter/test/unit/mutators/boolean-literal-mutator.spec.ts b/packages/instrumenter/test/unit/mutators/boolean-literal-mutator.spec.ts new file mode 100644 index 0000000000..65f2ab14ba --- /dev/null +++ b/packages/instrumenter/test/unit/mutators/boolean-literal-mutator.spec.ts @@ -0,0 +1,27 @@ +import { expect } from 'chai'; + +import { BooleanLiteralMutator } from '../../../src/mutators/boolean-literal-mutator'; +import { expectJSMutation } from '../../helpers/expect-mutation'; + +describe(BooleanLiteralMutator.name, () => { + let sut: BooleanLiteralMutator; + beforeEach(() => { + sut = new BooleanLiteralMutator(); + }); + + it('should have name "BooleanLiteral"', () => { + expect(sut.name).eq('BooleanLiteral'); + }); + + it('should mutate `true` into `false`', () => { + expectJSMutation(sut, 'true', 'false'); + }); + + it('should mutate `false` into `true`', () => { + expectJSMutation(sut, 'false', 'true'); + }); + + it('should mutate !a to a', () => { + expectJSMutation(sut, '!a', 'a'); + }); +}); diff --git a/packages/instrumenter/test/unit/mutators/conditional-expression-mutator.spec.ts b/packages/instrumenter/test/unit/mutators/conditional-expression-mutator.spec.ts new file mode 100644 index 0000000000..ac5314094f --- /dev/null +++ b/packages/instrumenter/test/unit/mutators/conditional-expression-mutator.spec.ts @@ -0,0 +1,104 @@ +import { expect } from 'chai'; + +import { expectJSMutation } from '../../helpers/expect-mutation'; +import { ConditionalExpressionMutator } from '../../../src/mutators/conditional-expression-mutator'; + +describe(ConditionalExpressionMutator.name, () => { + let sut: ConditionalExpressionMutator; + beforeEach(() => { + sut = new ConditionalExpressionMutator(); + }); + + it('should have name "ConditionalExpression"', () => { + expect(sut.name).eq('ConditionalExpression'); + }); + + it('should mutate ternary operator', () => { + expectJSMutation(sut, 'a < 3? b : c', 'false? b : c', 'true? b : c'); + }); + + it('should mutate < and >', () => { + expectJSMutation(sut, 'a < b', 'true', 'false'); + expectJSMutation(sut, 'a > b', 'true', 'false'); + }); + + it('should mutate <= and >=', () => { + expectJSMutation(sut, 'a <= b', 'true', 'false'); + expectJSMutation(sut, 'a >= b', 'true', 'false'); + }); + + it('should mutate == and ===', () => { + expectJSMutation(sut, 'a == b', 'true', 'false'); + expectJSMutation(sut, 'a === b', 'true', 'false'); + }); + + it('should mutate != and !==', () => { + expectJSMutation(sut, 'a != b', 'true', 'false'); + expectJSMutation(sut, 'a !== b', 'true', 'false'); + }); + + it('should mutate && and ||', () => { + expectJSMutation(sut, 'a && b', 'true', 'false'); + expectJSMutation(sut, 'a || b', 'true', 'false'); + }); + + it('should not mutate + and -', () => { + expectJSMutation(sut, 'a + b'); + expectJSMutation(sut, 'a - b'); + }); + + it('should not mutate *, % and /', () => { + expectJSMutation(sut, 'a * b'); + expectJSMutation(sut, 'a / b'); + expectJSMutation(sut, 'a % b'); + }); + + it('should not mutate assignments', () => { + expectJSMutation(sut, 'let displayName; displayName = "Label";'); + }); + + it('should mutate the expression of a do statement', () => { + expectJSMutation(sut, 'do { console.log(); } while(a < b);', 'do { console.log(); } while(false);'); + }); + + it('should mutate the condition of a for statement', () => { + expectJSMutation(sut, 'for(let i=0;i<10; i++) { console.log(); }', 'for(let i=0;false; i++) { console.log(); }'); + }); + + it('should mutate the condition of a for statement without a condition', () => { + expectJSMutation( + sut, + 'for(let i=0;; i++) { console.log(); }', + `for (let i = 0; false; i++) { + console.log(); +}` + ); + }); + + it('should mutate an expression to `true` and `false`', () => { + expectJSMutation(sut, 'if (something) { a++ }', 'if (true) { a++ }', 'if (false) { a++ }'); + }); + + it('should remove all cases one at a time', () => { + expectJSMutation( + sut, + 'switch (v) {case 0: a = "foo"; case 1: a = "qux"; break; default: a = "spam";}', + 'switch (v) {case 0: case 1: a = "qux"; break; default: a = "spam";}', + 'switch (v) {case 0: a = "foo"; case 1: default: a = "spam";}', + 'switch (v) {case 0: a = "foo"; case 1: a = "qux"; break; default:}' + ); + }); + + it('should not mutate empty cases (0 consequent statements)', () => { + expectJSMutation( + sut, + 'switch (v) {case 0: case 1: break; default: a = "spam";}', + 'switch (v) {case 0: case 1: default: a = "spam";}', + 'switch (v) {case 0: case 1: break; default:}' + ); + }); + + it('should mutate the expression of a while statement', () => { + expectJSMutation(sut, 'while(a < b) { console.log(); }', 'while(false) { console.log(); }'); + }); +}); diff --git a/packages/instrumenter/test/unit/mutators/equality-operator-mutator.spec.ts b/packages/instrumenter/test/unit/mutators/equality-operator-mutator.spec.ts new file mode 100644 index 0000000000..b5079a5d5c --- /dev/null +++ b/packages/instrumenter/test/unit/mutators/equality-operator-mutator.spec.ts @@ -0,0 +1,35 @@ +import { expect } from 'chai'; + +import { EqualityOperatorMutator } from '../../../src/mutators/equality-operator-mutator'; +import { expectJSMutation } from '../../helpers/expect-mutation'; + +describe(EqualityOperatorMutator.name, () => { + let sut: EqualityOperatorMutator; + beforeEach(() => { + sut = new EqualityOperatorMutator(); + }); + + it('should have name "EqualityOperator"', () => { + expect(sut.name).eq('EqualityOperator'); + }); + + it('should mutate < and >', () => { + expectJSMutation(sut, 'a < b', 'a >= b', 'a <= b'); + expectJSMutation(sut, 'a > b', 'a <= b', 'a >= b'); + }); + + it('should mutate <= and >=', () => { + expectJSMutation(sut, 'a <= b', 'a < b', 'a > b'); + expectJSMutation(sut, 'a >= b', 'a < b', 'a > b'); + }); + + it('should mutate == and ===', () => { + expectJSMutation(sut, 'a == b', 'a != b'); + expectJSMutation(sut, 'a === b', 'a !== b'); + }); + + it('should mutate != and !==', () => { + expectJSMutation(sut, 'a != b', 'a == b'); + expectJSMutation(sut, 'a !== b', 'a === b'); + }); +}); diff --git a/packages/instrumenter/test/unit/mutators/logical-operator-mutator.spec.ts b/packages/instrumenter/test/unit/mutators/logical-operator-mutator.spec.ts new file mode 100644 index 0000000000..149332f7ac --- /dev/null +++ b/packages/instrumenter/test/unit/mutators/logical-operator-mutator.spec.ts @@ -0,0 +1,20 @@ +import { expect } from 'chai'; + +import { LogicalOperatorMutator } from '../../../src/mutators/logical-operator-mutator'; +import { expectJSMutation } from '../../helpers/expect-mutation'; + +describe(LogicalOperatorMutator.name, () => { + let sut: LogicalOperatorMutator; + beforeEach(() => { + sut = new LogicalOperatorMutator(); + }); + + it('should have name "LogicalOperator"', () => { + expect(sut.name).eq('LogicalOperator'); + }); + + it('should mutate && and ||', () => { + expectJSMutation(sut, 'a && b', 'a || b'); + expectJSMutation(sut, 'a || b', 'a && b'); + }); +}); diff --git a/packages/instrumenter/test/unit/mutators/object-literal-mutator.spec.ts b/packages/instrumenter/test/unit/mutators/object-literal-mutator.spec.ts new file mode 100644 index 0000000000..52545e7dcc --- /dev/null +++ b/packages/instrumenter/test/unit/mutators/object-literal-mutator.spec.ts @@ -0,0 +1,31 @@ +import { expect } from 'chai'; + +import { ObjectLiteralMutator } from '../../../src/mutators/object-literal-mutator'; +import { expectJSMutation } from '../../helpers/expect-mutation'; + +describe(ObjectLiteralMutator.name, () => { + let sut: ObjectLiteralMutator; + beforeEach(() => { + sut = new ObjectLiteralMutator(); + }); + + it('should have name "ObjectLiteral"', () => { + expect(sut.name).eq('ObjectLiteral'); + }); + + it('should empty an object declaration', () => { + expectJSMutation(sut, 'const o = { foo: "bar" }', 'const o = {}'); + }); + + it('should empty an object declaration of all properties', () => { + expectJSMutation(sut, 'const o = { foo: "bar", baz: "qux" }', 'const o = {}'); + }); + + it('should empty string object keys', () => { + expectJSMutation(sut, 'const o = { ["foo"]: "bar" }', 'const o = {}'); + }); + + it('shoud not mutate empty object declarations', () => { + expectJSMutation(sut, 'const o = {}'); + }); +}); diff --git a/packages/instrumenter/test/unit/mutators/string-literal-mutator.spec.ts b/packages/instrumenter/test/unit/mutators/string-literal-mutator.spec.ts new file mode 100644 index 0000000000..51d1d538ff --- /dev/null +++ b/packages/instrumenter/test/unit/mutators/string-literal-mutator.spec.ts @@ -0,0 +1,97 @@ +import { expect } from 'chai'; + +import { expectJSMutation } from '../../helpers/expect-mutation'; +import { StringLiteralMutator } from '../../../src/mutators/string-literal-mutator'; + +describe(StringLiteralMutator.name, () => { + let sut: StringLiteralMutator; + beforeEach(() => { + sut = new StringLiteralMutator(); + }); + + it('should have name "StringLiteral"', () => { + expect(sut.name).eq('StringLiteral'); + }); + + describe('string literals', () => { + it('should mutate a string literal with double quotes', () => { + expectJSMutation(sut, 'const b = "Hello world!";', 'const b = "";'); + }); + + it('should mutate a string literal with single quotes', () => { + expectJSMutation(sut, "const b = 'Hello world!';", 'const b = "";'); + }); + + it('should mutate a template string', () => { + expectJSMutation(sut, 'const b = `Hello world!`;', 'const b = ``;'); + }); + + it('should mutate a template string referencing another variable', () => { + expectJSMutation(sut, 'const a = 10; const b = `${a} mutations`;', 'const a = 10; const b = ``;'); + expectJSMutation(sut, 'const a = 10; const b = `mutations: ${a}`;', 'const a = 10; const b = ``;'); + expectJSMutation(sut, 'const a = 10; const b = `mutations: ${a} out of 10`;', 'const a = 10; const b = ``;'); + }); + + it('should mutate empty strings', () => { + expectJSMutation(sut, 'const b = "";', 'const b = "Stryker was here!";'); + }); + + it('should mutate empty template strings', () => { + expectJSMutation(sut, 'const b = ``;', 'const b = `Stryker was here!`;'); + }); + + it('should not mutate directive prologues', () => { + expectJSMutation(sut, '"use strict";"use asm";'); + expectJSMutation(sut, 'function a() {"use strict";"use asm";}'); + }); + }); + + describe('imports/exports', () => { + it('should not mutate import statements', () => { + expectJSMutation(sut, 'import * as foo from "foo";'); + expectJSMutation(sut, 'import { foo } from "foo";'); + expectJSMutation(sut, 'import foo from "foo";'); + expectJSMutation(sut, 'import "foo";'); + }); + + it('should not mutate require call statements', () => { + expectJSMutation(sut, 'require("./lib/square");'); + }); + + it('should mutate other call statements', () => { + expectJSMutation(sut, 'require2("./lib/square");', 'require2("");'); + }); + + it('should not mutate export statements', () => { + expectJSMutation(sut, 'export * from "./foo";'); + expectJSMutation(sut, 'export { foo as boo } from "./foo";'); + }); + }); + + describe('type declarations', () => { + it('should not mutate type declarations', () => { + expectJSMutation(sut, 'const a: "hello" = "hello";', 'const a: "hello" = "";'); + expectJSMutation(sut, 'const a: Record<"id", number> = { id: 10 }'); + }); + + // interfaces itself are skipped entirely by the babel-transformer + }); + + describe('object properties', () => { + it('should not mutate inside object property keys', () => { + expectJSMutation(sut, 'const { className, "aria-label": label } = props;'); + }); + it('should not mutate inside object property keys', () => { + expectJSMutation(sut, 'const foo = { className, ["aria-label"]: label };'); + }); + it('should still mutate inside object property values', () => { + expectJSMutation(sut, 'const foo = { bar: "baz" };', 'const foo = { bar: "" };'); + }); + }); + + describe('jsx', () => { + it('should not mutate string JSX attributes', () => { + expectJSMutation(sut, ''); + }); + }); +}); diff --git a/packages/instrumenter/test/unit/mutators/unary-operator-mutator.spec.ts b/packages/instrumenter/test/unit/mutators/unary-operator-mutator.spec.ts new file mode 100644 index 0000000000..222a77b121 --- /dev/null +++ b/packages/instrumenter/test/unit/mutators/unary-operator-mutator.spec.ts @@ -0,0 +1,35 @@ +import { expect } from 'chai'; + +import { UnaryOperatorMutator } from '../../../src/mutators/unary-operator-mutator'; +import { expectJSMutation } from '../../helpers/expect-mutation'; + +describe(UnaryOperatorMutator.name, () => { + let sut: UnaryOperatorMutator; + beforeEach(() => { + sut = new UnaryOperatorMutator(); + }); + + it('should have name "UnaryOperator"', () => { + expect(sut.name).eq('UnaryOperator'); + }); + + it('should mutate -a to +a', () => { + expectJSMutation(sut, '-a', '+a'); + }); + + it('should mutate +a to -a', () => { + expectJSMutation(sut, '+a', '-a'); + }); + + it('should mutate ~a to a', () => { + expectJSMutation(sut, '~a', 'a'); + }); + + it('should not mutate a+a', () => { + expectJSMutation(sut, 'a+a'); + }); + + it('should not mutate a-a', () => { + expectJSMutation(sut, 'a-a'); + }); +}); diff --git a/packages/instrumenter/test/unit/mutators/update-operator-mutator.spec.ts b/packages/instrumenter/test/unit/mutators/update-operator-mutator.spec.ts new file mode 100644 index 0000000000..6ab9f6a833 --- /dev/null +++ b/packages/instrumenter/test/unit/mutators/update-operator-mutator.spec.ts @@ -0,0 +1,31 @@ +import { expect } from 'chai'; + +import { UpdateOperatorMutator } from '../../../src/mutators/update-operator-mutator'; +import { expectJSMutation } from '../../helpers/expect-mutation'; + +describe(UpdateOperatorMutator.name, () => { + let sut: UpdateOperatorMutator; + beforeEach(() => { + sut = new UpdateOperatorMutator(); + }); + + it('should have name "UpdateOperator"', () => { + expect(sut.name).eq('UpdateOperator'); + }); + + it('should mutate a++ to a--', () => { + expectJSMutation(sut, 'a++', 'a--'); + }); + + it('should mutate a-- to a++', () => { + expectJSMutation(sut, 'a--', 'a++'); + }); + + it('should mutate ++a to --a', () => { + expectJSMutation(sut, '++a', '--a'); + }); + + it('should mutate --a to ++a', () => { + expectJSMutation(sut, '--a', '++a'); + }); +}); diff --git a/packages/instrumenter/test/unit/parsers/html-parser.spec.ts b/packages/instrumenter/test/unit/parsers/html-parser.spec.ts new file mode 100644 index 0000000000..1884bd0718 --- /dev/null +++ b/packages/instrumenter/test/unit/parsers/html-parser.spec.ts @@ -0,0 +1,168 @@ +import { expect } from 'chai'; + +import sinon = require('sinon'); + +import { parse } from '../../../src/parsers/html-parser'; +import { ParserContext } from '../../../src/parsers/parser-context'; +import { parserContextStub } from '../../helpers/stubs'; +import { createJSAst } from '../../helpers/factories'; +import { AstFormat } from '../../../src/syntax'; +import { ParseError } from '../../../src/parsers/parse-error'; + +describe('html-parser', () => { + let contextStub: sinon.SinonStubbedInstance; + + beforeEach(() => { + contextStub = parserContextStub(); + }); + + describe('parsing', () => { + const simpleHtml = ` + + + + Title of the document + + + + The content of the document...... + + + + `; + + it('should be able to parse simple HTML', async () => { + const parsed = await parse(simpleHtml, 'index.html', contextStub); + expect(parsed).ok; + }); + + it('should work without script tags', async () => { + const parsed = await parse(simpleHtml, 'index.html', contextStub); + expect(parsed.root.scripts).lengthOf(0); + }); + + it('should throw an error on invalid HTML', async () => { + await expect(parse('

', 'index.html', contextStub)).rejectedWith( + ParseError, + 'Parse error in index.html (1:3) Unexpected closing tag "div".' + ); + }); + }); + + describe('html with one script tag', () => { + const scriptContent = ` + console.log('hello world'); + `; + const html = ` + + The content of the document...... + + + `; + + it('should deliver one script', async () => { + const parsed = await parse(html, 'index.html', contextStub); + expect(parsed.root.scripts).lengthOf(1); + }); + + it('should offset the location in the script', async () => { + // Arrange + const actualScriptAst = createJSAst({ rawContent: scriptContent }); + contextStub.parse.resolves(actualScriptAst); + + // Act + const parsed = await parse(html, 'index.html', contextStub); + + // Assert + expect(parsed.root.scripts[0].root.loc).deep.eq({ + start: { line: 5, column: 12 }, + end: { line: 7, column: 4 }, + }); + expect(parsed.root.scripts[0].root.start).eq(74); + expect(parsed.root.scripts[0].root.end).eq(111); + }); + }); + + describe('script parsing', () => { + const testCases = [ + { actualType: 'javascript', expectedType: AstFormat.JS }, + { actualType: 'JavaScript', expectedType: AstFormat.JS }, + { actualType: 'text/javascript', expectedType: AstFormat.JS }, + { actualType: 'js', expectedType: AstFormat.JS }, + { actualType: 'ts', expectedType: AstFormat.TS }, + { actualType: 'typescript', expectedType: AstFormat.TS }, + { actualType: 'TypeScript', expectedType: AstFormat.TS }, + { actualType: 'text/typescript', expectedType: AstFormat.TS }, + ]; + + testCases.forEach(({ actualType, expectedType }) => { + it(`should parse `, 'test.html', contextStub); + expect(contextStub.parse).calledWith(code, 'test.html', expectedType); + }); + it(`should parse `, 'test.html', contextStub); + expect(contextStub.parse).calledWith(code, 'test.html', expectedType); + }); + }); + + it('should parse `, 'test.html', contextStub); + expect(contextStub.parse).calledWith(code, 'test.html', AstFormat.JS); + }); + it('shouldn\'t parse scripts with a "src" attribute', async () => { + await parse('', 'test.html', contextStub); + expect(contextStub.parse).not.called; + }); + + it('should support script tags deep in html', async () => { + await parse('

', 'test.html', contextStub); + expect(contextStub.parse).called; + }); + + it('should support script tags with more attributes', async () => { + await parse('', 'test.html', contextStub); + expect(contextStub.parse).calledWith('', 'test.html', AstFormat.TS); + }); + + it('should ignore unknown script types', async () => { + const parsed = await parse('', 'test.html', contextStub); + expect(parsed.root.scripts).lengthOf(0); + }); + + it('should support multiple script tags', async () => { + // Arrange + const script1 = 'foo.bar()'; + const script2 = 'baz.qux()'; + const script3 = 'quux.forge()'; + const html = ` + + + + + + + `; + const expectedAsts = [createJSAst({ rawContent: script1 }), createJSAst({ rawContent: script2 }), createJSAst({ rawContent: script3 })]; + contextStub.parse + .withArgs(script1) + .resolves(expectedAsts[0]) + .withArgs(script2) + .resolves(expectedAsts[1]) + .withArgs(script3) + .resolves(expectedAsts[2]); + + // Act + const { + root: { scripts }, + } = await parse(html, 'test.html', contextStub); + + // Assert + expect(contextStub.parse).calledThrice; + expect(scripts).deep.eq(expectedAsts); + }); + }); +}); diff --git a/packages/instrumenter/test/unit/parsers/js-parser.spec.ts b/packages/instrumenter/test/unit/parsers/js-parser.spec.ts new file mode 100644 index 0000000000..f2391f4632 --- /dev/null +++ b/packages/instrumenter/test/unit/parsers/js-parser.spec.ts @@ -0,0 +1,95 @@ +import { expect } from 'chai'; + +import { createParser } from '../../../src/parsers/js-parser'; +import { JSAst, AstFormat } from '../../../src/syntax'; +import { expectAst, AstExpectation } from '../../helpers/syntax-test-helpers'; +import { createParserOptions } from '../../helpers/factories'; + +describe('js-parser', () => { + it('should be able to parse simple es5', async () => { + const expected: Omit = { + format: AstFormat.JS, + originFileName: 'foo.js', + rawContent: 'var foo = "bar"', + }; + const { format, originFileName, root, rawContent } = await createParser(createParserOptions())(expected.rawContent, expected.originFileName); + expect(format).eq(expected.format); + expect(rawContent).eq(expected.rawContent); + expect(originFileName).eq(expected.originFileName); + expectAst(root, (p) => p.isDeclaration()); + }); + + describe('default plugins', () => { + describe('with features', () => { + const itShouldSupportAst = createActArrangeAndAssertHelper((name) => `https://babeljs.io/docs/en/babel-plugin-syntax-${name}`); + itShouldSupportAst('async-generators', 'async function* agf() { await 1;}', (t) => t.isFunctionDeclaration() && t.node.generator); + itShouldSupportAst('dynamic-import', 'import("fs").then(console.log)', (t) => t.isImport()); + itShouldSupportAst('import-meta', 'console.log(import.meta);', (t) => t.isMetaProperty()); + itShouldSupportAst('big-int', 'const theBiggestInt = 9007199254740991n', (t) => t.isBigIntLiteral()); + itShouldSupportAst('logical-assignment-operators', 'a &&= b;', (t) => t.isAssignmentExpression() && t.node.operator === '&&='); + }); + + describe('with experimental features', () => { + // See https://babeljs.io/docs/en/plugins + const itShouldSupportAst = createActArrangeAndAssertHelper((name) => `https://babeljs.io/docs/en/babel-plugin-proposal-${name}`); + + itShouldSupportAst('do-expressions', 'let a = do { if(x > 10) { "big"; } else { "small"; } }', (t) => t.isDoExpression()); + itShouldSupportAst('object-rest-spread', 'let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };', (t) => t.isRestElement()); + itShouldSupportAst('class-properties', 'class Foo { bar = "baz" }', (t) => t.isClassProperty()); + itShouldSupportAst('class-properties (private properties)', 'class Foo { #bar = "baz" }', (t) => t.isClassPrivateProperty()); + itShouldSupportAst('class-properties (private methods)', 'class Foo { #bar(){ return "baz"; } }', (t) => t.isClassPrivateMethod()); + + itShouldSupportAst('export-default-from', 'export v from "mod";', (t) => t.isExportNamedDeclaration()); + itShouldSupportAst('export-namespace-from', 'export * as ns from "mod";', (t) => t.isExportNamespaceSpecifier()); + itShouldSupportAst('function-bind', 'obj::func', (t) => t.isBindExpression()); + itShouldSupportAst('function-sent', 'function* generator() { console.log("Sent", function.sent); console.log("Yield", yield);}', (t) => + t.isMetaProperty() + ); + itShouldSupportAst('numeric-separator', 'let budget = 1_000_000_000_000;', (t) => t.isNumericLiteral()); + itShouldSupportAst('optional-catch-binding', 'try{ throw 0; } catch { }', (t) => t.isCatchClause() && t.node.param === null); + itShouldSupportAst('optional-chaining', 'const baz = obj?.foo?.bar?.baz;', (t) => t.isOptionalMemberExpression()); + itShouldSupportAst('pipeline-operator', 'let result = "hello" |> doubleSay |> capitalize |> exclaim;', (t) => t.isBinaryExpression()); + itShouldSupportAst( + 'nullish-coalescing-operator', + 'var foo = object.foo ?? "default";', + (t) => t.isLogicalExpression() && t.node.operator === '??' + ); + itShouldSupportAst( + 'throw-expressions', + 'const test = param === true || throw new Error("Falsy!");', + (t) => t.isUnaryExpression() && t.node.operator === 'throw' + ); + + // @ts-expect-error not (yet) defined in the types + itShouldSupportAst('partial-application', 'const addOne = add(1, ?);', (t) => t.isArgumentPlaceholder()); + itShouldSupportAst('decorators', '@annotation class MyClass { }', (t) => t.isDecorator()); + }); + + describe('language extensions (https://babeljs.io/docs/en/babel-parser#language-extensions)', () => { + it('should support v8intrinsic', async () => { + const { root } = await createParser(createParserOptions())('%DebugPrint(foo);', 'test.js'); + // @ts-expect-error not (yet) defined in the types + expectAst(root, (t) => t.isV8IntrinsicIdentifier()); + }); + }); + function createActArrangeAndAssertHelper(makeUrl: (name: string) => string) { + return (babelProposalName: string, input: string, expectation: AstExpectation, only = false) => { + (only ? it.only : it)(`should support "${babelProposalName}" (${makeUrl(babelProposalName)})`, async () => { + const { root } = await createParser(createParserOptions())(input, 'test.js'); + expectAst(root, expectation); + }); + }; + } + }); + + describe('override plugins', () => { + it('should allow to override with empty plugins', async () => { + const parse = createParser(createParserOptions({ plugins: [] })); + await expect(parse('let result = "hello" |> doubleSay;', 'file.js')).rejected; + }); + it('should allow to force one plugin', async () => { + const parse = createParser(createParserOptions({ plugins: ['exportDefaultFrom'] })); + await expect(parse('export default from "./"', 'file.js')).not.rejected; + }); + }); +}); diff --git a/packages/instrumenter/test/unit/parsers/ts-parser.spec.ts b/packages/instrumenter/test/unit/parsers/ts-parser.spec.ts new file mode 100644 index 0000000000..35b4406c5f --- /dev/null +++ b/packages/instrumenter/test/unit/parsers/ts-parser.spec.ts @@ -0,0 +1,43 @@ +import { expect } from 'chai'; + +import { TSAst, AstFormat } from '../../../src/syntax'; +import { parse } from '../../../src/parsers/ts-parser'; +import { expectAst, AstExpectation } from '../../helpers/syntax-test-helpers'; + +describe('ts-parser', () => { + it('should be able to parse simple typescript', async () => { + const expected: Omit = { + format: AstFormat.TS, + originFileName: 'foo.ts', + rawContent: 'var foo: string = "bar";', + }; + const { format, originFileName, root, rawContent } = await parse(expected.rawContent, expected.originFileName); + expect(format).eq(expected.format); + expect(rawContent).eq(expected.rawContent); + expect(originFileName).eq(expected.originFileName); + expectAst(root, (p) => p.isTSTypeAnnotation()); + }); + + it('should allow for experimentalDecorators', async () => { + await arrangeAndAssert("@Component({ selector: 'auto-complete'}) class A {}", (t) => t.isDecorator()); + }); + + it('should allow jsx if extension is tsx', async () => { + await arrangeAndAssert( + `class MyComponent extends React.Component { + render() { + return {this.props.foo} + } + } + + ; // ok`, + (t) => t.isJSXElement(), + 'test.tsx' + ); + }); + + async function arrangeAndAssert(input: string, expectation: AstExpectation, fileName = 'test.ts') { + const { root } = await parse(input, fileName); + expectAst(root, expectation); + } +}); diff --git a/packages/instrumenter/test/unit/printers/html-printer.spec.ts b/packages/instrumenter/test/unit/printers/html-printer.spec.ts new file mode 100644 index 0000000000..62acaae5d3 --- /dev/null +++ b/packages/instrumenter/test/unit/printers/html-printer.spec.ts @@ -0,0 +1,86 @@ +import { expect } from 'chai'; +import sinon from 'sinon'; + +import { createHtmlAst, createJSAst } from '../../helpers/factories'; +import { print } from '../../../src/printers/html-printer'; +import { PrinterContext } from '../../../src/printers'; +import { printerContextStub } from '../../helpers/stubs'; +import { offsetLocations } from '../../../src/util/syntax-helpers'; + +describe('html-printer', () => { + let contextStub: sinon.SinonStubbedInstance; + + beforeEach(() => { + contextStub = printerContextStub(); + }); + + it('should output original file if no scripts are found', () => { + const expectedHtml = 'Title'; + const ast = createHtmlAst({ rawContent: expectedHtml }); + const output = print(ast, contextStub); + expect(output).eq(expectedHtml); + }); + + it('should replace a single script', () => { + // Arrange + const expectedScriptContent = 'foo = bar;'; + const jsScript = createJSAst({ + rawContent: expectedScriptContent, + }); + contextStub.print.returns(expectedScriptContent); + offsetLocations(jsScript.root, { column: 13, line: 1, position: 14 }); + const actualHtml = ''; + const expectedHtml = /'; + const expectedOutput = /'; + const expectedOutput = / + + + \ No newline at end of file diff --git a/packages/instrumenter/testResources/disable-type-checks/html-sample.html.out.snap b/packages/instrumenter/testResources/disable-type-checks/html-sample.html.out.snap new file mode 100644 index 0000000000..f4eb2c49a9 --- /dev/null +++ b/packages/instrumenter/testResources/disable-type-checks/html-sample.html.out.snap @@ -0,0 +1,53 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`disableTypeChecks integration should be able disable type checking of an html file 1`] = ` +" + + + + + + Document + + + + + + +" +`; + +exports[`disableTypeChecks integration should be able disable type checks of an html file 1`] = ` +" + + + + + + Document + + + + + + +" +`; diff --git a/packages/instrumenter/testResources/disable-type-checks/vue-sample.vue b/packages/instrumenter/testResources/disable-type-checks/vue-sample.vue new file mode 100644 index 0000000000..04293cd27a --- /dev/null +++ b/packages/instrumenter/testResources/disable-type-checks/vue-sample.vue @@ -0,0 +1,118 @@ + + + + + + + diff --git a/packages/instrumenter/testResources/disable-type-checks/vue-sample.vue.out.snap b/packages/instrumenter/testResources/disable-type-checks/vue-sample.vue.out.snap new file mode 100644 index 0000000000..96213eaf66 --- /dev/null +++ b/packages/instrumenter/testResources/disable-type-checks/vue-sample.vue.out.snap @@ -0,0 +1,129 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`disableTypeChecks integration should be able disable type checks of a vue file 1`] = ` +" + + + + + + +" +`; diff --git a/packages/instrumenter/testResources/instrumenter/app.component.ts b/packages/instrumenter/testResources/instrumenter/app.component.ts new file mode 100644 index 0000000000..720ba19362 --- /dev/null +++ b/packages/instrumenter/testResources/instrumenter/app.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.scss'] +}) +export class AppComponent { + title = 'angular-app'; +} diff --git a/packages/instrumenter/testResources/instrumenter/app.component.ts.out.snap b/packages/instrumenter/testResources/instrumenter/app.component.ts.out.snap new file mode 100644 index 0000000000..dd3e7e79b5 --- /dev/null +++ b/packages/instrumenter/testResources/instrumenter/app.component.ts.out.snap @@ -0,0 +1,67 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`instrumenter integration should be able to instrument an angular component 1`] = ` +"function stryNS_9fa48() { + var g = new Function(\\"return this\\")(); + var ns = g.__stryker__ || (g.__stryker__ = {}); + + if (ns.activeMutant === undefined && g.process && g.process.env && g.process.env.__STRYKER_ACTIVE_MUTANT__) { + ns.activeMutant = Number(g.process.env.__STRYKER_ACTIVE_MUTANT__); + } + + function retrieveNS() { + return ns; + } + + stryNS_9fa48 = retrieveNS; + return retrieveNS(); +} + +stryNS_9fa48(); + +function stryCov_9fa48() { + var ns = stryNS_9fa48(); + var cov = ns.mutantCoverage || (ns.mutantCoverage = { + static: {}, + perTest: {} + }); + + function cover() { + var c = cov.static; + + if (ns.currentTestId) { + c = cov.perTest[ns.currentTestId] = cov.perTest[ns.currentTestId] || {}; + } + + var a = arguments; + + for (var i = 0; i < a.length; i++) { + c[a[i]] = (c[a[i]] || 0) + 1; + } + } + + stryCov_9fa48 = cover; + cover.apply(null, arguments); +} + +function stryMutAct_9fa48(id) { + var ns = stryNS_9fa48(); + + function isActive(id) { + return ns.activeMutant === id; + } + + stryMutAct_9fa48 = isActive; + return isActive(id); +} + +import { Component } from '@angular/core'; +@Component({ + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.scss'] +}) +export class AppComponent { + title = stryMutAct_9fa48(0) ? \\"\\" : (stryCov_9fa48(0), 'angular-app'); +}" +`; diff --git a/packages/instrumenter/testResources/instrumenter/flow-typed.js b/packages/instrumenter/testResources/instrumenter/flow-typed.js new file mode 100644 index 0000000000..9f9e989f94 --- /dev/null +++ b/packages/instrumenter/testResources/instrumenter/flow-typed.js @@ -0,0 +1,23 @@ +declare module 'react-test-renderer' { + // eslint-disable-next-line no-inner-declarations +} +declare type ReactTestRenderer = { + toJSON(): null | ReactTestRendererJSON, + toTree(): null | ReactTestRendererTree, + unmount(nextElement?: React$Element): void, + update(nextElement: React$Element): void, + getInstance(): ?ReactComponentInstance, + root: ReactTestInstance, +}; + +declare type Thenable = { + then(resolve: () => mixed, reject?: () => mixed): mixed, +}; + +declare function create( + nextElement: React$Element, + options?: TestRendererOptions +): ReactTestRenderer; + +declare function act(callback: () => ?Thenable): Thenable; + diff --git a/packages/instrumenter/testResources/instrumenter/flow-typed.js.out.snap b/packages/instrumenter/testResources/instrumenter/flow-typed.js.out.snap new file mode 100644 index 0000000000..2f951e58bc --- /dev/null +++ b/packages/instrumenter/testResources/instrumenter/flow-typed.js.out.snap @@ -0,0 +1,19 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`instrumenter integration type declarations should not produce mutants for flow-types 1`] = ` +"declare module 'react-test-renderer' {// eslint-disable-next-line no-inner-declarations +} +declare type ReactTestRenderer = { + toJSON(): null | ReactTestRendererJSON, + toTree(): null | ReactTestRendererTree, + unmount(nextElement?: React$Element): void, + update(nextElement: React$Element): void, + getInstance(): ?ReactComponentInstance, + root: ReactTestInstance, +}; +declare type Thenable = { + then(resolve: () => mixed, reject?: () => mixed): mixed +}; +declare function create(nextElement: React$Element, options?: TestRendererOptions): ReactTestRenderer; +declare function act(callback: () => ?Thenable): Thenable;" +`; diff --git a/packages/instrumenter/testResources/instrumenter/html-sample.html b/packages/instrumenter/testResources/instrumenter/html-sample.html new file mode 100644 index 0000000000..2afd1faff0 --- /dev/null +++ b/packages/instrumenter/testResources/instrumenter/html-sample.html @@ -0,0 +1,19 @@ + + + + + + + Document + + + + + + + \ No newline at end of file diff --git a/packages/instrumenter/testResources/instrumenter/html-sample.html.out.snap b/packages/instrumenter/testResources/instrumenter/html-sample.html.out.snap new file mode 100644 index 0000000000..6b663eb18b --- /dev/null +++ b/packages/instrumenter/testResources/instrumenter/html-sample.html.out.snap @@ -0,0 +1,83 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`instrumenter integration should be able to instrument html 1`] = ` +" + + + + + + Document + + + + + + +" +`; diff --git a/packages/instrumenter/testResources/instrumenter/ignore.js b/packages/instrumenter/testResources/instrumenter/ignore.js new file mode 100644 index 0000000000..abdf337039 --- /dev/null +++ b/packages/instrumenter/testResources/instrumenter/ignore.js @@ -0,0 +1,4 @@ + +function add(a, b) { + return a + b; +} diff --git a/packages/instrumenter/testResources/instrumenter/ignore.js.out.snap b/packages/instrumenter/testResources/instrumenter/ignore.js.out.snap new file mode 100644 index 0000000000..b060f79dfe --- /dev/null +++ b/packages/instrumenter/testResources/instrumenter/ignore.js.out.snap @@ -0,0 +1,66 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`instrumenter integration should not place ignored mutants 1`] = ` +"function stryNS_9fa48() { + var g = new Function(\\"return this\\")(); + var ns = g.__stryker__ || (g.__stryker__ = {}); + + if (ns.activeMutant === undefined && g.process && g.process.env && g.process.env.__STRYKER_ACTIVE_MUTANT__) { + ns.activeMutant = Number(g.process.env.__STRYKER_ACTIVE_MUTANT__); + } + + function retrieveNS() { + return ns; + } + + stryNS_9fa48 = retrieveNS; + return retrieveNS(); +} + +stryNS_9fa48(); + +function stryCov_9fa48() { + var ns = stryNS_9fa48(); + var cov = ns.mutantCoverage || (ns.mutantCoverage = { + static: {}, + perTest: {} + }); + + function cover() { + var c = cov.static; + + if (ns.currentTestId) { + c = cov.perTest[ns.currentTestId] = cov.perTest[ns.currentTestId] || {}; + } + + var a = arguments; + + for (var i = 0; i < a.length; i++) { + c[a[i]] = (c[a[i]] || 0) + 1; + } + } + + stryCov_9fa48 = cover; + cover.apply(null, arguments); +} + +function stryMutAct_9fa48(id) { + var ns = stryNS_9fa48(); + + function isActive(id) { + return ns.activeMutant === id; + } + + stryMutAct_9fa48 = isActive; + return isActive(id); +} + +function add(a, b) { + if (stryMutAct_9fa48(0)) { + {} + } else { + stryCov_9fa48(0); + return a + b; + } +}" +`; diff --git a/packages/instrumenter/testResources/instrumenter/js-sample.js b/packages/instrumenter/testResources/instrumenter/js-sample.js new file mode 100644 index 0000000000..9949cce001 --- /dev/null +++ b/packages/instrumenter/testResources/instrumenter/js-sample.js @@ -0,0 +1,5 @@ +function add(a, b) { + return a + b; +} + +add(40, 2); diff --git a/packages/instrumenter/testResources/instrumenter/js-sample.js.out.snap b/packages/instrumenter/testResources/instrumenter/js-sample.js.out.snap new file mode 100644 index 0000000000..3e464ff6ac --- /dev/null +++ b/packages/instrumenter/testResources/instrumenter/js-sample.js.out.snap @@ -0,0 +1,68 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`instrumenter integration should be able to instrument a simple js file 1`] = ` +"function stryNS_9fa48() { + var g = new Function(\\"return this\\")(); + var ns = g.__stryker__ || (g.__stryker__ = {}); + + if (ns.activeMutant === undefined && g.process && g.process.env && g.process.env.__STRYKER_ACTIVE_MUTANT__) { + ns.activeMutant = Number(g.process.env.__STRYKER_ACTIVE_MUTANT__); + } + + function retrieveNS() { + return ns; + } + + stryNS_9fa48 = retrieveNS; + return retrieveNS(); +} + +stryNS_9fa48(); + +function stryCov_9fa48() { + var ns = stryNS_9fa48(); + var cov = ns.mutantCoverage || (ns.mutantCoverage = { + static: {}, + perTest: {} + }); + + function cover() { + var c = cov.static; + + if (ns.currentTestId) { + c = cov.perTest[ns.currentTestId] = cov.perTest[ns.currentTestId] || {}; + } + + var a = arguments; + + for (var i = 0; i < a.length; i++) { + c[a[i]] = (c[a[i]] || 0) + 1; + } + } + + stryCov_9fa48 = cover; + cover.apply(null, arguments); +} + +function stryMutAct_9fa48(id) { + var ns = stryNS_9fa48(); + + function isActive(id) { + return ns.activeMutant === id; + } + + stryMutAct_9fa48 = isActive; + return isActive(id); +} + +function add(a, b) { + if (stryMutAct_9fa48(0)) { + {} + } else { + stryCov_9fa48(0); + return stryMutAct_9fa48(1) ? a - b : (stryCov_9fa48(1), a + b); + } +} + +add(40, 2);" +`; diff --git a/packages/instrumenter/testResources/instrumenter/lit-html-sample.ts b/packages/instrumenter/testResources/instrumenter/lit-html-sample.ts new file mode 100644 index 0000000000..da0b981901 --- /dev/null +++ b/packages/instrumenter/testResources/instrumenter/lit-html-sample.ts @@ -0,0 +1,156 @@ +import { LitElement, html, property, customElement, svg } from 'lit-element'; +import { Thresholds } from 'mutation-testing-report-schema'; +import { pathJoin } from '../lib/codeHelpers'; +import { MetricsResult } from 'mutation-testing-metrics'; +import { toAbsoluteUrl } from '../lib/htmlHelpers'; + +@customElement('mutation-test-report-totals') +export class MutationTestReportTotalsComponent extends LitElement { + @property() + public model: MetricsResult | undefined; + + @property() + public thresholds: Thresholds | undefined; + + @property() + public currentPath: string[] = []; + + private readonly fileIcon = svg``; + private readonly directoryIcon = svg``; + + public render() { + if (this.model) { + return html` + + ${this.renderHead()} ${this.renderTableBody(this.model)} +
+ `; + } else { + return undefined; + } + } + + private renderHead() { + return html` + + +
File / Directory
+ + +
Mutation score
+ + +
# Killed
+ + +
# Survived
+ + +
# Timeout
+ + +
# No coverage
+ + +
# Ignored
+ + +
# Runtime errors
+ + +
# Compile errors
+ + +
Total detected
+ + +
Total undetected
+ + +
Total mutants
+ + + `; + } + + private renderTableBody(model: MetricsResult) { + const renderChildren = () => { + if (model.file) { + return undefined; + } else { + return model.childResults.map((childResult) => { + let fullName: string = childResult.name; + while (!childResult.file && childResult.childResults.length === 1) { + childResult = childResult.childResults[0]; + fullName = pathJoin(fullName, childResult.name); + } + return this.renderRow(fullName, childResult, pathJoin(...this.currentPath, fullName)); + }); + } + }; + return html` + + ${this.renderRow(model.name, model, undefined)} ${renderChildren()} + + `; + } + + private renderRow(name: string, row: MetricsResult, path: string | undefined) { + const { mutationScore } = row.metrics; + const scoreIsPresent = !isNaN(mutationScore); + const coloringClass = this.determineColoringClass(mutationScore); + const mutationScoreRounded = mutationScore.toFixed(2); + const progressBarStyle = `width: ${mutationScore}%`; + return html` + ${row.file ? this.fileIcon : this.directoryIcon} + ${typeof path === 'string' ? html`${name}` : html`${row.name}`} + + ${scoreIsPresent + ? html`
+
+ ${mutationScoreRounded}% +
+
` + : html` N/A `} + + + ${scoreIsPresent ? mutationScoreRounded : undefined} + + ${row.metrics.killed} + ${row.metrics.survived} + ${row.metrics.timeout} + ${row.metrics.noCoverage} + ${row.metrics.ignored} + ${row.metrics.runtimeErrors} + ${row.metrics.compileErrors} + ${row.metrics.totalDetected} + ${row.metrics.totalUndetected} + ${row.metrics.totalMutants} + `; + } + + private determineColoringClass(mutationScore: number) { + if (!isNaN(mutationScore) && this.thresholds) { + if (mutationScore < this.thresholds.low) { + return 'danger'; + } else if (mutationScore < this.thresholds.high) { + return 'warning'; + } else { + return 'success'; + } + } else { + return 'default'; + } + } +} diff --git a/packages/instrumenter/testResources/instrumenter/lit-html-sample.ts.out.snap b/packages/instrumenter/testResources/instrumenter/lit-html-sample.ts.out.snap new file mode 100644 index 0000000000..cee223251a --- /dev/null +++ b/packages/instrumenter/testResources/instrumenter/lit-html-sample.ts.out.snap @@ -0,0 +1,304 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`instrumenter integration should be able to instrument a lit-html file 1`] = ` +"function stryNS_9fa48() { + var g = new Function(\\"return this\\")(); + var ns = g.__stryker__ || (g.__stryker__ = {}); + + if (ns.activeMutant === undefined && g.process && g.process.env && g.process.env.__STRYKER_ACTIVE_MUTANT__) { + ns.activeMutant = Number(g.process.env.__STRYKER_ACTIVE_MUTANT__); + } + + function retrieveNS() { + return ns; + } + + stryNS_9fa48 = retrieveNS; + return retrieveNS(); +} + +stryNS_9fa48(); + +function stryCov_9fa48() { + var ns = stryNS_9fa48(); + var cov = ns.mutantCoverage || (ns.mutantCoverage = { + static: {}, + perTest: {} + }); + + function cover() { + var c = cov.static; + + if (ns.currentTestId) { + c = cov.perTest[ns.currentTestId] = cov.perTest[ns.currentTestId] || {}; + } + + var a = arguments; + + for (var i = 0; i < a.length; i++) { + c[a[i]] = (c[a[i]] || 0) + 1; + } + } + + stryCov_9fa48 = cover; + cover.apply(null, arguments); +} + +function stryMutAct_9fa48(id) { + var ns = stryNS_9fa48(); + + function isActive(id) { + return ns.activeMutant === id; + } + + stryMutAct_9fa48 = isActive; + return isActive(id); +} + +import { LitElement, html, property, customElement, svg } from 'lit-element'; +import { Thresholds } from 'mutation-testing-report-schema'; +import { pathJoin } from '../lib/codeHelpers'; +import { MetricsResult } from 'mutation-testing-metrics'; +import { toAbsoluteUrl } from '../lib/htmlHelpers'; +@customElement('mutation-test-report-totals') +export class MutationTestReportTotalsComponent extends LitElement { + @property() + public model: MetricsResult | undefined; + @property() + public thresholds: Thresholds | undefined; + @property() + public currentPath: string[] = stryMutAct_9fa48(0) ? [\\"Stryker was here\\"] : (stryCov_9fa48(0), []); + private readonly fileIcon = stryMutAct_9fa48(1) ? svg\`\` : (stryCov_9fa48(1), svg\`\`); + private readonly directoryIcon = stryMutAct_9fa48(2) ? svg\`\` : (stryCov_9fa48(2), svg\`\`); + + public render() { + if (stryMutAct_9fa48(3)) { + {} + } else { + stryCov_9fa48(3); + + if (stryMutAct_9fa48(5) ? false : stryMutAct_9fa48(4) ? true : (stryCov_9fa48(4, 5), this.model)) { + if (stryMutAct_9fa48(6)) { + {} + } else { + stryCov_9fa48(6); + return stryMutAct_9fa48(7) ? html\`\` : (stryCov_9fa48(7), html\` + + \${this.renderHead()} \${this.renderTableBody(this.model)} +
+ \`); + } + } else { + if (stryMutAct_9fa48(8)) { + {} + } else { + stryCov_9fa48(8); + return undefined; + } + } + } + } + + private renderHead() { + if (stryMutAct_9fa48(9)) { + {} + } else { + stryCov_9fa48(9); + return stryMutAct_9fa48(10) ? html\`\` : (stryCov_9fa48(10), html\` + + +
File / Directory
+ + +
Mutation score
+ + +
# Killed
+ + +
# Survived
+ + +
# Timeout
+ + +
# No coverage
+ + +
# Ignored
+ + +
# Runtime errors
+ + +
# Compile errors
+ + +
Total detected
+ + +
Total undetected
+ + +
Total mutants
+ + + \`); + } + } + + private renderTableBody(model: MetricsResult) { + if (stryMutAct_9fa48(11)) { + {} + } else { + stryCov_9fa48(11); + + const renderChildren = () => { + if (stryMutAct_9fa48(12)) { + {} + } else { + stryCov_9fa48(12); + + if (stryMutAct_9fa48(14) ? false : stryMutAct_9fa48(13) ? true : (stryCov_9fa48(13, 14), model.file)) { + if (stryMutAct_9fa48(15)) { + {} + } else { + stryCov_9fa48(15); + return undefined; + } + } else { + if (stryMutAct_9fa48(16)) { + {} + } else { + stryCov_9fa48(16); + return model.childResults.map(childResult => { + if (stryMutAct_9fa48(17)) { + {} + } else { + stryCov_9fa48(17); + let fullName: string = childResult.name; + + while (stryMutAct_9fa48(19) ? !childResult.file || childResult.childResults.length === 1 : stryMutAct_9fa48(18) ? false : (stryCov_9fa48(18, 19), (stryMutAct_9fa48(20) ? childResult.file : (stryCov_9fa48(20), !childResult.file)) && (stryMutAct_9fa48(23) ? childResult.childResults.length !== 1 : stryMutAct_9fa48(22) ? false : stryMutAct_9fa48(21) ? true : (stryCov_9fa48(21, 22, 23), childResult.childResults.length === 1)))) { + if (stryMutAct_9fa48(24)) { + {} + } else { + stryCov_9fa48(24); + childResult = childResult.childResults[0]; + fullName = pathJoin(fullName, childResult.name); + } + } + + return this.renderRow(fullName, childResult, pathJoin(...this.currentPath, fullName)); + } + }); + } + } + } + }; + + return stryMutAct_9fa48(25) ? html\`\` : (stryCov_9fa48(25), html\` + + \${this.renderRow(model.name, model, undefined)} \${renderChildren()} + + \`); + } + } + + private renderRow(name: string, row: MetricsResult, path: string | undefined) { + if (stryMutAct_9fa48(26)) { + {} + } else { + stryCov_9fa48(26); + const { + mutationScore + } = row.metrics; + const scoreIsPresent = stryMutAct_9fa48(27) ? isNaN(mutationScore) : (stryCov_9fa48(27), !isNaN(mutationScore)); + const coloringClass = this.determineColoringClass(mutationScore); + const mutationScoreRounded = mutationScore.toFixed(2); + const progressBarStyle = stryMutAct_9fa48(28) ? \`\` : (stryCov_9fa48(28), \`width: \${mutationScore}%\`); + return stryMutAct_9fa48(29) ? html\`\` : (stryCov_9fa48(29), html\` + \${row.file ? this.fileIcon : this.directoryIcon} + \${(stryMutAct_9fa48(32) ? typeof path !== 'string' : stryMutAct_9fa48(31) ? false : stryMutAct_9fa48(30) ? true : (stryCov_9fa48(30, 31, 32), typeof path === (stryMutAct_9fa48(33) ? \\"\\" : (stryCov_9fa48(33), 'string')))) ? stryMutAct_9fa48(34) ? html\`\` : (stryCov_9fa48(34), html\`\${name}\`) : stryMutAct_9fa48(35) ? html\`\` : (stryCov_9fa48(35), html\`\${row.name}\`)} + + \${scoreIsPresent ? stryMutAct_9fa48(36) ? html\`\` : (stryCov_9fa48(36), html\`
+
+ \${mutationScoreRounded}% +
+
\`) : stryMutAct_9fa48(37) ? html\`\` : (stryCov_9fa48(37), html\` N/A \`)} + + + \${scoreIsPresent ? mutationScoreRounded : undefined} + + \${row.metrics.killed} + \${row.metrics.survived} + \${row.metrics.timeout} + \${row.metrics.noCoverage} + \${row.metrics.ignored} + \${row.metrics.runtimeErrors} + \${row.metrics.compileErrors} + \${row.metrics.totalDetected} + \${row.metrics.totalUndetected} + \${row.metrics.totalMutants} + \`); + } + } + + private determineColoringClass(mutationScore: number) { + if (stryMutAct_9fa48(38)) { + {} + } else { + stryCov_9fa48(38); + + if (stryMutAct_9fa48(41) ? !isNaN(mutationScore) || this.thresholds : stryMutAct_9fa48(40) ? false : stryMutAct_9fa48(39) ? true : (stryCov_9fa48(39, 40, 41), (stryMutAct_9fa48(42) ? isNaN(mutationScore) : (stryCov_9fa48(42), !isNaN(mutationScore))) && this.thresholds)) { + if (stryMutAct_9fa48(43)) { + {} + } else { + stryCov_9fa48(43); + + if (stryMutAct_9fa48(47) ? mutationScore >= this.thresholds.low : stryMutAct_9fa48(46) ? mutationScore <= this.thresholds.low : stryMutAct_9fa48(45) ? false : stryMutAct_9fa48(44) ? true : (stryCov_9fa48(44, 45, 46, 47), mutationScore < this.thresholds.low)) { + if (stryMutAct_9fa48(48)) { + {} + } else { + stryCov_9fa48(48); + return stryMutAct_9fa48(49) ? \\"\\" : (stryCov_9fa48(49), 'danger'); + } + } else if (stryMutAct_9fa48(53) ? mutationScore >= this.thresholds.high : stryMutAct_9fa48(52) ? mutationScore <= this.thresholds.high : stryMutAct_9fa48(51) ? false : stryMutAct_9fa48(50) ? true : (stryCov_9fa48(50, 51, 52, 53), mutationScore < this.thresholds.high)) { + if (stryMutAct_9fa48(54)) { + {} + } else { + stryCov_9fa48(54); + return stryMutAct_9fa48(55) ? \\"\\" : (stryCov_9fa48(55), 'warning'); + } + } else { + if (stryMutAct_9fa48(56)) { + {} + } else { + stryCov_9fa48(56); + return stryMutAct_9fa48(57) ? \\"\\" : (stryCov_9fa48(57), 'success'); + } + } + } + } else { + if (stryMutAct_9fa48(58)) { + {} + } else { + stryCov_9fa48(58); + return stryMutAct_9fa48(59) ? \\"\\" : (stryCov_9fa48(59), 'default'); + } + } + } + } + +}" +`; diff --git a/packages/instrumenter/testResources/instrumenter/shebang.js b/packages/instrumenter/testResources/instrumenter/shebang.js new file mode 100644 index 0000000000..b691b76619 --- /dev/null +++ b/packages/instrumenter/testResources/instrumenter/shebang.js @@ -0,0 +1,3 @@ +#! /usr/bin/env node + +console.log('test'); diff --git a/packages/instrumenter/testResources/instrumenter/shebang.js.out.snap b/packages/instrumenter/testResources/instrumenter/shebang.js.out.snap new file mode 100644 index 0000000000..239391de3d --- /dev/null +++ b/packages/instrumenter/testResources/instrumenter/shebang.js.out.snap @@ -0,0 +1,61 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`instrumenter integration should be able to instrument js files with a shebang in them 1`] = ` +"#! /usr/bin/env node + +function stryNS_9fa48() { + var g = new Function(\\"return this\\")(); + var ns = g.__stryker__ || (g.__stryker__ = {}); + + if (ns.activeMutant === undefined && g.process && g.process.env && g.process.env.__STRYKER_ACTIVE_MUTANT__) { + ns.activeMutant = Number(g.process.env.__STRYKER_ACTIVE_MUTANT__); + } + + function retrieveNS() { + return ns; + } + + stryNS_9fa48 = retrieveNS; + return retrieveNS(); +} + +stryNS_9fa48(); + +function stryCov_9fa48() { + var ns = stryNS_9fa48(); + var cov = ns.mutantCoverage || (ns.mutantCoverage = { + static: {}, + perTest: {} + }); + + function cover() { + var c = cov.static; + + if (ns.currentTestId) { + c = cov.perTest[ns.currentTestId] = cov.perTest[ns.currentTestId] || {}; + } + + var a = arguments; + + for (var i = 0; i < a.length; i++) { + c[a[i]] = (c[a[i]] || 0) + 1; + } + } + + stryCov_9fa48 = cover; + cover.apply(null, arguments); +} + +function stryMutAct_9fa48(id) { + var ns = stryNS_9fa48(); + + function isActive(id) { + return ns.activeMutant === id; + } + + stryMutAct_9fa48 = isActive; + return isActive(id); +} + +console.log(stryMutAct_9fa48(0) ? \\"\\" : (stryCov_9fa48(0), 'test'));" +`; diff --git a/packages/instrumenter/testResources/instrumenter/super-call.ts b/packages/instrumenter/testResources/instrumenter/super-call.ts new file mode 100644 index 0000000000..0288be9ea7 --- /dev/null +++ b/packages/instrumenter/testResources/instrumenter/super-call.ts @@ -0,0 +1,5 @@ +export class InjectionError extends TypedInjectError { + constructor(public readonly path: InjectionTarget[], public readonly cause: Error) { + super(`Could not ${describeInjectAction(path[0])} ${path.map(name).join(' -> ')}. Cause: ${cause.message}`); + } +} diff --git a/packages/instrumenter/testResources/instrumenter/super-call.ts.out.snap b/packages/instrumenter/testResources/instrumenter/super-call.ts.out.snap new file mode 100644 index 0000000000..70d4976668 --- /dev/null +++ b/packages/instrumenter/testResources/instrumenter/super-call.ts.out.snap @@ -0,0 +1,64 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`instrumenter integration should be able to instrument super calls 1`] = ` +"function stryNS_9fa48() { + var g = new Function(\\"return this\\")(); + var ns = g.__stryker__ || (g.__stryker__ = {}); + + if (ns.activeMutant === undefined && g.process && g.process.env && g.process.env.__STRYKER_ACTIVE_MUTANT__) { + ns.activeMutant = Number(g.process.env.__STRYKER_ACTIVE_MUTANT__); + } + + function retrieveNS() { + return ns; + } + + stryNS_9fa48 = retrieveNS; + return retrieveNS(); +} + +stryNS_9fa48(); + +function stryCov_9fa48() { + var ns = stryNS_9fa48(); + var cov = ns.mutantCoverage || (ns.mutantCoverage = { + static: {}, + perTest: {} + }); + + function cover() { + var c = cov.static; + + if (ns.currentTestId) { + c = cov.perTest[ns.currentTestId] = cov.perTest[ns.currentTestId] || {}; + } + + var a = arguments; + + for (var i = 0; i < a.length; i++) { + c[a[i]] = (c[a[i]] || 0) + 1; + } + } + + stryCov_9fa48 = cover; + cover.apply(null, arguments); +} + +function stryMutAct_9fa48(id) { + var ns = stryNS_9fa48(); + + function isActive(id) { + return ns.activeMutant === id; + } + + stryMutAct_9fa48 = isActive; + return isActive(id); +} + +export class InjectionError extends TypedInjectError { + constructor(public readonly path: InjectionTarget[], public readonly cause: Error) { + super(stryMutAct_9fa48(0) ? \`\` : (stryCov_9fa48(0), \`Could not \${describeInjectAction(path[0])} \${path.map(name).join(stryMutAct_9fa48(1) ? \\"\\" : (stryCov_9fa48(1), ' -> '))}. Cause: \${cause.message}\`)); + } + +}" +`; diff --git a/packages/instrumenter/testResources/instrumenter/switch-case.js b/packages/instrumenter/testResources/instrumenter/switch-case.js new file mode 100644 index 0000000000..ea7418ea69 --- /dev/null +++ b/packages/instrumenter/testResources/instrumenter/switch-case.js @@ -0,0 +1,9 @@ +switch(foo){ + case 'bar': + console.log('bar'); + break; + case 'baz': + console.log('baz'); + break; + +} diff --git a/packages/instrumenter/testResources/instrumenter/switch-case.js.out.snap b/packages/instrumenter/testResources/instrumenter/switch-case.js.out.snap new file mode 100644 index 0000000000..4fa31ea6dc --- /dev/null +++ b/packages/instrumenter/testResources/instrumenter/switch-case.js.out.snap @@ -0,0 +1,74 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`instrumenter integration should be able to instrument switch case statements (using the switchCaseMutantPlacer) 1`] = ` +"function stryNS_9fa48() { + var g = new Function(\\"return this\\")(); + var ns = g.__stryker__ || (g.__stryker__ = {}); + + if (ns.activeMutant === undefined && g.process && g.process.env && g.process.env.__STRYKER_ACTIVE_MUTANT__) { + ns.activeMutant = Number(g.process.env.__STRYKER_ACTIVE_MUTANT__); + } + + function retrieveNS() { + return ns; + } + + stryNS_9fa48 = retrieveNS; + return retrieveNS(); +} + +stryNS_9fa48(); + +function stryCov_9fa48() { + var ns = stryNS_9fa48(); + var cov = ns.mutantCoverage || (ns.mutantCoverage = { + static: {}, + perTest: {} + }); + + function cover() { + var c = cov.static; + + if (ns.currentTestId) { + c = cov.perTest[ns.currentTestId] = cov.perTest[ns.currentTestId] || {}; + } + + var a = arguments; + + for (var i = 0; i < a.length; i++) { + c[a[i]] = (c[a[i]] || 0) + 1; + } + } + + stryCov_9fa48 = cover; + cover.apply(null, arguments); +} + +function stryMutAct_9fa48(id) { + var ns = stryNS_9fa48(); + + function isActive(id) { + return ns.activeMutant === id; + } + + stryMutAct_9fa48 = isActive; + return isActive(id); +} + +switch (foo) { + case stryMutAct_9fa48(1) ? \\"\\" : (stryCov_9fa48(1), 'bar'): + if (stryMutAct_9fa48(0)) {} else { + stryCov_9fa48(0); + console.log(stryMutAct_9fa48(2) ? \\"\\" : (stryCov_9fa48(2), 'bar')); + break; + } + + case stryMutAct_9fa48(4) ? \\"\\" : (stryCov_9fa48(4), 'baz'): + if (stryMutAct_9fa48(3)) {} else { + stryCov_9fa48(3); + console.log(stryMutAct_9fa48(5) ? \\"\\" : (stryCov_9fa48(5), 'baz')); + break; + } + +}" +`; diff --git a/packages/instrumenter/testResources/instrumenter/ts-declarations.ts b/packages/instrumenter/testResources/instrumenter/ts-declarations.ts new file mode 100644 index 0000000000..42b4e32708 --- /dev/null +++ b/packages/instrumenter/testResources/instrumenter/ts-declarations.ts @@ -0,0 +1,6 @@ +export declare const globalNamespace = "globalNamespace"; +declare function foo(): 'foo'; +declare module 'express' { +} + +React.useState(); diff --git a/packages/instrumenter/testResources/instrumenter/ts-declarations.ts.out.snap b/packages/instrumenter/testResources/instrumenter/ts-declarations.ts.out.snap new file mode 100644 index 0000000000..acba724781 --- /dev/null +++ b/packages/instrumenter/testResources/instrumenter/ts-declarations.ts.out.snap @@ -0,0 +1,8 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`instrumenter integration type declarations should not produce mutants for a TS declaration file 1`] = ` +"export declare const globalNamespace = \\"globalNamespace\\"; +declare function foo(): 'foo'; +declare module 'express' {} +React.useState();" +`; diff --git a/packages/instrumenter/testResources/instrumenter/ts-sample.ts b/packages/instrumenter/testResources/instrumenter/ts-sample.ts new file mode 100644 index 0000000000..1bcb72b3ec --- /dev/null +++ b/packages/instrumenter/testResources/instrumenter/ts-sample.ts @@ -0,0 +1 @@ +const bar: number = 40 + 2; diff --git a/packages/instrumenter/testResources/instrumenter/ts-sample.ts.out.snap b/packages/instrumenter/testResources/instrumenter/ts-sample.ts.out.snap new file mode 100644 index 0000000000..fb96df20f1 --- /dev/null +++ b/packages/instrumenter/testResources/instrumenter/ts-sample.ts.out.snap @@ -0,0 +1,59 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`instrumenter integration should be able to instrument a simple ts file 1`] = ` +"function stryNS_9fa48() { + var g = new Function(\\"return this\\")(); + var ns = g.__stryker__ || (g.__stryker__ = {}); + + if (ns.activeMutant === undefined && g.process && g.process.env && g.process.env.__STRYKER_ACTIVE_MUTANT__) { + ns.activeMutant = Number(g.process.env.__STRYKER_ACTIVE_MUTANT__); + } + + function retrieveNS() { + return ns; + } + + stryNS_9fa48 = retrieveNS; + return retrieveNS(); +} + +stryNS_9fa48(); + +function stryCov_9fa48() { + var ns = stryNS_9fa48(); + var cov = ns.mutantCoverage || (ns.mutantCoverage = { + static: {}, + perTest: {} + }); + + function cover() { + var c = cov.static; + + if (ns.currentTestId) { + c = cov.perTest[ns.currentTestId] = cov.perTest[ns.currentTestId] || {}; + } + + var a = arguments; + + for (var i = 0; i < a.length; i++) { + c[a[i]] = (c[a[i]] || 0) + 1; + } + } + + stryCov_9fa48 = cover; + cover.apply(null, arguments); +} + +function stryMutAct_9fa48(id) { + var ns = stryNS_9fa48(); + + function isActive(id) { + return ns.activeMutant === id; + } + + stryMutAct_9fa48 = isActive; + return isActive(id); +} + +const bar: number = stryMutAct_9fa48(0) ? 40 - 2 : (stryCov_9fa48(0), 40 + 2);" +`; diff --git a/packages/instrumenter/testResources/instrumenter/type-definitions.ts b/packages/instrumenter/testResources/instrumenter/type-definitions.ts new file mode 100644 index 0000000000..f99471cc0d --- /dev/null +++ b/packages/instrumenter/testResources/instrumenter/type-definitions.ts @@ -0,0 +1,4 @@ +/** + * @see https://github.com/stryker-mutator/stryker/issues/2465 + */ +const flatten = require('lodash/flatten') as typeof import('lodash/flatten'); diff --git a/packages/instrumenter/testResources/instrumenter/type-definitions.ts.out.snap b/packages/instrumenter/testResources/instrumenter/type-definitions.ts.out.snap new file mode 100644 index 0000000000..f567b1932c --- /dev/null +++ b/packages/instrumenter/testResources/instrumenter/type-definitions.ts.out.snap @@ -0,0 +1,8 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`instrumenter integration type declarations should not produce mutants for TS type definitions 1`] = ` +"/** + * @see https://github.com/stryker-mutator/stryker/issues/2465 + */ +const flatten = (require('lodash/flatten') as typeof import('lodash/flatten'));" +`; diff --git a/packages/instrumenter/testResources/instrumenter/vue-sample.vue b/packages/instrumenter/testResources/instrumenter/vue-sample.vue new file mode 100644 index 0000000000..2c201d49c6 --- /dev/null +++ b/packages/instrumenter/testResources/instrumenter/vue-sample.vue @@ -0,0 +1,116 @@ + + + + + + + diff --git a/packages/instrumenter/testResources/instrumenter/vue-sample.vue.out.snap b/packages/instrumenter/testResources/instrumenter/vue-sample.vue.out.snap new file mode 100644 index 0000000000..3c16fc6ca0 --- /dev/null +++ b/packages/instrumenter/testResources/instrumenter/vue-sample.vue.out.snap @@ -0,0 +1,236 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`instrumenter integration should be able to instrument a vue sample 1`] = ` +" + + + + + + +" +`; diff --git a/packages/instrumenter/testResources/parser/App.tsx b/packages/instrumenter/testResources/parser/App.tsx new file mode 100644 index 0000000000..4280507f3a --- /dev/null +++ b/packages/instrumenter/testResources/parser/App.tsx @@ -0,0 +1 @@ +const app = diff --git a/packages/instrumenter/testResources/parser/App.vue b/packages/instrumenter/testResources/parser/App.vue new file mode 100644 index 0000000000..34c1191f05 --- /dev/null +++ b/packages/instrumenter/testResources/parser/App.vue @@ -0,0 +1,37 @@ + + + + + diff --git a/packages/instrumenter/testResources/parser/app.cjs b/packages/instrumenter/testResources/parser/app.cjs new file mode 100644 index 0000000000..7868901fcb --- /dev/null +++ b/packages/instrumenter/testResources/parser/app.cjs @@ -0,0 +1 @@ +module.exports = class App {} \ No newline at end of file diff --git a/packages/instrumenter/testResources/parser/app.component.ts b/packages/instrumenter/testResources/parser/app.component.ts new file mode 100644 index 0000000000..720ba19362 --- /dev/null +++ b/packages/instrumenter/testResources/parser/app.component.ts @@ -0,0 +1,10 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.scss'] +}) +export class AppComponent { + title = 'angular-app'; +} diff --git a/packages/instrumenter/testResources/parser/app.mjs b/packages/instrumenter/testResources/parser/app.mjs new file mode 100644 index 0000000000..b6185569a9 --- /dev/null +++ b/packages/instrumenter/testResources/parser/app.mjs @@ -0,0 +1 @@ +export class App {} \ No newline at end of file diff --git a/packages/instrumenter/testResources/parser/index.html b/packages/instrumenter/testResources/parser/index.html new file mode 100644 index 0000000000..b286e90ebb --- /dev/null +++ b/packages/instrumenter/testResources/parser/index.html @@ -0,0 +1,26 @@ + + + + + + Document + + + + + + + + \ No newline at end of file diff --git a/packages/instrumenter/testResources/parser/js-in-babel-project/babel.config.json b/packages/instrumenter/testResources/parser/js-in-babel-project/babel.config.json new file mode 100644 index 0000000000..72f06188ed --- /dev/null +++ b/packages/instrumenter/testResources/parser/js-in-babel-project/babel.config.json @@ -0,0 +1,5 @@ +{ + "plugins": [ + ["@babel/plugin-proposal-decorators", { "legacy": true }] + ] +} diff --git a/packages/instrumenter/testResources/parser/js-in-babel-project/src/app.js b/packages/instrumenter/testResources/parser/js-in-babel-project/src/app.js new file mode 100644 index 0000000000..c9ff7826ec --- /dev/null +++ b/packages/instrumenter/testResources/parser/js-in-babel-project/src/app.js @@ -0,0 +1 @@ +class App {} diff --git a/packages/instrumenter/testResources/parser/jsx-with-babelrc/.babelrc b/packages/instrumenter/testResources/parser/jsx-with-babelrc/.babelrc new file mode 100644 index 0000000000..ed431dd915 --- /dev/null +++ b/packages/instrumenter/testResources/parser/jsx-with-babelrc/.babelrc @@ -0,0 +1,5 @@ +{ + "presets": [ + "@babel/preset-react" + ] +} \ No newline at end of file diff --git a/packages/instrumenter/testResources/parser/jsx-with-babelrc/Badge.js b/packages/instrumenter/testResources/parser/jsx-with-babelrc/Badge.js new file mode 100644 index 0000000000..fd4185dd50 --- /dev/null +++ b/packages/instrumenter/testResources/parser/jsx-with-babelrc/Badge.js @@ -0,0 +1,32 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +const propTypes = { + color: PropTypes.string +}; + +const defaultProps = { + color: 'secondary', +}; + +const Badge = (props) => { + let { + color, + ...attributes + } = props; + + const classes = ['badge', 'badge-' + color]; + + if (attributes.href && Tag === 'span') { + Tag = 'a'; + } + + return ( + + ); +}; + +Badge.propTypes = propTypes; +Badge.defaultProps = defaultProps; + +export default Badge; diff --git a/packages/instrumenter/testResources/parser/jsx-with-project-wide-config/babel.config.json b/packages/instrumenter/testResources/parser/jsx-with-project-wide-config/babel.config.json new file mode 100644 index 0000000000..52b6950ee8 --- /dev/null +++ b/packages/instrumenter/testResources/parser/jsx-with-project-wide-config/babel.config.json @@ -0,0 +1,5 @@ +{ + "presets": [ + "@babel/preset-react" + ] +} diff --git a/packages/instrumenter/testResources/parser/jsx-with-project-wide-config/src/Badge.js b/packages/instrumenter/testResources/parser/jsx-with-project-wide-config/src/Badge.js new file mode 100644 index 0000000000..fd4185dd50 --- /dev/null +++ b/packages/instrumenter/testResources/parser/jsx-with-project-wide-config/src/Badge.js @@ -0,0 +1,32 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +const propTypes = { + color: PropTypes.string +}; + +const defaultProps = { + color: 'secondary', +}; + +const Badge = (props) => { + let { + color, + ...attributes + } = props; + + const classes = ['badge', 'badge-' + color]; + + if (attributes.href && Tag === 'span') { + Tag = 'a'; + } + + return ( + + ); +}; + +Badge.propTypes = propTypes; +Badge.defaultProps = defaultProps; + +export default Badge; diff --git a/packages/instrumenter/testResources/parser/ts-in-babel-project/babel.config.js b/packages/instrumenter/testResources/parser/ts-in-babel-project/babel.config.js new file mode 100644 index 0000000000..c014408a28 --- /dev/null +++ b/packages/instrumenter/testResources/parser/ts-in-babel-project/babel.config.js @@ -0,0 +1,5 @@ +module.exports = { + plugins: [ + 'transform-decorators-legacy' + ] +} diff --git a/packages/instrumenter/testResources/parser/ts-in-babel-project/src/app.ts b/packages/instrumenter/testResources/parser/ts-in-babel-project/src/app.ts new file mode 100644 index 0000000000..c9ff7826ec --- /dev/null +++ b/packages/instrumenter/testResources/parser/ts-in-babel-project/src/app.ts @@ -0,0 +1 @@ +class App {} diff --git a/packages/instrumenter/testResources/printer/echo/ts-with-comments.ts b/packages/instrumenter/testResources/printer/echo/ts-with-comments.ts new file mode 100644 index 0000000000..c5c8145301 --- /dev/null +++ b/packages/instrumenter/testResources/printer/echo/ts-with-comments.ts @@ -0,0 +1,4 @@ +const a = 'b'; + +// @ts-expect-error +const c: number = a + 42; diff --git a/packages/instrumenter/testResources/printer/html/hello-world.in.html b/packages/instrumenter/testResources/printer/html/hello-world.in.html new file mode 100644 index 0000000000..c307582d1f --- /dev/null +++ b/packages/instrumenter/testResources/printer/html/hello-world.in.html @@ -0,0 +1,22 @@ + + + + Page Title + + + + +

My Web Page

+

A Paragraph

+ + + + + + diff --git a/packages/instrumenter/testResources/printer/html/hello-world.out.html b/packages/instrumenter/testResources/printer/html/hello-world.out.html new file mode 100644 index 0000000000..a4be44a555 --- /dev/null +++ b/packages/instrumenter/testResources/printer/html/hello-world.out.html @@ -0,0 +1,22 @@ + + + + Page Title + + + + +

My Web Page

+

A Paragraph

+ + + + + + diff --git a/packages/instrumenter/tsconfig.json b/packages/instrumenter/tsconfig.json new file mode 100644 index 0000000000..d5c40e5337 --- /dev/null +++ b/packages/instrumenter/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./src" + }, + { + "path": "./test" + } + ] +} diff --git a/packages/jasmine-framework/CHANGELOG.md b/packages/jasmine-framework/CHANGELOG.md index bd75b97372..7576a15b1d 100644 --- a/packages/jasmine-framework/CHANGELOG.md +++ b/packages/jasmine-framework/CHANGELOG.md @@ -3,6 +3,97 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [4.0.0-beta.10](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.9...v4.0.0-beta.10) (2020-10-05) + +**Note:** Version bump only for package @stryker-mutator/jasmine-framework + + + + + +# [4.0.0-beta.9](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.8...v4.0.0-beta.9) (2020-09-30) + +**Note:** Version bump only for package @stryker-mutator/jasmine-framework + + + + + +# [4.0.0-beta.8](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.7...v4.0.0-beta.8) (2020-09-22) + +**Note:** Version bump only for package @stryker-mutator/jasmine-framework + + + + + +# [4.0.0-beta.7](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.6...v4.0.0-beta.7) (2020-09-17) + +**Note:** Version bump only for package @stryker-mutator/jasmine-framework + + + + + +# [4.0.0-beta.6](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.5...v4.0.0-beta.6) (2020-09-10) + +**Note:** Version bump only for package @stryker-mutator/jasmine-framework + + + + + +# [4.0.0-beta.5](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.4...v4.0.0-beta.5) (2020-09-09) + +**Note:** Version bump only for package @stryker-mutator/jasmine-framework + + + + + +# [4.0.0-beta.4](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.3...v4.0.0-beta.4) (2020-08-29) + +**Note:** Version bump only for package @stryker-mutator/jasmine-framework + + + + + +# [4.0.0-beta.3](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.2...v4.0.0-beta.3) (2020-08-19) + +**Note:** Version bump only for package @stryker-mutator/jasmine-framework + + + + + +# [4.0.0-beta.2](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.1...v4.0.0-beta.2) (2020-08-07) + +**Note:** Version bump only for package @stryker-mutator/jasmine-framework + + + + + +# [4.0.0-beta.1](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.0...v4.0.0-beta.1) (2020-07-17) + +**Note:** Version bump only for package @stryker-mutator/jasmine-framework + + + + + +# [4.0.0-beta.0](https://github.com/stryker-mutator/stryker/compare/v3.3.1...v4.0.0-beta.0) (2020-07-10) + + +### Features + +* **test-framework:** remove `TestFramework` API ([fe5e200](https://github.com/stryker-mutator/stryker/commit/fe5e200e1f7ad7a24ebceacb2a62c2be58ce6a4f)) + + + + + ## [3.3.1](https://github.com/stryker-mutator/stryker/compare/v3.3.0...v3.3.1) (2020-07-04) **Note:** Version bump only for package @stryker-mutator/jasmine-framework diff --git a/packages/jasmine-framework/package.json b/packages/jasmine-framework/package.json index ecca5b0e96..25e93fd816 100644 --- a/packages/jasmine-framework/package.json +++ b/packages/jasmine-framework/package.json @@ -1,23 +1,16 @@ { "name": "@stryker-mutator/jasmine-framework", - "version": "3.3.1", + "version": "4.0.0-beta.10", "description": "A plugin to use the Jasmine test framework in Stryker, the JavaScript mutation testing framework", "main": "src/index.js", - "scripts": { - "test": "nyc --exclude-after-remap=false --check-coverage --reporter=html --report-dir=reports/coverage --lines 100 --functions 100 --branches 100 npm run mocha", - "mocha": "mocha \"test/helpers/**/*.js\" \"test/unit/**/*.js\" && mocha --timeout 10000 \"test/helpers/**/*.js\" \"test/integration/**/*.js\"", - "stryker": "node ../core/bin/stryker run" - }, + "scripts": {}, "repository": { "type": "git", "url": "git+ssh://git@github.com/stryker-mutator/stryker.git" }, "keywords": [ "stryker", - "jasmine", - "@stryker-mutator/test-framework-plugin", - "@stryker-mutator/karma-runner", - "@stryker-mutator/jasmine-runner" + "jasmine" ], "publishConfig": { "access": "public" @@ -28,18 +21,8 @@ "url": "https://github.com/stryker-mutator/stryker/issues" }, "homepage": "https://github.com/stryker-mutator/stryker/tree/master/packages/jasmine#readme", - "peerDependencies": { - "@stryker-mutator/core": "^3.0.0", - "jasmine-core": ">=2" - }, - "dependencies": { - "@stryker-mutator/api": "^3.3.1" - }, "contributors": [], "engines": { "node": ">=10" - }, - "devDependencies": { - "@types/node": "^14.0.1" } } diff --git a/packages/jasmine-framework/src/JasmineTestFramework.ts b/packages/jasmine-framework/src/JasmineTestFramework.ts deleted file mode 100644 index e68f53eb76..0000000000 --- a/packages/jasmine-framework/src/JasmineTestFramework.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { TestFramework, TestSelection } from '@stryker-mutator/api/test_framework'; - -export default class JasmineTestFramework implements TestFramework { - /** - * Creates a code fragment which, if included in a test run, - * is run before a particular test is run. - */ - public beforeEach(codeFragment: string): string { - return ` - jasmine.getEnv().addReporter({ - specStarted: function () { - ${codeFragment} - } - });`; - } - - /** - * Creates a code fragment which, if included in a test run, - * is run before a particular test is run. - */ - public afterEach(codeFragment: string): string { - return ` - jasmine.getEnv().addReporter({ - specDone: function () { - ${codeFragment} - } - });`; - } - - public filter(testSelections: TestSelection[]): string { - if (testSelections.length) { - const names = testSelections.map((selection) => selection.name); - return ` - jasmine.getEnv().specFilter = function (spec) { - return ${JSON.stringify(names)}.indexOf(spec.getFullName()) !== -1; - }`; - } else { - return ''; - } - } -} diff --git a/packages/jasmine-framework/src/index.ts b/packages/jasmine-framework/src/index.ts index 431f0039dd..19ee1fb54b 100644 --- a/packages/jasmine-framework/src/index.ts +++ b/packages/jasmine-framework/src/index.ts @@ -1,5 +1 @@ -import { declareClassPlugin, PluginKind } from '@stryker-mutator/api/plugin'; - -import JasmineTestFramework from './JasmineTestFramework'; - -export const strykerPlugins = [declareClassPlugin(PluginKind.TestFramework, 'jasmine', JasmineTestFramework)]; +console.warn('Framework plugins are no longer needed in Stryker 4.0. Please remove "@stryker-mutator/jasmine-framework" from your devDependencies.'); diff --git a/packages/jasmine-framework/stryker.conf.js b/packages/jasmine-framework/stryker.conf.js deleted file mode 100644 index fa5a53f3c4..0000000000 --- a/packages/jasmine-framework/stryker.conf.js +++ /dev/null @@ -1,5 +0,0 @@ -const path = require('path'); -const settings = require('../../stryker.parent.conf'); -const moduleName = __dirname.split(path.sep).pop(); -settings.dashboard.module = moduleName; -module.exports = settings; diff --git a/packages/jasmine-framework/test/helpers/initChai.ts b/packages/jasmine-framework/test/helpers/initChai.ts deleted file mode 100644 index 514154da42..0000000000 --- a/packages/jasmine-framework/test/helpers/initChai.ts +++ /dev/null @@ -1,6 +0,0 @@ -import * as chai from 'chai'; -import * as chaiAsPromised from 'chai-as-promised'; -import * as sinonChai from 'sinon-chai'; - -chai.use(sinonChai); -chai.use(chaiAsPromised); diff --git a/packages/jasmine-framework/test/integration/nestedSuite.it.spec.ts b/packages/jasmine-framework/test/integration/nestedSuite.it.spec.ts deleted file mode 100644 index f9ac5281cc..0000000000 --- a/packages/jasmine-framework/test/integration/nestedSuite.it.spec.ts +++ /dev/null @@ -1,96 +0,0 @@ -import * as fs from 'fs'; -import * as path from 'path'; - -import { TestSelection } from '@stryker-mutator/api/test_framework'; -import { expect } from 'chai'; -import * as execa from 'execa'; -import * as rimraf from 'rimraf'; - -import JasmineTestFramework from '../../src/JasmineTestFramework'; - -interface JasmineTest { - id: string; - description: string; - fullName: string; - failedExpectations: any[]; - passedExpectations: any[]; - status: string; -} - -describe('Selecting tests with nested suites', () => { - let sut: JasmineTestFramework; - let testSelections: TestSelection[]; - const jsonReporterFile = path.resolve(__dirname, '..', '..', 'testResources', 'json-reporter.js'); - const nestedSuiteFile = path.resolve(__dirname, '..', '..', 'testResources', 'nested-suite.js'); - const selectTestFile = path.join(__dirname, '..', '..', 'testResources', '__filterSpecs.js'); - - beforeEach(() => { - sut = new JasmineTestFramework(); - testSelections = [ - { id: 0, name: 'outer test 1' }, - { id: 1, name: 'outer inner test 2' }, - { id: 2, name: 'outer test 3' }, - ]; - }); - - afterEach(() => { - rimraf.sync(selectTestFile); - }); - - it('should run all tests in expected order when running all tests', () => { - const result = execJasmine(nestedSuiteFile); - expect(result.map((test) => test.fullName)).deep.eq(['outer test 1', 'outer inner test 2', 'outer test 3']); - }); - - it('should only run test 1 if filtered on index 0', () => { - filter([0]); - const result = execJasmine(selectTestFile, nestedSuiteFile); - expect(result).lengthOf(3); - expect(result[0].status).eq('passed'); - expect(result[1].status).eq('excluded'); - expect(result[2].status).eq('excluded'); - expect(result[0].fullName).eq('outer test 1'); - }); - - it('should only run test 2 if filtered on index 1', () => { - filter([1]); - const result = execJasmine(selectTestFile, nestedSuiteFile); - expect(result).lengthOf(3); - expect(result[0].status).eq('excluded'); - expect(result[1].status).eq('passed'); - expect(result[2].status).eq('excluded'); - expect(result[1].fullName).eq('outer inner test 2'); - }); - - it('should only run test 3 if filtered on index 2', () => { - filter([2]); - const result = execJasmine(selectTestFile, nestedSuiteFile); - expect(result).lengthOf(3); - expect(result[0].status).eq('excluded'); - expect(result[1].status).eq('excluded'); - expect(result[2].status).eq('passed'); - expect(result[2].fullName).eq('outer test 3'); - }); - - it('should only run tests 1 and 3 if filtered on indices 0 and 2', () => { - filter([0, 2]); - const result = execJasmine(selectTestFile, nestedSuiteFile); - expect(result).lengthOf(3); - expect(result[0].status).eq('passed'); - expect(result[1].status).eq('excluded'); - expect(result[2].status).eq('passed'); - expect(result[0].fullName).eq('outer test 1'); - expect(result[2].fullName).eq('outer test 3'); - }); - - function filter(testIds: number[]) { - const selections = testIds.map((id) => testSelections[id]); - const filterFn = `(function (window) {${sut.filter(selections)}})(global);`; - fs.writeFileSync(selectTestFile, filterFn, 'utf8'); - } - - function execJasmine(...files: string[]): JasmineTest[] { - const execResult = execa.sync('jasmine', ['--random=false', jsonReporterFile, ...files]); - return JSON.parse(execResult.stdout); - } -}); diff --git a/packages/jasmine-framework/test/unit/JasmineTestFramework.spec.ts b/packages/jasmine-framework/test/unit/JasmineTestFramework.spec.ts deleted file mode 100644 index ee56bf05d1..0000000000 --- a/packages/jasmine-framework/test/unit/JasmineTestFramework.spec.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { expect } from 'chai'; - -import JasmineTestFramework from '../../src/JasmineTestFramework'; - -describe('JasmineTestFramework', () => { - let sut: JasmineTestFramework; - beforeEach(() => (sut = new JasmineTestFramework())); - - describe('beforeEach()', () => { - it('should result in a specStarted reporter hook', () => - expect(sut.beforeEach('fragment')).to.contain('fragment').and.to.contain('specStarted: function () {')); - }); - - describe('afterEach()', () => { - it('should result in an specDone reporter hook', () => - expect(sut.afterEach('fragment')).to.contain('fragment').and.to.contain('specDone: function () {')); - }); - - describe('filter()', () => { - it("should result in a specFilter of jasmine it's", () => { - expect( - sut.filter([ - { id: 5, name: 'test five' }, - { id: 8, name: 'test eight' }, - ]) - ) - .to.contain('jasmine.getEnv().specFilter = function (spec)') - .and.to.contain('return ["test five","test eight"].indexOf(spec.getFullName()) !== -1;'); - }); - - it('should result in an empty string when filter is empty', () => { - expect(sut.filter([])).eq(''); - }); - }); -}); diff --git a/packages/jasmine-framework/test/unit/index.spec.ts b/packages/jasmine-framework/test/unit/index.spec.ts deleted file mode 100644 index 497f4dccdf..0000000000 --- a/packages/jasmine-framework/test/unit/index.spec.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { expect } from 'chai'; - -import { strykerPlugins } from '../..'; -import JasmineTestFramework from '../../src/JasmineTestFramework'; - -describe('index', () => { - it('should export strykerPlugins', () => { - expect(strykerPlugins[0].injectableClass).eq(JasmineTestFramework); - }); -}); diff --git a/packages/jasmine-framework/testResources/json-reporter.js b/packages/jasmine-framework/testResources/json-reporter.js deleted file mode 100644 index d4ea29bdbe..0000000000 --- a/packages/jasmine-framework/testResources/json-reporter.js +++ /dev/null @@ -1,13 +0,0 @@ - -const results = []; -jasmine.getEnv().clearReporters(); -jasmine.getEnv().addReporter({ - - specDone(result) { - results.push(result); - }, - - jasmineDone() { - console.log(JSON.stringify(results)); - } -}); diff --git a/packages/jasmine-framework/testResources/nested-suite.js b/packages/jasmine-framework/testResources/nested-suite.js deleted file mode 100644 index e06943fce1..0000000000 --- a/packages/jasmine-framework/testResources/nested-suite.js +++ /dev/null @@ -1,13 +0,0 @@ -describe('outer', () => { - - it('test 1', () => { - }); - - describe('inner', () => { - it('test 2', () => { - }); - }); - - it('test 3', () => { - }); -}); \ No newline at end of file diff --git a/packages/jasmine-framework/tsconfig.stryker.json b/packages/jasmine-framework/tsconfig.stryker.json deleted file mode 100644 index 0f7ed99680..0000000000 --- a/packages/jasmine-framework/tsconfig.stryker.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": "./tsconfig.test.json", - "include": [ - "src", - "test" - ], -} diff --git a/packages/jasmine-runner/.mocharc.jsonc b/packages/jasmine-runner/.mocharc.jsonc new file mode 100644 index 0000000000..6dab901bfe --- /dev/null +++ b/packages/jasmine-runner/.mocharc.jsonc @@ -0,0 +1,4 @@ +{ + "require": ["test/setup.js"], + "timeout": 30000 +} diff --git a/packages/jasmine-runner/.nycrc.json b/packages/jasmine-runner/.nycrc.json new file mode 100644 index 0000000000..6f8a0db075 --- /dev/null +++ b/packages/jasmine-runner/.nycrc.json @@ -0,0 +1,11 @@ +{ + "exclude-after-remap": false, + "check-coverage": true, + "reporter": ["text", "html"], + "report-dir": "reports/coverage", + "lines": 100, + "functions": 100, + "statements": 100, + "branches": 85, + "include": "src/**/*.js" +} diff --git a/packages/jasmine-runner/.vscode/launch.json b/packages/jasmine-runner/.vscode/launch.json index 570048043d..f26c524cca 100644 --- a/packages/jasmine-runner/.vscode/launch.json +++ b/packages/jasmine-runner/.vscode/launch.json @@ -7,38 +7,21 @@ { "type": "node", "request": "launch", - "name": "Unit tests", + "name": "Unit/integration tests", "program": "${workspaceFolder}/../../node_modules/mocha/bin/_mocha", "args": [ - "--timeout", - "999999", + "--no-timeout", "--colors", - "${workspaceFolder}/test/helpers/**/*.js", - "${workspaceFolder}/test/unit/**/*.js" + "${workspaceRoot}/test/**/*.js" ], "internalConsoleOptions": "openOnSessionStart", "outFiles": [ "${workspaceRoot}/test/**/*.js", "${workspaceRoot}/src/**/*.js" - ] - }, - { - "type": "node", - "request": "launch", - "name": "Integration tests", - "program": "${workspaceFolder}/../../node_modules/mocha/bin/_mocha", - "args": [ - "--timeout", - "999999", - "--colors", - "${workspaceFolder}/test/helpers/**/*.js", - "${workspaceFolder}/test/integration/**/*.js" ], - "internalConsoleOptions": "openOnSessionStart", - "outFiles": [ - "${workspaceRoot}/test/**/*.js", - "${workspaceRoot}/src/**/*.js" + "skipFiles": [ + "/**" ] } ] -} \ No newline at end of file +} diff --git a/packages/jasmine-runner/CHANGELOG.md b/packages/jasmine-runner/CHANGELOG.md index 50de5454cf..f4f12668e4 100644 --- a/packages/jasmine-runner/CHANGELOG.md +++ b/packages/jasmine-runner/CHANGELOG.md @@ -3,6 +3,130 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [4.0.0-beta.10](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.9...v4.0.0-beta.10) (2020-10-05) + +**Note:** Version bump only for package @stryker-mutator/jasmine-runner + + + + + +# [4.0.0-beta.9](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.8...v4.0.0-beta.9) (2020-09-30) + + +### Bug Fixes + +* **config:** deprecate function based config ([#2499](https://github.com/stryker-mutator/stryker/issues/2499)) ([8ea3c18](https://github.com/stryker-mutator/stryker/commit/8ea3c18421929a0724ff99e5bf02ce0f174266cd)) + + +### BREAKING CHANGES + +* **config:** exporting a function from stryker.conf.js is deprecated. Please export your config as an object instead, or use a stryker.conf.json file. + +Co-authored-by: Nico Jansen + + + + + +# [4.0.0-beta.8](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.7...v4.0.0-beta.8) (2020-09-22) + +**Note:** Version bump only for package @stryker-mutator/jasmine-runner + + + + + +# [4.0.0-beta.7](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.6...v4.0.0-beta.7) (2020-09-17) + +**Note:** Version bump only for package @stryker-mutator/jasmine-runner + + + + + +# [4.0.0-beta.6](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.5...v4.0.0-beta.6) (2020-09-10) + +**Note:** Version bump only for package @stryker-mutator/jasmine-runner + + + + + +# [4.0.0-beta.5](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.4...v4.0.0-beta.5) (2020-09-09) + + +### Bug Fixes + +* **jasmine-runner:** fix memory leaks ([457d807](https://github.com/stryker-mutator/stryker/commit/457d807989bd2a69a9e1b7bc33c3971a37c19737)) + + + + + +# [4.0.0-beta.4](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.3...v4.0.0-beta.4) (2020-08-29) + + +### Features + +* **api:** rename test_runner2 -> test_runner ([#2442](https://github.com/stryker-mutator/stryker/issues/2442)) ([4d3ae97](https://github.com/stryker-mutator/stryker/commit/4d3ae9764dbd689c895b76e44f2eea76c82fabc8)) +* **test-runner:** add `nrOfTests` metric ([0eea448](https://github.com/stryker-mutator/stryker/commit/0eea44892e2383e8b0a34c6267e2f455d604f55a)) + + +### BREAKING CHANGES + +* **api:** Plugin creators should now use `'test_runner'` instead of `'test_runner2'`. + + + + + +# [4.0.0-beta.3](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.2...v4.0.0-beta.3) (2020-08-19) + + +### Features + +* **test runner api:** remove `sandboxFileNames` injectable values ([#2369](https://github.com/stryker-mutator/stryker/issues/2369)) ([92f3bf5](https://github.com/stryker-mutator/stryker/commit/92f3bf528d0b01be1f6c219b37a5f90da0431686)), closes [#2351](https://github.com/stryker-mutator/stryker/issues/2351) + + + + + +# [4.0.0-beta.2](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.1...v4.0.0-beta.2) (2020-08-07) + + +### Features + +* **jest-runner:** support mutation switching ([#2350](https://github.com/stryker-mutator/stryker/issues/2350)) ([9e6e6e0](https://github.com/stryker-mutator/stryker/commit/9e6e6e077731344ed0588d64b5c8ba2f19c8492e)) + + + + + +# [4.0.0-beta.1](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.0...v4.0.0-beta.1) (2020-07-17) + +**Note:** Version bump only for package @stryker-mutator/jasmine-runner + + + + + +# [4.0.0-beta.0](https://github.com/stryker-mutator/stryker/compare/v3.3.1...v4.0.0-beta.0) (2020-07-10) + + +### Bug Fixes + +* **jasmine-runner:** update deprecated api calls ([#2250](https://github.com/stryker-mutator/stryker/issues/2250)) ([b6d6dfd](https://github.com/stryker-mutator/stryker/commit/b6d6dfdabf8db748660b9818415864de27d55a7f)) + + +### Features + +* **jasmine-runner:** implement new test runner api ([#2256](https://github.com/stryker-mutator/stryker/issues/2256)) ([871db8c](https://github.com/stryker-mutator/stryker/commit/871db8c24c3389133d9b4476acd33b0ddd956a36)), closes [#2249](https://github.com/stryker-mutator/stryker/issues/2249) + + + + + ## [3.3.1](https://github.com/stryker-mutator/stryker/compare/v3.3.0...v3.3.1) (2020-07-04) **Note:** Version bump only for package @stryker-mutator/jasmine-runner diff --git a/packages/jasmine-runner/package.json b/packages/jasmine-runner/package.json index e19859506f..8fe0a20070 100644 --- a/packages/jasmine-runner/package.json +++ b/packages/jasmine-runner/package.json @@ -1,11 +1,11 @@ { "name": "@stryker-mutator/jasmine-runner", - "version": "3.3.1", + "version": "4.0.0-beta.10", "description": "A plugin to use the Jasmine (NodeJS) test runner in Stryker, the mutation testing framework for JavaScript and friends", "main": "src/index.js", "scripts": { - "test": "nyc --exclude-after-remap=false --check-coverage --reporter=html --report-dir=reports/coverage --lines 100 --functions 100 --branches 85 npm run mocha", - "mocha": "mocha \"test/helpers/**/*.js\" \"test/unit/**/*.js\" \"test/integration/**/*.js\"", + "test": "nyc npm run test:all", + "test:all": "mocha \"test/**/*.js\"", "stryker": "node ../core/bin/stryker run" }, "nyc": { @@ -36,17 +36,16 @@ }, "homepage": "https://github.com/stryker-mutator/stryker/tree/master/packages/jasmine-runner#readme", "peerDependencies": { - "@stryker-mutator/core": "^3.0.0", + "@stryker-mutator/core": "~4.0.0", "jasmine": ">=2" }, "devDependencies": { - "@stryker-mutator/jasmine-framework": "^3.3.1", - "@stryker-mutator/test-helpers": "^3.3.1", + "@stryker-mutator/test-helpers": "4.0.0-beta.10", "@types/node": "^14.0.1" }, "dependencies": { - "@stryker-mutator/api": "^3.3.1", - "@stryker-mutator/util": "^3.3.1" + "@stryker-mutator/api": "4.0.0-beta.10", + "@stryker-mutator/util": "4.0.0-beta.10" }, "initStrykerConfig": { "jasmineConfigFile": "spec/support/jasmine.json" diff --git a/packages/jasmine-runner/src/JasmineTestRunner.ts b/packages/jasmine-runner/src/JasmineTestRunner.ts index b4a0c16cbc..62fe015469 100644 --- a/packages/jasmine-runner/src/JasmineTestRunner.ts +++ b/packages/jasmine-runner/src/JasmineTestRunner.ts @@ -1,75 +1,135 @@ import { EOL } from 'os'; -import { StrykerOptions } from '@stryker-mutator/api/core'; -import { commonTokens, tokens } from '@stryker-mutator/api/plugin'; -import { RunResult, RunStatus, TestResult, TestRunner } from '@stryker-mutator/api/test_runner'; -import { errorToString } from '@stryker-mutator/util'; +import { StrykerOptions, CoverageAnalysis, InstrumenterContext, MutantCoverage, INSTRUMENTER_CONSTANTS } from '@stryker-mutator/api/core'; +import { commonTokens, tokens, Injector, PluginContext } from '@stryker-mutator/api/plugin'; +import { + DryRunStatus, + TestResult, + TestRunner, + MutantRunOptions, + DryRunResult, + MutantRunResult, + toMutantRunResult, + ErrorDryRunResult, + DryRunOptions, +} from '@stryker-mutator/api/test_runner'; +import { errorToString, Task, DirectoryRequireCache, I } from '@stryker-mutator/util'; import { JasmineRunnerOptions } from '../src-generated/jasmine-runner-options'; -import { evalGlobal, Jasmine, toStrykerTestResult } from './helpers'; +import { Jasmine, toStrykerTestResult } from './helpers'; +import * as pluginTokens from './pluginTokens'; -export default class JasmineTestRunner implements TestRunner { +export function createJasmineTestRunnerFactory( + namespace: typeof INSTRUMENTER_CONSTANTS.NAMESPACE | '__stryker2__' = INSTRUMENTER_CONSTANTS.NAMESPACE +) { + createJasmineTestRunner.inject = tokens(commonTokens.injector); + function createJasmineTestRunner(injector: Injector) { + return injector + .provideClass(pluginTokens.directoryRequireCache, DirectoryRequireCache) + .provideValue(pluginTokens.globalNamespace, namespace) + .injectClass(JasmineTestRunner); + } + return createJasmineTestRunner; +} + +export const createJasmineTestRunner = createJasmineTestRunnerFactory(); + +export class JasmineTestRunner implements TestRunner { private readonly jasmineConfigFile: string | undefined; private readonly Date: typeof Date = Date; // take Date prototype now we still can (user might choose to mock it away) + private readonly instrumenterContext: InstrumenterContext; - public static inject = tokens(commonTokens.sandboxFileNames, commonTokens.options); - constructor(private readonly fileNames: readonly string[], options: StrykerOptions) { + public static inject = tokens(commonTokens.options, pluginTokens.directoryRequireCache, pluginTokens.globalNamespace); + constructor( + options: StrykerOptions, + private readonly requireCache: I, + globalNamespace: typeof INSTRUMENTER_CONSTANTS.NAMESPACE | '__stryker2__' + ) { this.jasmineConfigFile = (options as JasmineRunnerOptions).jasmineConfigFile; + this.instrumenterContext = global[globalNamespace] || (global[globalNamespace] = {}); } - public run(options: { testHooks?: string }): Promise { - this.clearRequireCache(); - const tests: TestResult[] = []; - let startTimeCurrentSpec = 0; - const jasmine = this.createJasmineRunner(); - const self = this; - if (options.testHooks) { - evalGlobal(options.testHooks); - } - return new Promise((resolve) => { + public dryRun(options: DryRunOptions): Promise { + return this.run(undefined, options.coverageAnalysis); + } + + public async mutantRun(options: MutantRunOptions): Promise { + this.instrumenterContext.activeMutant = options.activeMutant.id; + const runResult = await this.run(options.testFilter); + return toMutantRunResult(runResult); + } + + public async init(): Promise { + this.requireCache.init({ rootModuleId: require.resolve('jasmine'), initFiles: [] }); + } + + public async dispose(): Promise { + this.requireCache.clear(); + } + + private async run(testFilter?: string[], coverageAnalysis?: CoverageAnalysis): Promise { + this.requireCache.clear(); + try { + const jasmine = this.createJasmineRunner(testFilter); + const self = this; + const tests: TestResult[] = []; + const runTask = new Task(); + let startTimeCurrentSpec = 0; const reporter: jasmine.CustomReporter = { - specStarted() { + specStarted(spec) { + if (coverageAnalysis && coverageAnalysis === 'perTest') { + self.instrumenterContext.currentTestId = spec.id; + } startTimeCurrentSpec = new self.Date().getTime(); }, - specDone(result: jasmine.CustomReporterResult) { tests.push(toStrykerTestResult(result, new self.Date().getTime() - startTimeCurrentSpec)); }, - jasmineDone() { - resolve({ - errorMessages: [], - status: RunStatus.Complete, + self.requireCache.record(); + let mutantCoverage: MutantCoverage | undefined = undefined; + if (coverageAnalysis === 'all' || coverageAnalysis === 'perTest') { + mutantCoverage = self.instrumenterContext.mutantCoverage; + } + runTask.resolve({ + status: DryRunStatus.Complete, tests, + mutantCoverage, }); }, }; - jasmine.addReporter(reporter); + + jasmine.env.addReporter(reporter); jasmine.execute(); - }).catch((error) => ({ - errorMessages: [`An error occurred while loading your jasmine specs${EOL}${errorToString(error)}`], - status: RunStatus.Error, - tests: [], - })); + const result = await runTask.promise; + return result; + } catch (error) { + const errorResult: ErrorDryRunResult = { + errorMessage: `An error occurred while loading your jasmine specs${EOL}${errorToString(error)}`, + status: DryRunStatus.Error, + }; + return errorResult; + } } - private createJasmineRunner() { + private createJasmineRunner(testFilter: undefined | string[]) { + let specFilter: undefined | ((spec: jasmine.Spec) => boolean) = undefined; + if (testFilter) { + specFilter = (spec) => testFilter.includes(spec.id.toString()); + } const jasmine = new Jasmine({ projectBaseDir: process.cwd() }); // The `loadConfigFile` will fallback on the default jasmine.loadConfigFile(this.jasmineConfigFile); - jasmine.stopSpecOnExpectationFailure(true); - jasmine.env.throwOnExpectationFailure(true); + jasmine.env.configure({ + failFast: true, + oneFailurePerSpec: true, + specFilter, + }); jasmine.exit = () => {}; - jasmine.clearReporters(); + jasmine.env.clearReporters(); jasmine.randomizeTests(false); return jasmine; } - - public clearRequireCache() { - this.fileNames.forEach((fileName) => { - delete require.cache[fileName]; - }); - } } diff --git a/packages/jasmine-runner/src/helpers.ts b/packages/jasmine-runner/src/helpers.ts index 0c09ff6dbe..bafa6b06d1 100644 --- a/packages/jasmine-runner/src/helpers.ts +++ b/packages/jasmine-runner/src/helpers.ts @@ -3,26 +3,28 @@ import { TestResult, TestStatus } from '@stryker-mutator/api/test_runner'; import JasmineConstructor = require('jasmine'); export function toStrykerTestResult(specResult: jasmine.CustomReporterResult, timeSpentMs: number): TestResult { - let status = TestStatus.Failed; - let failureMessages: string[] | undefined; + const baseResult = { + id: specResult.id.toString(), + name: specResult.fullName, + timeSpentMs, + }; if (specResult.status === 'disabled' || specResult.status === 'pending' || specResult.status === 'excluded') { - status = TestStatus.Skipped; + return { + ...baseResult, + status: TestStatus.Skipped, + }; } else if (!specResult.failedExpectations || specResult.failedExpectations.length === 0) { - status = TestStatus.Success; + return { + ...baseResult, + status: TestStatus.Success, + }; } else { - failureMessages = specResult.failedExpectations.map((failedExpectation) => failedExpectation.message); + return { + ...baseResult, + status: TestStatus.Failed, + failureMessage: specResult.failedExpectations.map((failedExpectation) => failedExpectation.message).join(','), + }; } - return { - failureMessages, - name: specResult.fullName, - status, - timeSpentMs, - }; -} - -export function evalGlobal(body: string) { - const fn = new Function('require', body); - fn(require); } export const Jasmine = JasmineConstructor; diff --git a/packages/jasmine-runner/src/index.ts b/packages/jasmine-runner/src/index.ts index 2cd31c9afb..10159abf03 100644 --- a/packages/jasmine-runner/src/index.ts +++ b/packages/jasmine-runner/src/index.ts @@ -1,9 +1,9 @@ -import { declareClassPlugin, PluginKind } from '@stryker-mutator/api/plugin'; +import { declareFactoryPlugin, PluginKind } from '@stryker-mutator/api/plugin'; import * as strykerValidationSchema from '../schema/jasmine-runner-options.json'; -import JasmineTestRunner from './JasmineTestRunner'; +import { JasmineTestRunner, createJasmineTestRunner, createJasmineTestRunnerFactory } from './JasmineTestRunner'; -export const strykerPlugins = [declareClassPlugin(PluginKind.TestRunner, 'jasmine', JasmineTestRunner)]; +export const strykerPlugins = [declareFactoryPlugin(PluginKind.TestRunner, 'jasmine', createJasmineTestRunner)]; -export { strykerValidationSchema }; +export { strykerValidationSchema, JasmineTestRunner, createJasmineTestRunnerFactory }; diff --git a/packages/jasmine-runner/src/pluginTokens.ts b/packages/jasmine-runner/src/pluginTokens.ts new file mode 100644 index 0000000000..dc27e151a7 --- /dev/null +++ b/packages/jasmine-runner/src/pluginTokens.ts @@ -0,0 +1,2 @@ +export const directoryRequireCache = 'directoryRequireCache'; +export const globalNamespace = 'globalNamespace'; diff --git a/packages/jasmine-runner/stryker.conf.js b/packages/jasmine-runner/stryker.conf.js index 5f801069f7..522cbc6cf6 100644 --- a/packages/jasmine-runner/stryker.conf.js +++ b/packages/jasmine-runner/stryker.conf.js @@ -1,6 +1,8 @@ const path = require('path'); const settings = require('../../stryker.parent.conf'); const moduleName = __dirname.split(path.sep).pop(); +settings.plugins = settings.plugins.map(p => path.resolve(p)); settings.dashboard.module = moduleName; -settings.coverageAnalysis = 'off'; +settings.files = ['{src-generated,src,test,schema,testResources,typings}/**/*.{ts,json}', '*.{ts,json}']; +settings.mutate = ['src/**/!(*d).ts']; module.exports = settings; diff --git a/packages/jasmine-runner/test/helpers/assertions.ts b/packages/jasmine-runner/test/helpers/assertions.ts index f54e783082..94388e033a 100644 --- a/packages/jasmine-runner/test/helpers/assertions.ts +++ b/packages/jasmine-runner/test/helpers/assertions.ts @@ -1,10 +1,9 @@ -import { TestResult, TestStatus } from '@stryker-mutator/api/test_runner'; +import { TestResult, SuccessTestResult, FailedTestResult, SkippedTestResult } from '@stryker-mutator/api/test_runner'; import { expect } from 'chai'; -export function expectTestResultsToEqual( - actualTestResults: TestResult[], - expectedResults: ReadonlyArray<{ name: string; status: TestStatus; failureMessages: string[] | undefined }> -) { +type TimelessTestResult = Omit | Omit | Omit; + +export function expectTestResultsToEqual(actualTestResults: TestResult[], expectedResults: readonly TimelessTestResult[]) { expect(actualTestResults).lengthOf( expectedResults.length, `Expected ${JSON.stringify(actualTestResults, null, 2)} to equal ${JSON.stringify(expectedResults, null, 2)}` @@ -12,9 +11,8 @@ export function expectTestResultsToEqual( expectedResults.forEach((expectedResult) => { const actualTestResult = actualTestResults.find((testResult) => testResult.name === expectedResult.name); if (actualTestResult) { - expect({ name: actualTestResult.name, status: actualTestResult.status, failureMessages: actualTestResult.failureMessages }).deep.equal( - expectedResult - ); + const { timeSpentMs, ...actualWithoutTiming } = actualTestResult; + expect(actualWithoutTiming).deep.equal(expectedResult); } else { expect.fail( undefined, diff --git a/packages/jasmine-runner/test/helpers/global.ts b/packages/jasmine-runner/test/helpers/global.ts new file mode 100644 index 0000000000..07e688a1a7 --- /dev/null +++ b/packages/jasmine-runner/test/helpers/global.ts @@ -0,0 +1,5 @@ +declare namespace NodeJS { + interface Global { + __testsInCurrentJasmineRun: string[]; + } +} diff --git a/packages/jasmine-runner/test/helpers/initChai.ts b/packages/jasmine-runner/test/helpers/initChai.ts deleted file mode 100644 index 514154da42..0000000000 --- a/packages/jasmine-runner/test/helpers/initChai.ts +++ /dev/null @@ -1,6 +0,0 @@ -import * as chai from 'chai'; -import * as chaiAsPromised from 'chai-as-promised'; -import * as sinonChai from 'sinon-chai'; - -chai.use(sinonChai); -chai.use(chaiAsPromised); diff --git a/packages/jasmine-runner/test/helpers/initSinon.ts b/packages/jasmine-runner/test/helpers/initSinon.ts deleted file mode 100644 index 5d2a1383b2..0000000000 --- a/packages/jasmine-runner/test/helpers/initSinon.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { testInjector } from '@stryker-mutator/test-helpers'; -import * as sinon from 'sinon'; - -afterEach(() => { - sinon.reset(); - testInjector.reset(); -}); diff --git a/packages/jasmine-runner/test/helpers/initSourceMaps.ts b/packages/jasmine-runner/test/helpers/initSourceMaps.ts deleted file mode 100644 index fcfbfda16c..0000000000 --- a/packages/jasmine-runner/test/helpers/initSourceMaps.ts +++ /dev/null @@ -1 +0,0 @@ -import 'source-map-support/register'; diff --git a/packages/jasmine-runner/test/helpers/mockFactories.ts b/packages/jasmine-runner/test/helpers/mockFactories.ts new file mode 100644 index 0000000000..eda3dd7039 --- /dev/null +++ b/packages/jasmine-runner/test/helpers/mockFactories.ts @@ -0,0 +1,59 @@ +import sinon = require('sinon'); + +export function createRunDetails(): jasmine.RunDetails { + return { + failedExpectations: [], + order: { + random: false, + seed: '12foo', + sort: (_) => _, + } as jasmine.Order, + }; +} + +export function createCustomReporterResult(overrides?: Partial): jasmine.CustomReporterResult { + return { + description: 'should have bar', + fullName: 'Foo should have bar', + id: 'spec0', + ...overrides, + }; +} + +export function createEnvStub(): sinon.SinonStubbedInstance { + return { + currentSpec: sinon.stub(), + matchersClass: sinon.stub(), + version: sinon.stub(), + versionString: sinon.stub(), + nextSpecId: sinon.stub(), + addReporter: sinon.stub(), + execute: sinon.stub(), + describe: sinon.stub(), + beforeEach: sinon.stub(), + beforeAll: sinon.stub(), + currentRunner: sinon.stub(), + afterEach: sinon.stub(), + afterAll: sinon.stub(), + xdescribe: sinon.stub(), + it: sinon.stub(), + xit: sinon.stub(), + compareRegExps_: sinon.stub(), + compareObjects_: sinon.stub(), + equals_: sinon.stub(), + contains_: sinon.stub(), + addCustomEqualityTester: sinon.stub(), + addMatchers: sinon.stub(), + specFilter: sinon.stub(), + throwOnExpectationFailure: sinon.stub(), + stopOnSpecFailure: sinon.stub(), + seed: sinon.stub(), + provideFallbackReporter: sinon.stub(), + throwingExpectationFailures: sinon.stub(), + allowRespy: sinon.stub(), + randomTests: sinon.stub(), + randomizeTests: sinon.stub(), + clearReporters: sinon.stub(), + configure: sinon.stub(), + }; +} diff --git a/packages/jasmine-runner/test/integration/JasmineRunner.it.spec.ts b/packages/jasmine-runner/test/integration/JasmineRunner.it.spec.ts index 81488f6e83..1584dba64c 100644 --- a/packages/jasmine-runner/test/integration/JasmineRunner.it.spec.ts +++ b/packages/jasmine-runner/test/integration/JasmineRunner.it.spec.ts @@ -1,187 +1,121 @@ import * as path from 'path'; -import { RunStatus, TestResult, TestStatus } from '@stryker-mutator/api/test_runner'; -import JasmineTestFramework from '@stryker-mutator/jasmine-framework/src/JasmineTestFramework'; -import { factory } from '@stryker-mutator/test-helpers'; +import { factory, assertions, testInjector } from '@stryker-mutator/test-helpers'; import { expect } from 'chai'; +import { TestStatus } from '@stryker-mutator/api/test_runner'; -import JasmineTestRunner from '../../src/JasmineTestRunner'; +import { JasmineTestRunner, createJasmineTestRunnerFactory } from '../../src/JasmineTestRunner'; import { expectTestResultsToEqual } from '../helpers/assertions'; -function wrapInClosure(codeFragment: string) { - return ` - (function (window) { - ${codeFragment} - })((Function('return this'))());`; -} +import { jasmineInitSuccessResults } from './helpers'; describe('JasmineRunner integration', () => { let sut: JasmineTestRunner; - afterEach(() => { + + afterEach(async () => { process.chdir(path.resolve(__dirname, '../../..')); + await sut.dispose(); }); describe('using the jasmine-init project', () => { - const expectedJasmineInitResults = Object.freeze([ - Object.freeze({ - failureMessages: undefined, - name: 'Player should be able to play a Song', - status: TestStatus.Success, - }), - Object.freeze({ - failureMessages: undefined, - name: 'Player when song has been paused should indicate that the song is currently paused', - status: TestStatus.Success, - }), - Object.freeze({ - failureMessages: undefined, - name: 'Player when song has been paused should be possible to resume', - status: TestStatus.Success, - }), - Object.freeze({ - failureMessages: undefined, - name: 'Player tells the current song if the user has made it a favorite', - status: TestStatus.Success, - }), - Object.freeze({ - failureMessages: undefined, - name: 'Player #resume should throw an exception if song is already playing', - status: TestStatus.Success, - }), - ]); - - beforeEach(() => { + beforeEach(async () => { process.chdir(path.resolve(__dirname, '../../testResources/jasmine-init')); - sut = new JasmineTestRunner( - [ - path.resolve('lib', 'jasmine_examples', 'Player.js'), - path.resolve('lib', 'jasmine_examples', 'Song.js'), - path.resolve('spec', 'helpers', 'jasmine_examples', 'SpecHelper.js'), - path.resolve('spec', 'jasmine_examples', 'PlayerSpec.js'), - ], - factory.strykerOptions({ jasmineConfigFile: 'spec/support/jasmine.json' }) - ); + testInjector.options.jasmineConfigFile = 'spec/support/jasmine.json'; + sut = testInjector.injector.injectFunction(createJasmineTestRunnerFactory('__stryker2__')); + await sut.init(); }); + it('should run the specs', async () => { - const runResult = await sut.run({}); - expect(runResult.status).eq(RunStatus.Complete); - expectTestResultsToEqual(runResult.tests, expectedJasmineInitResults); + const runResult = await sut.dryRun(factory.dryRunOptions()); + assertions.expectCompleted(runResult); + expectTestResultsToEqual(runResult.tests, jasmineInitSuccessResults); }); it('should be able to run twice in short succession', async () => { - await sut.run({}); - const secondRunResult = await sut.run({}); - expect(secondRunResult.status).eq(RunStatus.Complete); - expectTestResultsToEqual(secondRunResult.tests, expectedJasmineInitResults); + await sut.dryRun(factory.dryRunOptions()); + const secondRunResult = await sut.dryRun(factory.dryRunOptions()); + assertions.expectCompleted(secondRunResult); + expectTestResultsToEqual(secondRunResult.tests, jasmineInitSuccessResults); }); it('should be able to filter tests', async () => { // Arrange - const testFramework = new JasmineTestFramework(); - const testHooks = wrapInClosure( - testFramework.filter([ - { - id: 1, - name: expectedJasmineInitResults[1].name, - }, - { - id: 3, - name: expectedJasmineInitResults[3].name, - }, - ]) - ); + const jasmineInitResults = jasmineInitSuccessResults; + const testFilter = [jasmineInitResults[1].id, jasmineInitResults[3].id]; // Act - const runResult = await sut.run({ testHooks }); + const runResult = await sut.mutantRun(factory.mutantRunOptions({ testFilter })); // Assert - expect(runResult.status).eq(RunStatus.Complete); - expectTestsFiltered(runResult.tests, 1, 3); + assertions.expectSurvived(runResult); + expect(global.__testsInCurrentJasmineRun).deep.eq(['spec1', 'spec3']); }); it('should be able to clear the filter after a filtered run', async () => { // Arrange - const testFramework = new JasmineTestFramework(); - const filter1Test = wrapInClosure(testFramework.filter([{ id: 1, name: expectedJasmineInitResults[1].name }])); - const filterNoTests = wrapInClosure(testFramework.filter([])); + const jasmineInitResults = jasmineInitSuccessResults; + const filter1Test = [jasmineInitResults[1].id]; + const filterNoTests = undefined; + + // Act + await sut.mutantRun(factory.mutantRunOptions({ testFilter: filter1Test })); + global.__testsInCurrentJasmineRun = []; + await sut.mutantRun(factory.mutantRunOptions({ testFilter: filterNoTests })); - await sut.run({ testHooks: filter1Test }); - const actualResult = await sut.run({ testHooks: filterNoTests }); - expectTestResultsToEqual(actualResult.tests, expectedJasmineInitResults); + // Assert + expect(global.__testsInCurrentJasmineRun).deep.eq(['spec0', 'spec1', 'spec2', 'spec3', 'spec4']); }); it('should be able to filter tests in quick succession', async () => { // Arrange - const testFramework = new JasmineTestFramework(); - const testHooks1 = wrapInClosure( - testFramework.filter([ - { - id: 1, - name: expectedJasmineInitResults[1].name, - }, - ]) - ); - const testHooks2 = wrapInClosure( - testFramework.filter([ - { - id: 2, - name: expectedJasmineInitResults[2].name, - }, - ]) - ); + const testHooks1 = [jasmineInitSuccessResults[1].id]; + const testHooks2 = [jasmineInitSuccessResults[2].id]; // Act - const firstResult = await sut.run({ testHooks: testHooks1 }); - const secondResult = await sut.run({ testHooks: testHooks2 }); + await sut.mutantRun(factory.mutantRunOptions({ testFilter: testHooks1 })); + const testsRunFirstTime = global.__testsInCurrentJasmineRun; + global.__testsInCurrentJasmineRun = []; + await sut.mutantRun(factory.mutantRunOptions({ testFilter: testHooks2 })); + const testsRunSecondTime = global.__testsInCurrentJasmineRun; // Assert - expectTestsFiltered(firstResult.tests, 1); - expectTestsFiltered(secondResult.tests, 2); + expect(testsRunFirstTime).deep.eq(['spec1']); + expect(testsRunSecondTime).deep.eq(['spec2']); }); - - function expectTestsFiltered(actualTestResults: TestResult[], ...filteredTestIds: number[]) { - expectTestResultsToEqual( - actualTestResults, - expectedJasmineInitResults.map((testResult, id) => ({ - failureMessages: testResult.failureMessages, - name: testResult.name, - status: filteredTestIds.includes(id) ? TestStatus.Success : TestStatus.Skipped, - })) - ); - } }); describe('using a jasmine-project with errors', () => { - beforeEach(() => { + beforeEach(async () => { process.chdir(path.resolve(__dirname, '../../testResources/errors')); - sut = new JasmineTestRunner([path.resolve('lib', 'error.js'), path.resolve('spec', 'errorSpec.js')], factory.strykerOptions()); + sut = testInjector.injector.injectFunction(createJasmineTestRunnerFactory('__stryker2__')); + await sut.init(); }); it('should be able to tell the error', async () => { - const result = await sut.run({}); - expect(result.status).eq(RunStatus.Error); - expect(result.errorMessages).lengthOf(1); - const actualError: string = (result.errorMessages as string[])[0]; - expect(actualError) + const result = await sut.dryRun(factory.dryRunOptions()); + assertions.expectErrored(result); + expect(result.errorMessage) .matches(/^An error occurred while loading your jasmine specs.*/) .matches(/.*SyntaxError: Unexpected identifier.*/); }); }); describe('when it includes failed tests', () => { - beforeEach(() => { + beforeEach(async () => { process.chdir(path.resolve(__dirname, '../../testResources/test-failures')); - sut = new JasmineTestRunner([path.resolve('lib', 'foo.js'), path.resolve('spec', 'fooSpec.js')], factory.strykerOptions()); + sut = testInjector.injector.injectFunction(createJasmineTestRunnerFactory('__stryker2__')); + await sut.init(); }); it('should complete with one test failure', async () => { - const result = await sut.run({}); - expect(result.status).eq(RunStatus.Complete); + const result = await sut.dryRun(factory.dryRunOptions()); + assertions.expectCompleted(result); expectTestResultsToEqual(result.tests, [ { - failureMessages: ["Expected 'bar' to be 'baz'."], - name: 'foo should be baz', + id: 'spec0', status: TestStatus.Failed, + failureMessage: "Expected 'bar' to be 'baz'.", + name: 'foo should be baz', }, ]); }); diff --git a/packages/jasmine-runner/test/integration/MemoryLeak.it.spec.ts b/packages/jasmine-runner/test/integration/MemoryLeak.it.spec.ts new file mode 100644 index 0000000000..dcd6318dca --- /dev/null +++ b/packages/jasmine-runner/test/integration/MemoryLeak.it.spec.ts @@ -0,0 +1,18 @@ +import path = require('path'); + +import execa = require('execa'); + +import { expect } from 'chai'; + +import { JasmineTestRunner } from '../../src'; + +describe(JasmineTestRunner.name, () => { + it('should not leak memory when running multiple times (#2461)', async () => { + const childProcess = await execa.node(path.resolve(__dirname, 'MemoryLeak.worker.js'), [], { + stdio: 'pipe', + nodeOptions: ['--max-old-space-size=32', '--max-semi-space-size=1'], + }); + expect(childProcess.exitCode).eq(0); + expect(childProcess.stdout).contains('Iterator count 1'); + }); +}); diff --git a/packages/jasmine-runner/test/integration/MemoryLeak.worker.ts b/packages/jasmine-runner/test/integration/MemoryLeak.worker.ts new file mode 100644 index 0000000000..670185b851 --- /dev/null +++ b/packages/jasmine-runner/test/integration/MemoryLeak.worker.ts @@ -0,0 +1,44 @@ +import path = require('path'); + +import { testInjector } from '@stryker-mutator/test-helpers'; + +import { expect } from 'chai'; +import { DryRunStatus, TestStatus } from '@stryker-mutator/api/test_runner'; + +import { createJasmineTestRunnerFactory } from '../../src'; + +/** + * This file will run the mocha runner a number of times in a test suite that is designed + * to result in an OutOfMemory error when the mocha test runner does not clean it's memory + * Start this process with `--max-old-space-size=32 --max-semi-space-size=1` to get a fast OutOfMemory error (if there is a memory leak) + * + * @see https://github.com/stryker-mutator/stryker/issues/2461 + * @see https://nodejs.org/api/modules.html#modules_accessing_the_main_module + * @see https://stackoverflow.com/questions/30252905/nodejs-decrease-v8-garbage-collector-memory-usage + */ + +if (require.main === module) { + main().catch((err) => { + console.error(err); + process.exitCode = 1; + }); +} + +async function main() { + process.chdir(path.resolve(__dirname, '..', '..', 'testResources', 'big-project')); + const jasmineRunner = testInjector.injector.injectFunction(createJasmineTestRunnerFactory('__stryker2__')); + await jasmineRunner.init(); + await doDryRun(); + + async function doDryRun(n = 20) { + if (n > 0) { + console.log(`Iterator count ${n}`); + const result = await jasmineRunner.dryRun({ coverageAnalysis: 'off', timeout: 3000 }); + if (result.status === DryRunStatus.Complete) { + expect(result.tests).lengthOf(1); + expect(result.tests[0].status).eq(TestStatus.Success); + } + await doDryRun(n - 1); + } + } +} diff --git a/packages/jasmine-runner/test/integration/helpers.ts b/packages/jasmine-runner/test/integration/helpers.ts new file mode 100644 index 0000000000..52681b4c7d --- /dev/null +++ b/packages/jasmine-runner/test/integration/helpers.ts @@ -0,0 +1,17 @@ +import { TestStatus, SuccessTestResult } from '@stryker-mutator/api/test_runner'; + +export const jasmineInitResultTestNames = Object.freeze([ + 'Player should be able to play a Song', + 'Player when song has been paused should indicate that the song is currently paused', + 'Player when song has been paused should be possible to resume', + 'Player tells the current song if the user has made it a favorite', + 'Player #resume should throw an exception if song is already playing', +]); + +export const jasmineInitSuccessResults: ReadonlyArray> = Object.freeze([ + { id: 'spec0', name: jasmineInitResultTestNames[0], status: TestStatus.Success }, + { id: 'spec1', name: jasmineInitResultTestNames[1], status: TestStatus.Success }, + { id: 'spec2', name: jasmineInitResultTestNames[2], status: TestStatus.Success }, + { id: 'spec3', name: jasmineInitResultTestNames[3], status: TestStatus.Success }, + { id: 'spec4', name: jasmineInitResultTestNames[4], status: TestStatus.Success }, +]); diff --git a/packages/jasmine-runner/test/integration/jasmine-init-instrumented.it.spec.ts b/packages/jasmine-runner/test/integration/jasmine-init-instrumented.it.spec.ts new file mode 100644 index 0000000000..10fa906fef --- /dev/null +++ b/packages/jasmine-runner/test/integration/jasmine-init-instrumented.it.spec.ts @@ -0,0 +1,71 @@ +import path = require('path'); + +import { factory, testInjector } from '@stryker-mutator/test-helpers'; +import { expect } from 'chai'; +import { MutantRunStatus } from '@stryker-mutator/api/test_runner'; +import { assertions } from '@stryker-mutator/test-helpers'; + +import { JasmineTestRunner, createJasmineTestRunnerFactory } from '../../src'; + +describe('JasmineRunner integration with code instrumentation', () => { + let sut: JasmineTestRunner; + + beforeEach(() => { + process.chdir(path.resolve(__dirname, '../../testResources/jasmine-init-instrumented')); + sut = testInjector.injector.injectFunction(createJasmineTestRunnerFactory('__stryker2__')); + }); + + afterEach(async () => { + await sut.dispose(); + }); + + describe('dryRun', () => { + it('should not report coverage when coverageAnalysis is "off"', async () => { + const result = await sut.dryRun(factory.dryRunOptions({ coverageAnalysis: 'off' })); + assertions.expectCompleted(result); + expect(result.mutantCoverage).undefined; + }); + + it('should report static coverage when coverageAnalysis is "all"', async () => { + const result = await sut.dryRun(factory.dryRunOptions({ coverageAnalysis: 'all' })); + assertions.expectCompleted(result); + expect(result.mutantCoverage).not.undefined; + expect(Object.keys(result.mutantCoverage!.perTest).length).eq(0); + expect(Object.keys(result.mutantCoverage!.static).length).eq(13); + }); + + it('should report static and perTest coverage when coverageAnalysis is "perTest"', async () => { + const result = await sut.dryRun(factory.dryRunOptions({ coverageAnalysis: 'perTest' })); + assertions.expectCompleted(result); + expect(result.mutantCoverage).not.undefined; + expect(Object.keys(result.mutantCoverage!.perTest).length).eq(5); // 5 tests + expect(Object.keys(result.mutantCoverage!.static).length).eq(1); // 1 static mutant + }); + }); + + describe('mutantRun', () => { + it('should be able to kill a mutant', async () => { + const result = await sut.mutantRun(factory.mutantRunOptions({ activeMutant: factory.mutant({ id: 1 }) })); + assertions.expectKilled(result); + expect(result.killedBy).eq('spec0'); + expect(result.failureMessage).eq('Expected Player({ currentlyPlayingSong: Song({ }), isPlaying: false }) to be playing Song({ }).'); + }); + + it('should be able report "survive" when a mutant is invincible', async () => { + const result = await sut.mutantRun(factory.mutantRunOptions({ activeMutant: factory.mutant({ id: 12 }) })); + assertions.expectSurvived(result); + }); + + it('should be able to kill again after a mutant survived', async () => { + await sut.mutantRun(factory.mutantRunOptions({ activeMutant: factory.mutant({ id: 12 }) })); + const result = await sut.mutantRun(factory.mutantRunOptions({ activeMutant: factory.mutant({ id: 2 }) })); + const expected = factory.killedMutantRunResult({ + killedBy: 'spec1', + status: MutantRunStatus.Killed, + failureMessage: 'Expected true to be falsy.', + nrOfTests: 2, // spec0 and spec1 + }); + expect(result).deep.eq(expected); + }); + }); +}); diff --git a/packages/jasmine-runner/test/setup.ts b/packages/jasmine-runner/test/setup.ts new file mode 100644 index 0000000000..200cf7c7c7 --- /dev/null +++ b/packages/jasmine-runner/test/setup.ts @@ -0,0 +1,21 @@ +import 'source-map-support/register'; +import * as chai from 'chai'; +import * as chaiAsPromised from 'chai-as-promised'; +import * as sinonChai from 'sinon-chai'; +import { testInjector } from '@stryker-mutator/test-helpers'; +import * as sinon from 'sinon'; + +chai.use(sinonChai); +chai.use(chaiAsPromised); + +export const mochaHooks = { + afterEach() { + delete global.__stryker2__?.activeMutant; + delete global.__stryker2__?.currentTestId; + delete global.__stryker2__?.mutantCoverage; + global.__testsInCurrentJasmineRun = []; + + sinon.restore(); + testInjector.reset(); + }, +}; diff --git a/packages/jasmine-runner/test/unit/JasmineTestRunner.spec.ts b/packages/jasmine-runner/test/unit/JasmineTestRunner.spec.ts index 9c7e2bda9b..c31e69c63c 100644 --- a/packages/jasmine-runner/test/unit/JasmineTestRunner.spec.ts +++ b/packages/jasmine-runner/test/unit/JasmineTestRunner.spec.ts @@ -1,132 +1,247 @@ -import { RunStatus, TestResult, TestStatus } from '@stryker-mutator/api/test_runner'; -import { factory } from '@stryker-mutator/test-helpers'; -import { expect } from 'chai'; import * as sinon from 'sinon'; - +import { expect } from 'chai'; +import { factory, assertions, testInjector } from '@stryker-mutator/test-helpers'; +import { TestStatus, CompleteDryRunResult, DryRunStatus } from '@stryker-mutator/api/test_runner'; import Jasmine = require('jasmine'); +import { DirectoryRequireCache } from '@stryker-mutator/util'; import * as helpers from '../../src/helpers'; -import JasmineTestRunner from '../../src/JasmineTestRunner'; +import * as pluginTokens from '../../src/pluginTokens'; +import { JasmineTestRunner } from '../../src'; import { expectTestResultsToEqual } from '../helpers/assertions'; +import { createEnvStub, createRunDetails, createCustomReporterResult } from '../helpers/mockFactories'; -type SinonStubbedInstance = { - [P in keyof TType]: TType[P] extends Function ? sinon.SinonStub : TType[P]; -}; - -describe('JasmineTestRunner', () => { - let sandbox: sinon.SinonSandbox; - let jasmineStub: SinonStubbedInstance; - let evalGlobalStub: sinon.SinonStub; +describe(JasmineTestRunner.name, () => { + let reporter: jasmine.CustomReporter; + let jasmineStub: sinon.SinonStubbedInstance; + let jasmineEnvStub: sinon.SinonStubbedInstance; + let directoryRequireCacheMock: sinon.SinonStubbedInstance; let sut: JasmineTestRunner; - let fileNames: string[]; let clock: sinon.SinonFakeTimers; beforeEach(() => { - sandbox = sinon.createSandbox(); - jasmineStub = sandbox.createStubInstance(Jasmine); - jasmineStub.env = { - throwOnExpectationFailure: sandbox.stub(), - }; - evalGlobalStub = sandbox.stub(helpers, 'evalGlobal'); - sandbox.stub(helpers, 'Jasmine').returns(jasmineStub); - fileNames = ['foo.js', 'bar.js']; - clock = sandbox.useFakeTimers(); - sut = new JasmineTestRunner(fileNames, factory.strykerOptions({ jasmineConfigFile: 'jasmineConfFile' })); + jasmineStub = sinon.createStubInstance(Jasmine); + jasmineEnvStub = createEnvStub(); + jasmineStub.env = (jasmineEnvStub as unknown) as jasmine.Env; + sinon.stub(helpers, 'Jasmine').returns(jasmineStub); + clock = sinon.useFakeTimers(); + directoryRequireCacheMock = sinon.createStubInstance(DirectoryRequireCache); + jasmineEnvStub.addReporter.callsFake((rep: jasmine.CustomReporter) => (reporter = rep)); + testInjector.options.jasmineConfigFile = 'jasmineConfFile'; + sut = testInjector.injector + .provideValue(pluginTokens.directoryRequireCache, directoryRequireCacheMock) + .provideValue(pluginTokens.globalNamespace, '__stryker2__' as const) + .injectClass(JasmineTestRunner); }); - afterEach(() => { - delete require.cache['foo.js']; - delete require.cache['bar.js']; - sandbox.restore(); + describe('init', () => { + it('should initialize the require cache', async () => { + await sut.init(); + expect(directoryRequireCacheMock.init).calledWithExactly({ initFiles: [], rootModuleId: require.resolve('jasmine') }); + }); }); - it('should configure jasmine on run', async () => { - await actRunWithoutTests(); - expect(jasmineStub.execute).called; - expect(helpers.Jasmine).calledWithNew; - expect(helpers.Jasmine).calledWith({ projectBaseDir: process.cwd() }); - expect(jasmineStub.loadConfigFile).calledWith('jasmineConfFile'); - expect(jasmineStub.stopSpecOnExpectationFailure).calledWith(true); - expect(jasmineStub.env.throwOnExpectationFailure).calledWith(true); - expect(jasmineStub.exit).ok; - expect(jasmineStub.clearReporters).called; - expect(jasmineStub.randomizeTests).calledWith(false); - }); + describe('mutantRun', () => { + it('should configure jasmine on run', async () => { + await actEmptyMutantRun(); + expect(jasmineStub.execute).called; + expect(helpers.Jasmine).calledWithNew; + expect(helpers.Jasmine).calledWith({ projectBaseDir: process.cwd() }); + expect(jasmineStub.loadConfigFile).calledWith('jasmineConfFile'); + expect(jasmineStub.env.configure).calledWith({ + failFast: true, + oneFailurePerSpec: true, + specFilter: undefined, + }); + expect(jasmineStub.exit).ok.and.not.eq(process.exit); + expect(jasmineStub.env.clearReporters).called; + expect(jasmineStub.randomizeTests).calledWith(false); + }); - it('should clear require cache on run', async () => { - require.cache['foo.js'] = 'foo' as any; - require.cache['bar.js'] = 'bar' as any; - await actRunWithoutTests(); - expect(require.cache['foo.js']).not.ok; - expect(require.cache['bar.js']).not.ok; - }); + it('should clear require cache for each run', async () => { + await actEmptyMutantRun(); + expect(directoryRequireCacheMock.clear).called; + expect(directoryRequireCacheMock.record).called; + expect(directoryRequireCacheMock.clear).calledBefore(directoryRequireCacheMock.record); + }); - it('should report completed specs', async () => { - // Arrange - function addReporter(rep: jasmine.CustomReporter) { - rep.specDone({ id: 'spec0', fullName: 'foo spec', status: 'success' }); - rep.specDone({ id: 'spec1', fullName: 'bar spec', status: 'failure', failedExpectations: [{ message: 'bar failed' }] }); - rep.specDone({ id: 'spec2', fullName: 'disabled', status: 'disabled' }); - rep.specDone({ id: 'spec3', fullName: 'pending', status: 'pending' }); - rep.specDone({ id: 'spec4', fullName: 'excluded', status: 'excluded' }); - rep.jasmineDone(); - } - jasmineStub.addReporter.callsFake(addReporter); - - // Act - const result = await sut.run({}); - - // Assert - expect(result.status).eq(RunStatus.Complete); - expectTestResultsToEqual(result.tests, [ - { name: 'foo spec', status: TestStatus.Success, failureMessages: undefined }, - { name: 'bar spec', status: TestStatus.Failed, failureMessages: ['bar failed'] }, - { name: 'disabled', status: TestStatus.Skipped, failureMessages: undefined }, - { name: 'pending', status: TestStatus.Skipped, failureMessages: undefined }, - { name: 'excluded', status: TestStatus.Skipped, failureMessages: undefined }, - ]); - }); + it('should filter tests based on testFilter', async () => { + await actEmptyMutantRun(['1']); + expect(jasmineEnvStub.configure).calledWithMatch({ + specFilter: sinon.match.func, + }); + const actualSpecFilter: (spec: Pick) => boolean = jasmineEnvStub.configure.getCall(0).args[0].specFilter; + expect(actualSpecFilter({ id: 1 })).true; + expect(actualSpecFilter({ id: 2 })).false; + }); - it('should time spec duration', async () => { - function addReporter(rep: jasmine.CustomReporter) { - rep.specStarted(); - clock.tick(10); - rep.specDone({ fullName: 'foobar spec', id: 'spec0' }); - rep.jasmineDone(); + it('should set the activeMutant on global scope', async () => { + actEmptyMutantRun(undefined, factory.mutant({ id: 23 })); + expect(global.__stryker2__?.activeMutant).eq(23); + }); + + function actEmptyMutantRun(testFilter?: string[], activeMutant = factory.mutant(), sandboxFileName = 'sandbox/file') { + let reporter: jasmine.CustomReporter; + function addReporter(rep: jasmine.CustomReporter) { + reporter = rep; + } + jasmineEnvStub.addReporter.callsFake(addReporter); + jasmineStub.execute.callsFake(() => reporter.jasmineDone!(createRunDetails())); + return sut.mutantRun({ activeMutant, testFilter, timeout: 2000, sandboxFileName }); } - jasmineStub.addReporter.callsFake(addReporter); - const result = await sut.run({}); - const expectedTestResult: TestResult = { - failureMessages: undefined, - name: 'foobar spec', - status: TestStatus.Success, - timeSpentMs: 10, - }; - expect(result.tests).deep.eq([expectedTestResult]); }); - it('should report errors on run', async () => { - const error = new Error('foobar'); - jasmineStub.execute.throws(error); - const result = await sut.run({}); - expect(result.status).eq(RunStatus.Error); - expect(result.errorMessages).lengthOf(1); - expect((result.errorMessages || [])[0]) - .matches(/An error occurred while loading your jasmine specs.*/) - .and.matches(/.*Error: foobar.*/); - }); + describe('dryRun', () => { + it('should time spec duration', async () => { + // Arrange + clock.setSystemTime(new Date(2010, 1, 1)); + jasmineStub.execute.callsFake(() => { + const spec = createCustomReporterResult(); + reporter.specStarted!(spec); + clock.tick(10); + reporter.specDone!(spec); + reporter.jasmineDone!(createRunDetails()); + }); - it('should evaluate testHooks in global context', async () => { - const hooks = 'foobar'; - await actRunWithoutTests(hooks); - expect(evalGlobalStub).calledWith(hooks); - }); + // Act + const result = await sut.dryRun(factory.dryRunOptions()); - function actRunWithoutTests(testHooks?: string) { - function addReporter(rep: jasmine.CustomReporter) { - rep.jasmineDone(); - } - jasmineStub.addReporter.callsFake(addReporter); - return sut.run({ testHooks }); - } + // Assert + assertions.expectCompleted(result); + expect(result.tests[0].timeSpentMs).deep.eq(10); + }); + + (['perTest', 'all'] as const).forEach((coverageAnalysis) => + it(`should report mutation coverage when coverage analysis is ${coverageAnalysis}`, async () => { + // Arrange + const expectedMutationCoverage = { + perTest: { + [1]: [2, 3], + }, + static: {}, + }; + global.__stryker2__!.mutantCoverage = expectedMutationCoverage; + jasmineStub.execute.callsFake(() => { + reporter.jasmineDone!(createRunDetails()); + }); + + // Act + const result = await sut.dryRun(factory.dryRunOptions({ coverageAnalysis })); + + // Assert + const expectedResult: CompleteDryRunResult = { + status: DryRunStatus.Complete, + tests: [], + mutantCoverage: expectedMutationCoverage, + }; + expect(result).deep.eq(expectedResult); + }) + ); + + it('should not report mutation coverage when coverage analysis is "off"', async () => { + // Arrange + const expectedMutationCoverage = { + perTest: {}, + static: {}, + }; + global.__stryker2__!.mutantCoverage = expectedMutationCoverage; + jasmineStub.execute.callsFake(() => { + reporter.jasmineDone!(createRunDetails()); + }); + + // Act + const result = await sut.dryRun(factory.dryRunOptions({ coverageAnalysis: 'off' })); + + // Assert + const expectedResult: CompleteDryRunResult = { + status: DryRunStatus.Complete, + tests: [], + mutantCoverage: undefined, + }; + expect(result).deep.eq(expectedResult); + }); + + it('set current test id between specs when coverageAnalysis = "perTest"', async () => { + // Arrange + let firstCurrentTestId: string | undefined; + let secondCurrentTestId: string | undefined; + jasmineStub.execute.callsFake(() => { + const spec0 = createCustomReporterResult({ id: 'spec0' }); + const spec1 = createCustomReporterResult({ id: 'spec23' }); + reporter.specStarted!(spec0); + firstCurrentTestId = global.__stryker2__!.currentTestId; + reporter.specDone!(spec0); + reporter.specStarted!(spec1); + secondCurrentTestId = global.__stryker2__!.currentTestId; + reporter.specDone!(spec1); + reporter.jasmineDone!(createRunDetails()); + }); + + // Act + await sut.dryRun(factory.dryRunOptions({ coverageAnalysis: 'perTest' })); + + // Assert + expect(firstCurrentTestId).eq('spec0'); + expect(secondCurrentTestId).eq('spec23'); + }); + + it('not set current test id between specs when coverageAnalysis = "all"', async () => { + // Arrange + let firstCurrentTestId: string | undefined; + jasmineStub.execute.callsFake(() => { + const spec0 = createCustomReporterResult({ id: 'spec0' }); + reporter.specStarted!(spec0); + firstCurrentTestId = global.__stryker2__!.currentTestId; + reporter.specDone!(spec0); + reporter.jasmineDone!(createRunDetails()); + }); + + // Act + await sut.dryRun(factory.dryRunOptions({ coverageAnalysis: 'all' })); + + // Assert + expect(firstCurrentTestId).undefined; + }); + + it('should report completed specs', async () => { + // Arrange + jasmineStub.execute.callsFake(() => { + reporter.specDone!({ id: 'spec0', fullName: 'foo spec', status: 'success', description: 'string' }); + reporter.specDone!({ + id: 'spec1', + fullName: 'bar spec', + status: 'failure', + failedExpectations: [{ actual: 'foo', expected: 'bar', matcherName: 'fooMatcher', passed: false, message: 'bar failed', stack: 'stack' }], + description: 'string', + }); + reporter.specDone!({ id: 'spec2', fullName: 'disabled', status: 'disabled', description: 'string' }); + reporter.specDone!({ id: 'spec3', fullName: 'pending', status: 'pending', description: 'string' }); + reporter.specDone!({ id: 'spec4', fullName: 'excluded', status: 'excluded', description: 'string' }); + reporter.jasmineDone!(createRunDetails()); + }); + + // Act + const result = await sut.dryRun(factory.dryRunOptions()); + + // Assert + assertions.expectCompleted(result); + expectTestResultsToEqual(result.tests, [ + { id: 'spec0', name: 'foo spec', status: TestStatus.Success }, + { id: 'spec1', name: 'bar spec', status: TestStatus.Failed, failureMessage: 'bar failed' }, + { id: 'spec2', name: 'disabled', status: TestStatus.Skipped }, + { id: 'spec3', name: 'pending', status: TestStatus.Skipped }, + { id: 'spec4', name: 'excluded', status: TestStatus.Skipped }, + ]); + }); + + it('should report errors on run', async () => { + const error = new Error('foobar'); + jasmineStub.execute.throws(error); + const result = await sut.dryRun(factory.dryRunOptions()); + assertions.expectErrored(result); + expect(result.errorMessage) + .matches(/An error occurred while loading your jasmine specs.*/) + .and.matches(/.*Error: foobar.*/); + }); + }); }); diff --git a/packages/jasmine-runner/testResources/big-project/lib/big-text.js b/packages/jasmine-runner/testResources/big-project/lib/big-text.js new file mode 100644 index 0000000000..b6cd664ae5 --- /dev/null +++ b/packages/jasmine-runner/testResources/big-project/lib/big-text.js @@ -0,0 +1,6 @@ + +// Change the text each iteration to prevent nodejs from optimizing it into one value on the heap +if (!global.n) { + global.n = 500000; +} +module.exports.text = new Array(global.n++).fill('i').join(','); diff --git a/packages/jasmine-runner/testResources/big-project/spec/support/jasmine.json b/packages/jasmine-runner/testResources/big-project/spec/support/jasmine.json new file mode 100644 index 0000000000..3ea316690a --- /dev/null +++ b/packages/jasmine-runner/testResources/big-project/spec/support/jasmine.json @@ -0,0 +1,11 @@ +{ + "spec_dir": "spec", + "spec_files": [ + "**/*[sS]pec.js" + ], + "helpers": [ + "helpers/**/*.js" + ], + "stopSpecOnExpectationFailure": false, + "random": false +} diff --git a/packages/jasmine-runner/testResources/big-project/spec/tests/big-text.spec.js b/packages/jasmine-runner/testResources/big-project/spec/tests/big-text.spec.js new file mode 100644 index 0000000000..9df7ac2c3a --- /dev/null +++ b/packages/jasmine-runner/testResources/big-project/spec/tests/big-text.spec.js @@ -0,0 +1,9 @@ +const { text } = require('../../lib/big-text'); + +describe('Big text', () => { + it('should contain i', () => { + if (text.indexOf('i') === -1) { + throw new Error(); + } + }); +}); diff --git a/packages/jasmine-runner/testResources/jasmine-init-instrumented/lib/jasmine_examples/Player.js b/packages/jasmine-runner/testResources/jasmine-init-instrumented/lib/jasmine_examples/Player.js new file mode 100644 index 0000000000..0e2e05da89 --- /dev/null +++ b/packages/jasmine-runner/testResources/jasmine-init-instrumented/lib/jasmine_examples/Player.js @@ -0,0 +1,107 @@ +// This file is generated with tasks/instrument-test-resources.js + function stryNS_9fa48() { + var g = new Function("return this")(); + var ns = g.__stryker2__ || (g.__stryker2__ = {}); + + if (ns.activeMutant === undefined && g.process && g.process.env && g.process.env.__STRYKER_ACTIVE_MUTANT__) { + ns.activeMutant = Number(g.process.env.__STRYKER_ACTIVE_MUTANT__); + } + + function retrieveNS() { + return ns; + } + + stryNS_9fa48 = retrieveNS; + return retrieveNS(); +} + +stryNS_9fa48(); + +function stryCov_9fa48() { + var ns = stryNS_9fa48(); + var cov = ns.mutantCoverage || (ns.mutantCoverage = { + static: {}, + perTest: {} + }); + + function cover() { + var c = cov.static; + + if (ns.currentTestId) { + c = cov.perTest[ns.currentTestId] = cov.perTest[ns.currentTestId] || {}; + } + + var a = arguments; + + for (var i = 0; i < a.length; i++) { + c[a[i]] = (c[a[i]] || 0) + 1; + } + } + + stryCov_9fa48 = cover; + cover.apply(null, arguments); +} + +function stryMutAct_9fa48(id) { + var ns = stryNS_9fa48(); + + function isActive(id) { + return ns.activeMutant === id; + } + + stryMutAct_9fa48 = isActive; + return isActive(id); +} + +function Player() {} + +Player.prototype.play = function (song) { + if (stryMutAct_9fa48(0)) { + {} + } else { + stryCov_9fa48(0); + this.currentlyPlayingSong = song; + this.isPlaying = stryMutAct_9fa48(1) ? false : (stryCov_9fa48(1), true); + } +}; + +Player.prototype.pause = function () { + if (stryMutAct_9fa48(2)) { + {} + } else { + stryCov_9fa48(2); + this.isPlaying = stryMutAct_9fa48(3) ? true : (stryCov_9fa48(3), false); + } +}; + +Player.prototype.resume = function () { + if (stryMutAct_9fa48(4)) { + {} + } else { + stryCov_9fa48(4); + + if (stryMutAct_9fa48(6) ? false : stryMutAct_9fa48(5) ? true : (stryCov_9fa48(5, 6), this.isPlaying)) { + if (stryMutAct_9fa48(7)) { + {} + } else { + stryCov_9fa48(7); + throw new Error(stryMutAct_9fa48(8) ? "" : (stryCov_9fa48(8), "song is already playing")); + } + } + + this.isPlaying = stryMutAct_9fa48(9) ? false : (stryCov_9fa48(9), true); + } +}; + +Player.prototype.makeFavorite = function () { + if (stryMutAct_9fa48(10)) { + {} + } else { + stryCov_9fa48(10); + this.currentlyPlayingSong.persistFavoriteStatus(stryMutAct_9fa48(11) ? false : (stryCov_9fa48(11), true)); + } +}; // Add random string, resulting in a static mutant in the instrumented code. + + +module.exports.foo = stryMutAct_9fa48(12) ? "" : (stryCov_9fa48(12), 'bar'); +module.exports = Player; \ No newline at end of file diff --git a/packages/jasmine-runner/testResources/jasmine-init-instrumented/lib/jasmine_examples/Song.js b/packages/jasmine-runner/testResources/jasmine-init-instrumented/lib/jasmine_examples/Song.js new file mode 100644 index 0000000000..aa0cea72b2 --- /dev/null +++ b/packages/jasmine-runner/testResources/jasmine-init-instrumented/lib/jasmine_examples/Song.js @@ -0,0 +1,68 @@ +// This file is generated with tasks/instrument-test-resources.js + function stryNS_9fa48() { + var g = new Function("return this")(); + var ns = g.__stryker2__ || (g.__stryker2__ = {}); + + if (ns.activeMutant === undefined && g.process && g.process.env && g.process.env.__STRYKER_ACTIVE_MUTANT__) { + ns.activeMutant = Number(g.process.env.__STRYKER_ACTIVE_MUTANT__); + } + + function retrieveNS() { + return ns; + } + + stryNS_9fa48 = retrieveNS; + return retrieveNS(); +} + +stryNS_9fa48(); + +function stryCov_9fa48() { + var ns = stryNS_9fa48(); + var cov = ns.mutantCoverage || (ns.mutantCoverage = { + static: {}, + perTest: {} + }); + + function cover() { + var c = cov.static; + + if (ns.currentTestId) { + c = cov.perTest[ns.currentTestId] = cov.perTest[ns.currentTestId] || {}; + } + + var a = arguments; + + for (var i = 0; i < a.length; i++) { + c[a[i]] = (c[a[i]] || 0) + 1; + } + } + + stryCov_9fa48 = cover; + cover.apply(null, arguments); +} + +function stryMutAct_9fa48(id) { + var ns = stryNS_9fa48(); + + function isActive(id) { + return ns.activeMutant === id; + } + + stryMutAct_9fa48 = isActive; + return isActive(id); +} + +function Song() {} + +Song.prototype.persistFavoriteStatus = function (value) { + if (stryMutAct_9fa48(13)) { + {} + } else { + stryCov_9fa48(13); + // something complicated + throw new Error(stryMutAct_9fa48(14) ? "" : (stryCov_9fa48(14), "not yet implemented")); + } +}; + +module.exports = Song; \ No newline at end of file diff --git a/packages/jasmine-runner/testResources/jasmine-init-instrumented/spec/helpers/jasmine_examples/SpecHelper.js b/packages/jasmine-runner/testResources/jasmine-init-instrumented/spec/helpers/jasmine_examples/SpecHelper.js new file mode 100644 index 0000000000..578b3e8626 --- /dev/null +++ b/packages/jasmine-runner/testResources/jasmine-init-instrumented/spec/helpers/jasmine_examples/SpecHelper.js @@ -0,0 +1,15 @@ +beforeEach(function () { + jasmine.addMatchers({ + toBePlaying: function () { + return { + compare: function (actual, expected) { + var player = actual; + + return { + pass: player.currentlyPlayingSong === expected && player.isPlaying + } + } + }; + } + }); +}); diff --git a/packages/jasmine-runner/testResources/jasmine-init-instrumented/spec/jasmine_examples/PlayerSpec.js b/packages/jasmine-runner/testResources/jasmine-init-instrumented/spec/jasmine_examples/PlayerSpec.js new file mode 100644 index 0000000000..80f149e3a8 --- /dev/null +++ b/packages/jasmine-runner/testResources/jasmine-init-instrumented/spec/jasmine_examples/PlayerSpec.js @@ -0,0 +1,60 @@ +describe("Player", function() { + var Player = require('../../lib/jasmine_examples/Player'); + var Song = require('../../lib/jasmine_examples/Song'); + var player; + var song; + + beforeEach(function() { + player = new Player(); + song = new Song(); + }); + + it("should be able to play a Song", function() { + player.play(song); + expect(player.currentlyPlayingSong).toEqual(song); + + //demonstrates use of custom matcher + expect(player).toBePlaying(song); + }); + + describe("when song has been paused", function() { + beforeEach(function() { + player.play(song); + player.pause(); + }); + + it("should indicate that the song is currently paused", function() { + expect(player.isPlaying).toBeFalsy(); + + // demonstrates use of 'not' with a custom matcher + expect(player).not.toBePlaying(song); + }); + + it("should be possible to resume", function() { + player.resume(); + expect(player.isPlaying).toBeTruthy(); + expect(player.currentlyPlayingSong).toEqual(song); + }); + }); + + // demonstrates use of spies to intercept and test method calls + it("tells the current song if the user has made it a favorite", function() { + spyOn(song, 'persistFavoriteStatus'); + + player.play(song); + player.makeFavorite(); + + expect(song.persistFavoriteStatus).toHaveBeenCalledWith(true); + }); + + //demonstrates use of expected exceptions + describe("#resume", function() { + it("should throw an exception if song is already playing", function() { + player.play(song); + + expect(function() { + player.resume(); + }).toThrowError("song is already playing"); + }); + }); +}); diff --git a/packages/jasmine-runner/testResources/jasmine-init-instrumented/spec/support/jasmine.json b/packages/jasmine-runner/testResources/jasmine-init-instrumented/spec/support/jasmine.json new file mode 100644 index 0000000000..3ea316690a --- /dev/null +++ b/packages/jasmine-runner/testResources/jasmine-init-instrumented/spec/support/jasmine.json @@ -0,0 +1,11 @@ +{ + "spec_dir": "spec", + "spec_files": [ + "**/*[sS]pec.js" + ], + "helpers": [ + "helpers/**/*.js" + ], + "stopSpecOnExpectationFailure": false, + "random": false +} diff --git a/packages/jasmine-runner/testResources/jasmine-init/lib/jasmine_examples/Player.js b/packages/jasmine-runner/testResources/jasmine-init/lib/jasmine_examples/Player.js index fe95f89465..d72f90c770 100644 --- a/packages/jasmine-runner/testResources/jasmine-init/lib/jasmine_examples/Player.js +++ b/packages/jasmine-runner/testResources/jasmine-init/lib/jasmine_examples/Player.js @@ -21,4 +21,7 @@ Player.prototype.makeFavorite = function() { this.currentlyPlayingSong.persistFavoriteStatus(true); }; +// Add random string, resulting in a static mutant in the instrumented code. +module.exports.foo = 'bar'; + module.exports = Player; diff --git a/packages/jasmine-runner/testResources/jasmine-init/spec/jasmine_examples/PlayerSpec.js b/packages/jasmine-runner/testResources/jasmine-init/spec/jasmine_examples/PlayerSpec.js index 80f149e3a8..f29080325e 100644 --- a/packages/jasmine-runner/testResources/jasmine-init/spec/jasmine_examples/PlayerSpec.js +++ b/packages/jasmine-runner/testResources/jasmine-init/spec/jasmine_examples/PlayerSpec.js @@ -1,15 +1,24 @@ -describe("Player", function() { +// Add this reporter to spy on the specs being executed +jasmine.getEnv().addReporter({ + specDone(spec) { + if (spec.status !== 'excluded') { + global.__testsInCurrentJasmineRun.push(spec.id); + } + } +}); + +describe("Player", function () { var Player = require('../../lib/jasmine_examples/Player'); var Song = require('../../lib/jasmine_examples/Song'); var player; var song; - beforeEach(function() { + beforeEach(function () { player = new Player(); song = new Song(); }); - it("should be able to play a Song", function() { + it("should be able to play a Song", function () { player.play(song); expect(player.currentlyPlayingSong).toEqual(song); @@ -17,20 +26,20 @@ describe("Player", function() { expect(player).toBePlaying(song); }); - describe("when song has been paused", function() { - beforeEach(function() { + describe("when song has been paused", function () { + beforeEach(function () { player.play(song); player.pause(); }); - it("should indicate that the song is currently paused", function() { + it("should indicate that the song is currently paused", function () { expect(player.isPlaying).toBeFalsy(); // demonstrates use of 'not' with a custom matcher expect(player).not.toBePlaying(song); }); - it("should be possible to resume", function() { + it("should be possible to resume", function () { player.resume(); expect(player.isPlaying).toBeTruthy(); expect(player.currentlyPlayingSong).toEqual(song); @@ -38,7 +47,7 @@ describe("Player", function() { }); // demonstrates use of spies to intercept and test method calls - it("tells the current song if the user has made it a favorite", function() { + it("tells the current song if the user has made it a favorite", function () { spyOn(song, 'persistFavoriteStatus'); player.play(song); @@ -48,11 +57,11 @@ describe("Player", function() { }); //demonstrates use of expected exceptions - describe("#resume", function() { - it("should throw an exception if song is already playing", function() { + describe("#resume", function () { + it("should throw an exception if song is already playing", function () { player.play(song); - expect(function() { + expect(function () { player.resume(); }).toThrowError("song is already playing"); }); diff --git a/packages/jasmine-runner/tsconfig.stryker.json b/packages/jasmine-runner/tsconfig.stryker.json deleted file mode 100644 index 9d9e80e976..0000000000 --- a/packages/jasmine-runner/tsconfig.stryker.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "./tsconfig.test.json", - "include": [ - "src", - "src-generated", - "schema/*.json", - "test", - "typings" - ], -} diff --git a/packages/jasmine-runner/typings/JasmineTypes.d.ts b/packages/jasmine-runner/typings/JasmineTypes.d.ts index aa559d5ced..2322e02d49 100644 --- a/packages/jasmine-runner/typings/JasmineTypes.d.ts +++ b/packages/jasmine-runner/typings/JasmineTypes.d.ts @@ -1,96 +1,895 @@ +/* eslint-disable @typescript-eslint/explicit-member-accessibility */ +/* eslint-disable @typescript-eslint/class-name-casing */ + +/** + * Grabbed from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/jasmine, + * but removed duplicate globals, `it`, `describe`, etc + */ + declare namespace jasmine { - interface Order { - new (options: { - random: boolean; - seed: string; - }): any; - random: boolean; - seed: string; - sort(items: T[]): T[]; - } - interface Trace { - name: string; - message: string; - stack: any; - } - interface Result { - type: string; - } - interface ExpectationResult extends Result { - matcherName: string; - passed(): boolean; - expected: any; - actual: any; - message: string; - trace: Trace; - } - interface RunDetails { - failedExpectations: ExpectationResult[]; - order: Order; - } - interface SuiteInfo { - totalSpecsDefined: number; - } - interface CustomReportExpectation { - message: string; - } - interface FailedExpectation extends CustomReportExpectation { - } - interface PassedExpectation extends CustomReportExpectation { - } - interface CustomReporterResult { - failedExpectations?: FailedExpectation[]; - fullName: string; - id: string; - passedExpectations?: PassedExpectation[]; - pendingReason?: string; - status?: string; - } - interface CustomReporter { - jasmineStarted?(suiteInfo: SuiteInfo): void; - suiteStarted?(result: CustomReporterResult): void; - specStarted(): void; - specDone(result: CustomReporterResult): void; - suiteDone?(result: CustomReporterResult): void; - jasmineDone(): void; - } - interface Env { - throwOnExpectationFailure(value: boolean): void; + interface DoneFn extends Function { + (): void; + + /** fails the spec and indicates that it has completed. If the message is an Error, Error.message is used */ + fail: (message?: Error | string) => void; + } + + type Func = (...args: any[]) => any; + + // Use trick with prototype to allow abstract classes. + // More info: https://stackoverflow.com/a/38642922/2009373 + type Constructor = Function & { prototype: any }; + + type ImplementationCallback = (() => PromiseLike) | ((done: DoneFn) => void); + + type ExpectedRecursive = + | T + | ObjectContaining + | AsymmetricMatcher + | { + [K in keyof T]: ExpectedRecursive | Any; + }; + type Expected = + | T + | ObjectContaining + | AsymmetricMatcher + | Any + | Spy + | { + [K in keyof T]: ExpectedRecursive; + }; + type SpyObjMethodNames = T extends undefined + ? readonly string[] | { [methodName: string]: any } + : ReadonlyArray | { [P in keyof T]?: T[P] extends Func ? ReturnType : any }; + + type SpyObjPropertyNames = T extends undefined + ? readonly string[] | { [propertyName: string]: any } + : ReadonlyArray | { [P in keyof T]?: T[P] }; + + /** + * Configuration that can be used when configuring Jasmine via {@link jasmine.Env.configure} + */ + interface EnvConfiguration { + random?: boolean; + seed?: number; + failFast?: boolean; + failSpecWithNoExpectations?: boolean; + oneFailurePerSpec?: boolean; + hideDisabled?: boolean; + specFilter?: Function; + promise?: Function; + } + + function clock(): Clock; + + var matchersUtil: MatchersUtil; + + /** + * That will succeed if the actual value being compared is an instance of the specified class/constructor. + */ + function any(aclass: Constructor | symbol): AsymmetricMatcher; + + /** + * That will succeed if the actual value being compared is not `null` and not `undefined`. + */ + function anything(): AsymmetricMatcher; + + /** + * That will succeed if the actual value being compared is `true` or anything truthy. + * @since 3.1.0 + */ + function truthy(): AsymmetricMatcher; + + /** + * That will succeed if the actual value being compared is `null`, `undefined`, `0`, `false` or anything falsey. + * @since 3.1.0 + */ + function falsy(): AsymmetricMatcher; + + /** + * That will succeed if the actual value being compared is empty. + * @since 3.1.0 + */ + function empty(): AsymmetricMatcher; + + /** + * That will succeed if the actual value being compared is not empty. + * @since 3.1.0 + */ + function notEmpty(): AsymmetricMatcher; + + function arrayContaining(sample: ArrayLike): ArrayContaining; + function arrayWithExactContents(sample: ArrayLike): ArrayContaining; + function objectContaining(sample: { [K in keyof T]?: ExpectedRecursive }): ObjectContaining; + + function setDefaultSpyStrategy(and: SpyAnd): void; + function createSpy(name?: string, originalFn?: Fn): Spy; + function createSpyObj(baseName: string, methodNames: SpyObjMethodNames, propertyNames?: SpyObjPropertyNames): any; + function createSpyObj(baseName: string, methodNames: SpyObjMethodNames, propertyNames?: SpyObjPropertyNames): SpyObj; + function createSpyObj(methodNames: SpyObjMethodNames, propertyNames?: SpyObjPropertyNames): any; + function createSpyObj(methodNames: SpyObjMethodNames, propertyNames?: SpyObjPropertyNames): SpyObj; + + function pp(value: any): string; + + function getEnv(): Env; + + function addCustomEqualityTester(equalityTester: CustomEqualityTester): void; + + function addMatchers(matchers: CustomMatcherFactories): void; + function addAsyncMatchers(matchers: CustomAsyncMatcherFactories): void; + + function stringMatching(str: string | RegExp): AsymmetricMatcher; + + function formatErrorMsg(domain: string, usage: string): (msg: string) => string; + + interface Any extends AsymmetricMatcher { + (...params: any[]): any; // jasmine.Any can also be a function + new (expectedClass: any): any; + + jasmineMatches(other: any): boolean; + jasmineToString(): string; + } + + interface AsymmetricMatcher { + asymmetricMatch(other: TValue, customTesters: readonly CustomEqualityTester[]): boolean; + jasmineToString?(): string; + } + + // taken from TypeScript lib.core.es6.d.ts, applicable to CustomMatchers.contains() + interface ArrayLike { + length: number; + [n: number]: T; + } + + interface ArrayContaining extends AsymmetricMatcher { + new?(sample: ArrayLike): ArrayLike; + } + + interface ObjectContaining extends AsymmetricMatcher { + new?(sample: { [K in keyof T]?: any }): { [K in keyof T]?: any }; + + jasmineMatches(other: any, mismatchKeys: any[], mismatchValues: any[]): boolean; + jasmineToString?(): string; + } + + interface Block { + new (env: Env, func: SpecFunction, spec: Spec): any; + + execute(onComplete: () => void): void; + } + + interface WaitsBlock extends Block { + new (env: Env, timeout: number, spec: Spec): any; + } + + interface WaitsForBlock extends Block { + new (env: Env, timeout: number, latchFunction: SpecFunction, message: string, spec: Spec): any; + } + + interface Clock { + install(): void; + uninstall(): void; + /** Calls to any registered callback are triggered when the clock is ticked forward via the jasmine.clock().tick function, which takes a number of milliseconds. */ + tick(ms: number): void; + mockDate(date?: Date): void; + withMock(func: () => void): void; + } + + type CustomEqualityTester = (first: any, second: any) => boolean | void; + + interface CustomMatcher { + compare(actual: T, expected: T, ...args: any[]): CustomMatcherResult; + compare(actual: any, ...expected: any[]): CustomMatcherResult; + negativeCompare?(actual: T, expected: T, ...args: any[]): CustomMatcherResult; + negativeCompare?(actual: any, ...expected: any[]): CustomMatcherResult; + } + + interface CustomAsyncMatcher { + compare(actual: T, expected: T, ...args: any[]): Promise; + compare(actual: any, ...expected: any[]): Promise; + negativeCompare?(actual: T, expected: T, ...args: any[]): Promise; + negativeCompare?(actual: any, ...expected: any[]): Promise; + } + + type CustomMatcherFactory = (util: MatchersUtil, customEqualityTesters: readonly CustomEqualityTester[]) => CustomMatcher; + + type CustomAsyncMatcherFactory = (util: MatchersUtil, customEqualityTesters: readonly CustomEqualityTester[]) => CustomAsyncMatcher; + + interface CustomMatcherFactories { + [name: string]: CustomMatcherFactory; + } + + interface CustomAsyncMatcherFactories { + [name: string]: CustomAsyncMatcherFactory; + } + + interface CustomMatcherResult { + pass: boolean; + message?: string; + } + + interface MatchersUtil { + equals(a: any, b: any, customTesters?: readonly CustomEqualityTester[]): boolean; + contains(haystack: ArrayLike | string, needle: any, customTesters?: readonly CustomEqualityTester[]): boolean; + buildFailureMessage(matcherName: string, isNot: boolean, actual: any, ...expected: any[]): string; + } + + interface Env { + currentSpec: Spec; + + matchersClass: Matchers; + + version(): any; + versionString(): string; + nextSpecId(): number; + addReporter(reporter: Reporter | CustomReporter): void; + execute(): void; + describe(description: string, specDefinitions: () => void): Suite; + // ddescribe(description: string, specDefinitions: () => void): Suite; Not a part of jasmine. Angular team adds these + beforeEach(beforeEachFunction: ImplementationCallback, timeout?: number): void; + beforeAll(beforeAllFunction: ImplementationCallback, timeout?: number): void; + currentRunner(): Runner; + afterEach(afterEachFunction: ImplementationCallback, timeout?: number): void; + afterAll(afterAllFunction: ImplementationCallback, timeout?: number): void; + xdescribe(desc: string, specDefinitions: () => void): XSuite; + it(description: string, func: () => void): Spec; + // iit(description: string, func: () => void): Spec; Not a part of jasmine. Angular team adds these + xit(desc: string, func: () => void): XSpec; + compareRegExps_(a: RegExp, b: RegExp, mismatchKeys: string[], mismatchValues: string[]): boolean; + compareObjects_(a: any, b: any, mismatchKeys: string[], mismatchValues: string[]): boolean; + equals_(a: any, b: any, mismatchKeys: string[], mismatchValues: string[]): boolean; + contains_(haystack: any, needle: any): boolean; + addCustomEqualityTester(equalityTester: CustomEqualityTester): void; + addMatchers(matchers: CustomMatcherFactories): void; + specFilter(spec: Spec): boolean; + /** + * @deprecated Use oneFailurePerSpec option in {@link jasmine.Env.configure} instead. + */ + throwOnExpectationFailure(value: boolean): void; + /** + * @deprecated Use failFast option in {@link jasmine.Env.configure} instead. + */ + stopOnSpecFailure(value: boolean): void; + /** + * @deprecated Use seed option in {@link jasmine.Env.configure} instead. + */ + seed(seed: string | number): string | number; + provideFallbackReporter(reporter: Reporter): void; + throwingExpectationFailures(): boolean; + allowRespy(allow: boolean): void; + randomTests(): boolean; + /** + * @deprecated Use random option in {@link jasmine.Env.configure} instead. + */ + randomizeTests(b: boolean): void; + clearReporters(): void; + configure(configuration: EnvConfiguration): void; + } + + interface FakeTimer { + new (): any; + + reset(): void; + tick(millis: number): void; + runFunctionsWithinRange(oldMillis: number, nowMillis: number): void; + scheduleFunction(timeoutKey: any, funcToCall: () => void, millis: number, recurring: boolean): void; + } + + type HtmlReporter = new () => any; + + type HtmlSpecFilter = new () => any; + + interface Result { + type: string; + } + + interface NestedResults extends Result { + description: string; + + totalCount: number; + passedCount: number; + failedCount: number; + + skipped: boolean; + + rollupCounts(result: NestedResults): void; + log(values: any): void; + getItems(): Result[]; + addResult(result: Result): void; + passed(): boolean; + } + + interface MessageResult extends Result { + values: any; + trace: Trace; + } + + interface ExpectationResult extends Result { + matcherName: string; + passed(): boolean; + expected: any; + actual: any; + message: string; + trace: Trace; + } + + interface Order { + new (options: { random: boolean; seed: string }): any; + random: boolean; + seed: string; + sort(items: T[]): T[]; + } + + namespace errors { + class ExpectationFailed extends Error { + constructor(); + + stack: any; } + } + + interface TreeProcessor { + new (attrs: any): any; + execute: (done: Function) => void; + processTree(): any; + } + + interface Trace { + name: string; + message: string; + stack: any; + } + + interface PrettyPrinter { + new (): any; + + format(value: any): void; + iterateObject(obj: any, fn: (property: string, isGetter: boolean) => void): void; + emitScalar(value: any): void; + emitString(value: string): void; + emitArray(array: any[]): void; + emitObject(obj: any): void; + append(value: any): void; + } + + interface StringPrettyPrinter extends PrettyPrinter {} + + interface Queue { + new (env: any): any; + + env: Env; + ensured: boolean[]; + blocks: Block[]; + running: boolean; + index: number; + offset: number; + abort: boolean; + + addBefore(block: Block, ensure?: boolean): void; + add(block: any, ensure?: boolean): void; + insertNext(block: any, ensure?: boolean): void; + start(onComplete?: () => void): void; + isRunning(): boolean; + next_(): void; + results(): NestedResults; + } + + interface Matchers { + new (env: Env, actual: T, spec: Env, isNot?: boolean): any; + + env: Env; + actual: T; + spec: Env; + isNot?: boolean; + message(): any; + + /** + * Expect the actual value to be `===` to the expected value. + * + * @param expected - The expected value to compare against. + * @param expectationFailOutput + * @example + * expect(thing).toBe(realThing); + */ + toBe(expected: Expected, expectationFailOutput?: any): boolean; + + /** + * Expect the actual value to be equal to the expected, using deep equality comparison. + * @param expected - Expected value. + * @param expectationFailOutput + * @example + * expect(bigObject).toEqual({ "foo": ['bar', 'baz'] }); + */ + toEqual(expected: Expected, expectationFailOutput?: any): boolean; + + /** + * Expect the actual value to match a regular expression. + * @param expected - Value to look for in the string. + * @example + * expect("my string").toMatch(/string$/); + * expect("other string").toMatch("her"); + */ + toMatch(expected: string | RegExp, expectationFailOutput?: any): boolean; + + toBeDefined(expectationFailOutput?: any): boolean; + toBeUndefined(expectationFailOutput?: any): boolean; + toBeNull(expectationFailOutput?: any): boolean; + toBeNaN(): boolean; + toBeTruthy(expectationFailOutput?: any): boolean; + toBeFalsy(expectationFailOutput?: any): boolean; + toBeTrue(): boolean; + toBeFalse(): boolean; + toHaveBeenCalled(): boolean; + toHaveBeenCalledBefore(expected: Func): boolean; + toHaveBeenCalledWith(...params: any[]): boolean; + toHaveBeenCalledTimes(expected: number): boolean; + toContain(expected: any, expectationFailOutput?: any): boolean; + toBeLessThan(expected: number, expectationFailOutput?: any): boolean; + toBeLessThanOrEqual(expected: number, expectationFailOutput?: any): boolean; + toBeGreaterThan(expected: number, expectationFailOutput?: any): boolean; + toBeGreaterThanOrEqual(expected: number, expectationFailOutput?: any): boolean; + toBeCloseTo(expected: number, precision?: any, expectationFailOutput?: any): boolean; + toThrow(expected?: any): boolean; + toThrowError(message?: string | RegExp): boolean; + toThrowError(expected?: new (...args: any[]) => Error, message?: string | RegExp): boolean; + toThrowMatching(predicate: (thrown: any) => boolean): boolean; + toBeNegativeInfinity(expectationFailOutput?: any): boolean; + toBePositiveInfinity(expectationFailOutput?: any): boolean; + toBeInstanceOf(expected: Constructor): boolean; + + /** + * Expect the actual value to be a DOM element that has the expected class. + * @since 3.0.0 + * @param expected - The class name to test for. + * @example + * var el = document.createElement('div'); + * el.className = 'foo bar baz'; + * expect(el).toHaveClass('bar'); + */ + toHaveClass(expected: string, expectationFailOutput?: any): boolean; + + /** + * Add some context for an expect. + * @param message - Additional context to show when the matcher fails + */ + withContext(message: string): Matchers; + + /** + * Invert the matcher following this expect. + */ + not: Matchers; + } + + interface ArrayLikeMatchers extends Matchers> { + /** + * Expect the actual value to be `===` to the expected value. + * + * @param expected - The expected value to compare against. + * @param expectationFailOutput + * @example + * expect(thing).toBe(realThing); + */ + toBe(expected: Expected> | ArrayContaining, expectationFailOutput?: any): boolean; + + /** + * Expect the actual value to be equal to the expected, using deep equality comparison. + * @param expected - Expected value. + * @param expectationFailOutput + * @example + * expect(bigObject).toEqual({ "foo": ['bar', 'baz'] }); + */ + toEqual(expected: Expected> | ArrayContaining, expectationFailOutput?: any): boolean; + + toContain(expected: Expected, expectationFailOutput?: any): boolean; + + /** + * Add some context for an expect. + * @param message - Additional context to show when the matcher fails. + */ + withContext(message: string): ArrayLikeMatchers; + + /** + * Invert the matcher following this expect. + */ + not: ArrayLikeMatchers; + } + + type MatchableArgs = Fn extends (...args: infer P) => any ? { [K in keyof P]: P[K] | AsymmetricMatcher } : never; + + interface FunctionMatchers extends Matchers { + toHaveBeenCalledWith(...params: MatchableArgs): boolean; + + /** + * Add some context for an expect. + * @param message - Additional context to show when the matcher fails. + */ + withContext(message: string): FunctionMatchers; + + /** + * Invert the matcher following this expect. + */ + not: FunctionMatchers; + } + + interface NothingMatcher { + nothing(): void; + } + + interface AsyncMatchers { + /** + * Expect a promise to be resolved. + * @param expectationFailOutput + */ + toBeResolved(expectationFailOutput?: any): Promise; + + /** + * Expect a promise to be rejected. + * @param expectationFailOutput + */ + toBeRejected(expectationFailOutput?: any): Promise; + + /** + * Expect a promise to be resolved to a value equal to the expected, using deep equality comparison. + * @param expected - Value that the promise is expected to resolve to. + */ + toBeResolvedTo(expected: Expected): Promise; + + /** + * Expect a promise to be rejected with a value equal to the expected, using deep equality comparison. + * @param expected - Value that the promise is expected to be rejected with. + */ + toBeRejectedWith(expected: Expected): Promise; + + /** + * Expect a promise to be rejected with a value matched to the expected. + * @param expected - Error constructor the object that was thrown needs to be an instance of. If not provided, Error will be used. + * @param message - The message that should be set on the thrown Error. + */ + toBeRejectedWithError(expected?: new (...args: any[]) => Error, message?: string | RegExp): Promise; + + /** + * Expect a promise to be rejected with a value matched to the expected. + * @param message - The message that should be set on the thrown Error. + */ + toBeRejectedWithError(message?: string | RegExp): Promise; + + /** + * Add some context for an expect. + * @param message - Additional context to show when the matcher fails. + */ + withContext(message: string): AsyncMatchers; + + /** + * Invert the matcher following this expect. + */ + not: AsyncMatchers; + } + + interface Reporter { + reportRunnerStarting(runner: Runner): void; + reportRunnerResults(runner: Runner): void; + reportSuiteResults(suite: Suite): void; + reportSpecStarting(spec: Spec): void; + reportSpecResults(spec: Spec): void; + log(str: string): void; + } + + interface MultiReporter extends Reporter { + addReporter(reporter: Reporter): void; + } + + interface SuiteInfo { + totalSpecsDefined: number; + } + + interface CustomReportExpectation { + matcherName: string; + message: string; + passed: boolean; + stack: string; + } + + interface FailedExpectation extends CustomReportExpectation { + actual: string; + expected: string; + } + + interface PassedExpectation extends CustomReportExpectation {} + + interface CustomReporterResult { + description: string; + failedExpectations?: FailedExpectation[]; + fullName: string; + id: string; + passedExpectations?: PassedExpectation[]; + pendingReason?: string; + status?: string; + } + + interface RunDetails { + failedExpectations: ExpectationResult[]; + order: Order; + } + + interface CustomReporter { + jasmineStarted?(suiteInfo: SuiteInfo): void; + suiteStarted?(result: CustomReporterResult): void; + specStarted?(result: CustomReporterResult): void; + specDone?(result: CustomReporterResult): void; + suiteDone?(result: CustomReporterResult): void; + jasmineDone?(runDetails: RunDetails): void; + } + + interface Runner { + new (env: Env): any; + + execute(): void; + beforeEach(beforeEachFunction: SpecFunction): void; + afterEach(afterEachFunction: SpecFunction): void; + beforeAll(beforeAllFunction: SpecFunction): void; + afterAll(afterAllFunction: SpecFunction): void; + finishCallback(): void; + addSuite(suite: Suite): void; + add(block: Block): void; + specs(): Spec[]; + suites(): Suite[]; + topLevelSuites(): Suite[]; + results(): NestedResults; + } + + type SpecFunction = (spec?: Spec) => void; + + interface SuiteOrSpec { + id: number; + env: Env; + description: string; + queue: Queue; + } + + interface Spec extends SuiteOrSpec { + new (env: Env, suite: Suite, description: string): any; + + suite: Suite; + + afterCallbacks: SpecFunction[]; + spies_: Spy[]; + + results_: NestedResults; + matchersClass: Matchers; + + getFullName(): string; + results(): NestedResults; + log(arguments: any): any; + runs(func: SpecFunction): Spec; + addToQueue(block: Block): void; + addMatcherResult(result: Result): void; + getResult(): any; + expect(actual: any): any; + waits(timeout: number): Spec; + waitsFor(latchFunction: SpecFunction, timeoutMessage?: string, timeout?: number): Spec; + fail(e?: any): void; + getMatchersClass_(): Matchers; + addMatchers(matchersPrototype: CustomMatcherFactories): void; + finishCallback(): void; + finish(onComplete?: () => void): void; + after(doAfter: SpecFunction): void; + execute(onComplete?: () => void, enabled?: boolean): any; + addBeforesAndAftersToQueue(): void; + explodes(): void; + spyOn(obj: any, methodName: string, ignoreMethodDoesntExist: boolean): Spy; + spyOnProperty(object: any, property: string, accessType?: 'get' | 'set'): Spy; + spyOnAllFunctions(object: any): Spy; + + removeAllSpies(): void; + throwOnExpectationFailure: boolean; + } + + interface XSpec { + id: number; + runs(): void; + } + + interface Suite extends SuiteOrSpec { + new (env: Env, description: string, specDefinitions: () => void, parentSuite: Suite): any; + + parentSuite: Suite; + + getFullName(): string; + finish(onComplete?: () => void): void; + beforeEach(beforeEachFunction: SpecFunction): void; + afterEach(afterEachFunction: SpecFunction): void; + beforeAll(beforeAllFunction: SpecFunction): void; + afterAll(afterAllFunction: SpecFunction): void; + results(): NestedResults; + add(suiteOrSpec: SuiteOrSpec): void; + specs(): Spec[]; + suites(): Suite[]; + children(): any[]; + execute(onComplete?: () => void): void; + } + + interface XSuite { + execute(): void; + } + + interface Spy { + (...params: Parameters): ReturnType; + + and: SpyAnd; + calls: Calls; + withArgs(...args: MatchableArgs): Spy; + } + + type SpyObj = T & + { + [K in keyof T]: T[K] extends Func ? T[K] & Spy : T[K]; + }; + + /** + * It's like SpyObj, but doesn't verify argument/return types for functions. + * Useful if TS cannot correctly infer type for complex objects. + */ + type NonTypedSpyObj = SpyObj<{ [K in keyof T]: T[K] extends Func ? Func : T[K] }>; + + /** + * Obtains the promised type that a promise-returning function resolves to. + */ + type PromisedReturnType = Fn extends (...args: any[]) => PromiseLike ? TResult : never; + + /** + * Obtains the type that a promise-returning function can be rejected with. + * This is so we can use .and.rejectWith() only for functions that return a promise. + */ + type PromisedRejectType = Fn extends (...args: any[]) => PromiseLike ? any : never; + + interface SpyAnd { + identity: string; + + /** By chaining the spy with and.callThrough, the spy will still track all calls to it but in addition it will delegate to the actual implementation. */ + callThrough(): Spy; + /** By chaining the spy with and.returnValue, all calls to the function will return a specific value. */ + returnValue(val: ReturnType): Spy; + /** By chaining the spy with and.returnValues, all calls to the function will return specific values in order until it reaches the end of the return values list. */ + returnValues(...values: Array>): Spy; + /** By chaining the spy with and.callFake, all calls to the spy will delegate to the supplied function. */ + callFake(fn: Fn): Spy; + /** Tell the spy to return a promise resolving to the specified value when invoked. */ + resolveTo(val?: PromisedReturnType): Spy; + /** Tell the spy to return a promise rejecting with the specified value when invoked. */ + rejectWith(val?: PromisedRejectType): Spy; + /** By chaining the spy with and.throwError, all calls to the spy will throw the specified value. */ + throwError(msg: string | Error): Spy; + /** When a calling strategy is used for a spy, the original stubbing behavior can be returned at any time with and.stub. */ + stub(): Spy; + } + + interface Calls { + /** By chaining the spy with calls.any(), will return false if the spy has not been called at all, and then true once at least one call happens. */ + any(): boolean; + /** By chaining the spy with calls.count(), will return the number of times the spy was called */ + count(): number; + /** By chaining the spy with calls.argsFor(), will return the arguments passed to call number index */ + argsFor(index: number): Parameters; + /** By chaining the spy with calls.allArgs(), will return the arguments to all calls */ + allArgs(): ReadonlyArray>; + /** By chaining the spy with calls.all(), will return the context (the this) and arguments passed all calls */ + all(): ReadonlyArray>; + /** By chaining the spy with calls.mostRecent(), will return the context (the this) and arguments for the most recent call */ + mostRecent(): CallInfo; + /** By chaining the spy with calls.first(), will return the context (the this) and arguments for the first call */ + first(): CallInfo; + /** By chaining the spy with calls.reset(), will clears all tracking for a spy */ + reset(): void; + } + + interface CallInfo { + /** The context (the this) for the call */ + object: any; + /** All arguments passed to the call */ + args: Parameters; + /** The return value of the call */ + returnValue: ReturnType; + } + + interface Util { + inherit(childClass: Function, parentClass: Function): any; + formatException(e: any): any; + htmlEscape(str: string): string; + argsToArray(args: any): any; + extend(destination: any, source: any): any; + } + + interface JsApiReporter extends Reporter { + started: boolean; + finished: boolean; + result: any; + messages: any; + runDetails: RunDetails; + + new (): any; + + suites(): Suite[]; + summarize_(suiteOrSpec: SuiteOrSpec): any; + results(): any; + resultsForSpec(specId: any): any; + log(str: any): any; + resultsForSpecs(specIds: any): any; + summarizeResult_(result: any): any; + } + + interface Jasmine { + Spec: Spec; + clock: Clock; + util: Util; + } + + var HtmlReporter: HtmlReporter; + var HtmlSpecFilter: HtmlSpecFilter; + + /** + * Default number of milliseconds Jasmine will wait for an asynchronous spec to complete. + */ + var DEFAULT_TIMEOUT_INTERVAL: number; + + /** + * Maximum number of array elements to display when pretty printing objects. + * This will also limit the number of keys and values displayed for an object. + * Elements past this number will be ellipised. + */ + var MAX_PRETTY_PRINT_ARRAY_LENGTH: number; + + /** + * Maximum number of charasters to display when pretty printing objects. + * Characters past this number will be ellipised. + */ + var MAX_PRETTY_PRINT_CHARS: number; + + /** + * Maximum object depth the pretty printer will print to. + * Set this to a lower value to speed up pretty printing if you have large objects. + */ + var MAX_PRETTY_PRINT_DEPTH: number; } + declare module 'jasmine' { - class Jasmine { - constructor(options: any); - addReporter(reporter: jasmine.CustomReporter): void; - addSpecFile(filePath: string): void; - addSpecFiles(files: string[]): void; - clearReporters(): void; - configureDefaultReporter(options: any, ...args: any[]): void; - env: jasmine.Env; - execute(files?: string[], filterString?: string): any; - exit: (code: number) => void; - exitCodeCompletion(passed: any): void; - loadConfig(config: any): void; - loadConfigFile(configFilePath: any): void; - loadHelpers(): void; - loadSpecs(): void; - onComplete(onCompleteCallback: (passed: boolean) => void): void; - randomizeTests(value?: any): boolean; - seed(value: any): void; - showColors(value: any): void; - stopSpecOnExpectationFailure(value: boolean): void; - stopOnSpecFailure(value: boolean): void; - static ConsoleReporter(): any; - reportersCount: number; - completionReporter: jasmine.CustomReporter; - reporter: jasmine.CustomReporter; - coreVersion(): string; - showingColors: boolean; - projectBaseDir: string; - printDeprecation(): void; - specFiles: string[]; - helperFiles: string[]; - } - export = Jasmine; + class jasmine { + constructor(options: any); + jasmine: jasmine.Jasmine; + addMatchers(matchers: jasmine.CustomMatcherFactories): void; + addReporter(reporter: jasmine.Reporter): void; + addSpecFile(filePath: string): void; + addSpecFiles(files: string[]): void; + configureDefaultReporter(options: any, ...args: any[]): void; + execute(files?: string[], filterString?: string): any; + exitCodeCompletion(passed: any): void; + loadConfig(config: any): void; + loadConfigFile(configFilePath: any): void; + loadHelpers(): void; + loadSpecs(): void; + onComplete(onCompleteCallback: (passed: boolean) => void): void; + provideFallbackReporter(reporter: jasmine.Reporter): void; + randomizeTests(value?: any): boolean; + seed(value: any): void; + showColors(value: any): void; + stopSpecOnExpectationFailure(value: any): void; + static ConsoleReporter(): any; + env: jasmine.Env; + + /** + * Custom edit for Stryker + * @see https://github.com/jasmine/jasmine-npm/blob/master/lib/jasmine.js#L24 + */ + exit(): void; + + reportersCount: number; + completionReporter: jasmine.CustomReporter; + reporter: jasmine.CustomReporter; + coreVersion(): string; + showingColors: boolean; + projectBaseDir: string; + printDeprecation(): void; + specFiles: string[]; + helperFiles: string[]; + } + export = jasmine; } -//# sourceMappingURL=JasmineTypes.d.ts.map \ No newline at end of file diff --git a/packages/jasmine-runner/typings/global.d.ts b/packages/jasmine-runner/typings/global.d.ts new file mode 100644 index 0000000000..72ed9d5a97 --- /dev/null +++ b/packages/jasmine-runner/typings/global.d.ts @@ -0,0 +1,7 @@ +declare namespace NodeJS { + interface Global { + __stryker__: import('@stryker-mutator/api/core').InstrumenterContext | undefined; + // used during testing, so we can actually run stryker on the @stryker-mutator/jasmine-runner package itself + __stryker2__: import('@stryker-mutator/api/core').InstrumenterContext | undefined; + } +} diff --git a/packages/javascript-mutator/CHANGELOG.md b/packages/javascript-mutator/CHANGELOG.md index 2ed1b7671e..d243c5775c 100644 --- a/packages/javascript-mutator/CHANGELOG.md +++ b/packages/javascript-mutator/CHANGELOG.md @@ -3,6 +3,99 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [4.0.0-beta.10](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.9...v4.0.0-beta.10) (2020-10-05) + +**Note:** Version bump only for package @stryker-mutator/javascript-mutator + + + + + +# [4.0.0-beta.9](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.8...v4.0.0-beta.9) (2020-09-30) + +**Note:** Version bump only for package @stryker-mutator/javascript-mutator + + + + + +# [4.0.0-beta.8](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.7...v4.0.0-beta.8) (2020-09-22) + +**Note:** Version bump only for package @stryker-mutator/javascript-mutator + + + + + +# [4.0.0-beta.7](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.6...v4.0.0-beta.7) (2020-09-17) + +**Note:** Version bump only for package @stryker-mutator/javascript-mutator + + + + + +# [4.0.0-beta.6](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.5...v4.0.0-beta.6) (2020-09-10) + +**Note:** Version bump only for package @stryker-mutator/javascript-mutator + + + + + +# [4.0.0-beta.5](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.4...v4.0.0-beta.5) (2020-09-09) + +**Note:** Version bump only for package @stryker-mutator/javascript-mutator + + + + + +# [4.0.0-beta.4](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.3...v4.0.0-beta.4) (2020-08-29) + +**Note:** Version bump only for package @stryker-mutator/javascript-mutator + + + + + +# [4.0.0-beta.3](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.2...v4.0.0-beta.3) (2020-08-19) + +**Note:** Version bump only for package @stryker-mutator/javascript-mutator + + + + + +# [4.0.0-beta.2](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.1...v4.0.0-beta.2) (2020-08-07) + +**Note:** Version bump only for package @stryker-mutator/javascript-mutator + + + + + +# [4.0.0-beta.1](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.0...v4.0.0-beta.1) (2020-07-17) + +**Note:** Version bump only for package @stryker-mutator/javascript-mutator + + + + + +# [4.0.0-beta.0](https://github.com/stryker-mutator/stryker/compare/v3.3.1...v4.0.0-beta.0) (2020-07-10) + + +### Features + +* **api:** add id to Mutant interface ([#2255](https://github.com/stryker-mutator/stryker/issues/2255)) ([cfc9053](https://github.com/stryker-mutator/stryker/commit/cfc90537d0b9815cba2b44b9681d171ca602766e)) +* **checker:** add checker api ([#2240](https://github.com/stryker-mutator/stryker/issues/2240)) ([d463f86](https://github.com/stryker-mutator/stryker/commit/d463f8639437c114da4fe30115652e8a470dd179)), closes [#1514](https://github.com/stryker-mutator/stryker/issues/1514) [#1980](https://github.com/stryker-mutator/stryker/issues/1980) +* **mutator:** remove `Mutator` API ([3ca89cf](https://github.com/stryker-mutator/stryker/commit/3ca89cf7e23af70f83e0c0ac02ab5241fc0790ff)) + + + + + ## [3.3.1](https://github.com/stryker-mutator/stryker/compare/v3.3.0...v3.3.1) (2020-07-04) **Note:** Version bump only for package @stryker-mutator/javascript-mutator diff --git a/packages/javascript-mutator/package.json b/packages/javascript-mutator/package.json index deafe422a4..e3ff8d6b96 100644 --- a/packages/javascript-mutator/package.json +++ b/packages/javascript-mutator/package.json @@ -1,13 +1,9 @@ { "name": "@stryker-mutator/javascript-mutator", - "version": "3.3.1", + "version": "4.0.0-beta.10", "description": "A plugin for javascript projects using Stryker", "main": "src/index.js", - "scripts": { - "test": "nyc --exclude-after-remap=false --check-coverage --reporter=html --report-dir=reports/coverage --lines 85 --functions 90 --branches 60 npm run mocha", - "mocha": "mocha \"test/helpers/**/*.js\" \"test/unit/**/*.js\" \"test/integration/**/*.js\"", - "stryker": "node ../core/bin/stryker run" - }, + "scripts": {}, "repository": { "type": "git", "url": "https://github.com/stryker-mutator/stryker" @@ -34,24 +30,5 @@ "Sander Koenders " ], "homepage": "https://github.com/stryker-mutator/stryker/tree/master/packages/javascript-mutator#readme", - "license": "Apache-2.0", - "dependencies": { - "@babel/generator": "~7.9.4", - "@babel/parser": "~7.9.4", - "@babel/traverse": "~7.9.5", - "@stryker-mutator/api": "^3.3.1", - "tslib": "~2.0.0" - }, - "peerDependencies": { - "@stryker-mutator/core": "^3.0.0" - }, - "devDependencies": { - "@babel/types": "~7.9.0", - "@stryker-mutator/mutator-specification": "^3.3.1", - "@stryker-mutator/test-helpers": "^3.3.1", - "@types/babel__generator": "^7.0.0", - "@types/babel__traverse": "^7.0.0", - "@types/lodash.clonedeep": "^4.5.6", - "@types/node": "^14.0.1" - } + "license": "Apache-2.0" } diff --git a/packages/javascript-mutator/src/JavaScriptMutator.ts b/packages/javascript-mutator/src/JavaScriptMutator.ts deleted file mode 100644 index c714bcd434..0000000000 --- a/packages/javascript-mutator/src/JavaScriptMutator.ts +++ /dev/null @@ -1,46 +0,0 @@ -import * as types from '@babel/types'; -import { File } from '@stryker-mutator/api/core'; -import { Logger } from '@stryker-mutator/api/logging'; -import { Mutant, Mutator } from '@stryker-mutator/api/mutant'; -import { commonTokens, tokens } from '@stryker-mutator/api/plugin'; - -import BabelParser from './helpers/BabelParser'; -import { NodeMutator } from './mutators/NodeMutator'; -import { NODE_MUTATORS_TOKEN, PARSER_TOKEN } from './helpers/tokens'; - -export class JavaScriptMutator implements Mutator { - public static inject = tokens(commonTokens.logger, NODE_MUTATORS_TOKEN, PARSER_TOKEN); - constructor(private readonly log: Logger, private readonly mutators: readonly NodeMutator[], private readonly parser: BabelParser) {} - - public mutate(inputFiles: File[]): Mutant[] { - const mutants: Mutant[] = []; - - inputFiles.forEach((file) => { - const ast = this.parser.parse(file.textContent); - - this.parser.getNodes(ast).forEach((node) => { - this.mutators.forEach((mutator) => { - const fileName = file.name; - const mutatorName = mutator.name; - - mutator.mutate(node).forEach(([original, mutation]) => { - if (original.start !== null && original.end !== null) { - const replacement = types.isNode(mutation) ? this.parser.generateCode(mutation) : mutation.raw; - - mutants.push({ - fileName: fileName, - mutatorName: mutatorName, - range: [original.start, original.end], - replacement, - }); - - this.log.trace(`Generated mutant for mutator ${mutatorName} in file ${fileName} with replacement code "${replacement}"`); - } - }); - }); - }); - }); - - return mutants; - } -} diff --git a/packages/javascript-mutator/src/helpers/BabelParser.ts b/packages/javascript-mutator/src/helpers/BabelParser.ts deleted file mode 100644 index eae51c9168..0000000000 --- a/packages/javascript-mutator/src/helpers/BabelParser.ts +++ /dev/null @@ -1,62 +0,0 @@ -import generate from '@babel/generator'; -import { parse, ParserOptions } from '@babel/parser'; -import traverse, { NodePath } from '@babel/traverse'; -import * as types from '@babel/types'; -import { Logger } from '@stryker-mutator/api/logging'; -import { commonTokens, tokens } from '@stryker-mutator/api/plugin'; -import { MutatorDescriptor } from '@stryker-mutator/api/core'; - -import { NodeWithParent } from './ParentNode'; - -export default class BabelParser { - public static inject = tokens(commonTokens.logger, commonTokens.mutatorDescriptor); - private readonly options: ParserOptions; - - constructor(private readonly log: Logger, mutatorDescriptor: MutatorDescriptor) { - this.options = this.createOptions(mutatorDescriptor.plugins); - } - - public parse(code: string): types.File { - return parse(code, this.options); - } - - private createOptions(pluginOverrides: Array | null): ParserOptions { - const plugins = pluginOverrides || [ - 'asyncGenerators', - 'bigInt', - 'classProperties', - 'dynamicImport', - 'flow', - 'jsx', - 'objectRestSpread', - ['decorators', { decoratorsBeforeExport: true }] as any, - ]; - const options: ParserOptions = { - plugins, - sourceType: 'unambiguous', - }; - if (this.log.isDebugEnabled()) { - this.log.debug(`Using options ${JSON.stringify(options)}`); - } - return options; - } - - public getNodes(ast: types.File): NodeWithParent[] { - const nodes: NodeWithParent[] = []; - - traverse(ast, { - enter(path: NodePath) { - const node: NodeWithParent = path.node; - node.parent = path.parent as any; - Object.freeze(node); - nodes.push(node); - }, - }); - - return nodes; - } - - public generateCode(ast: types.Node) { - return generate(ast).code; - } -} diff --git a/packages/javascript-mutator/src/helpers/NodeGenerator.ts b/packages/javascript-mutator/src/helpers/NodeGenerator.ts deleted file mode 100644 index a9b2037bed..0000000000 --- a/packages/javascript-mutator/src/helpers/NodeGenerator.ts +++ /dev/null @@ -1,10 +0,0 @@ -import * as types from '@babel/types'; - -export class NodeGenerator { - public static createMutatedCloneWithProperties(originalNode: types.Node, props: { [key: string]: any }): types.Node { - return { - ...originalNode, - ...props, - }; - } -} diff --git a/packages/javascript-mutator/src/helpers/ParentNode.ts b/packages/javascript-mutator/src/helpers/ParentNode.ts deleted file mode 100644 index f4c43697b5..0000000000 --- a/packages/javascript-mutator/src/helpers/ParentNode.ts +++ /dev/null @@ -1,7 +0,0 @@ -import * as types from '@babel/types'; - -export default interface NodeParent { - parent?: types.Node; -} - -export type NodeWithParent = types.Node & NodeParent; diff --git a/packages/javascript-mutator/src/helpers/tokens.ts b/packages/javascript-mutator/src/helpers/tokens.ts deleted file mode 100644 index 6b79f79779..0000000000 --- a/packages/javascript-mutator/src/helpers/tokens.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const PARSER_TOKEN = 'parser'; -export const NODE_MUTATORS_TOKEN = 'NodeMutators'; diff --git a/packages/javascript-mutator/src/index.ts b/packages/javascript-mutator/src/index.ts index 2e47f90b32..4f19ca877a 100644 --- a/packages/javascript-mutator/src/index.ts +++ b/packages/javascript-mutator/src/index.ts @@ -1,13 +1 @@ -import { commonTokens, declareFactoryPlugin, Injector, OptionsContext, PluginKind, tokens } from '@stryker-mutator/api/plugin'; - -import { JavaScriptMutator } from './JavaScriptMutator'; -import { nodeMutators } from './mutators'; -import { NODE_MUTATORS_TOKEN, PARSER_TOKEN } from './helpers/tokens'; -import BabelParser from './helpers/BabelParser'; - -export const strykerPlugins = [declareFactoryPlugin(PluginKind.Mutator, 'javascript', javaScriptMutatorFactory)]; - -function javaScriptMutatorFactory(injector: Injector): JavaScriptMutator { - return injector.provideValue(NODE_MUTATORS_TOKEN, nodeMutators).provideClass(PARSER_TOKEN, BabelParser).injectClass(JavaScriptMutator); -} -javaScriptMutatorFactory.inject = tokens(commonTokens.injector); +console.warn('Mutator plugins are no longer needed in Stryker 4.0. Please remove "@stryker-mutator/javascript-mutator" from your devDependencies.'); diff --git a/packages/javascript-mutator/src/mutators/ArithmeticOperatorMutator.ts b/packages/javascript-mutator/src/mutators/ArithmeticOperatorMutator.ts deleted file mode 100644 index 3581edefc5..0000000000 --- a/packages/javascript-mutator/src/mutators/ArithmeticOperatorMutator.ts +++ /dev/null @@ -1,35 +0,0 @@ -import * as types from '@babel/types'; - -import { NodeGenerator } from '../helpers/NodeGenerator'; - -import { NodeMutator } from './NodeMutator'; - -export default class ArithmeticOperatorMutator implements NodeMutator { - private readonly operators: { [targetedOperator: string]: string | string[] } = { - '+': '-', - '-': '+', - '*': '/', - '/': '*', - '%': '*', - }; - - public name = 'ArithmeticOperator'; - - public mutate(node: types.Node): Array<[types.Node, types.Node | { raw: string }]> { - if (types.isBinaryExpression(node)) { - let mutatedOperators = this.operators[node.operator]; - if (mutatedOperators) { - if (typeof mutatedOperators === 'string') { - mutatedOperators = [mutatedOperators]; - } - - return mutatedOperators.map((mutatedOperator) => [ - node, - NodeGenerator.createMutatedCloneWithProperties(node, { operator: mutatedOperator as any }), - ]); - } - } - - return []; - } -} diff --git a/packages/javascript-mutator/src/mutators/ArrayDeclarationMutator.ts b/packages/javascript-mutator/src/mutators/ArrayDeclarationMutator.ts deleted file mode 100644 index 5da03840ae..0000000000 --- a/packages/javascript-mutator/src/mutators/ArrayDeclarationMutator.ts +++ /dev/null @@ -1,27 +0,0 @@ -import * as types from '@babel/types'; - -import { NodeMutator } from './NodeMutator'; - -/** - * Represents a mutator which can remove the content of an array's elements. - */ -export default class ArrayDeclarationMutator implements NodeMutator { - public name = 'ArrayDeclaration'; - - public mutate(node: types.Node): Array<[types.Node, types.Node | { raw: string }]> { - if (types.isArrayExpression(node)) { - return [ - // replace [...] - node.elements.length - ? [node, { raw: '[]' }] // raw string here - : [node, { raw: '["Stryker was here"]' }], - ]; - } else if ((types.isCallExpression(node) || types.isNewExpression(node)) && types.isIdentifier(node.callee) && node.callee.name === 'Array') { - const newPrefix = types.isNewExpression(node) ? 'new ' : ''; - const mutatedCallArgs = node.arguments && node.arguments.length ? '' : '[]'; - return [[node, { raw: `${newPrefix}Array(${mutatedCallArgs})` }]]; - } else { - return []; - } - } -} diff --git a/packages/javascript-mutator/src/mutators/ArrowFunctionMutator.ts b/packages/javascript-mutator/src/mutators/ArrowFunctionMutator.ts deleted file mode 100644 index aaadc1e7a5..0000000000 --- a/packages/javascript-mutator/src/mutators/ArrowFunctionMutator.ts +++ /dev/null @@ -1,16 +0,0 @@ -import * as types from '@babel/types'; - -import { NodeMutator } from './NodeMutator'; - -/** - * Represents a mutator which can remove the content of a Object. - */ -export default class ArrowFunctionMutator implements NodeMutator { - public name = 'ArrowFunction'; - - public mutate(node: types.Node): Array<[types.Node, types.Node | { raw: string }]> { - return types.isArrowFunctionExpression(node) && !types.isBlockStatement(node.body) - ? [[node, { raw: '() => undefined' }]] // raw string replacement - : []; - } -} diff --git a/packages/javascript-mutator/src/mutators/BlockStatementMutator.ts b/packages/javascript-mutator/src/mutators/BlockStatementMutator.ts deleted file mode 100644 index c427fc95c9..0000000000 --- a/packages/javascript-mutator/src/mutators/BlockStatementMutator.ts +++ /dev/null @@ -1,20 +0,0 @@ -import * as types from '@babel/types'; - -import { NodeGenerator } from '../helpers/NodeGenerator'; - -import { NodeMutator } from './NodeMutator'; - -/** - * Represents a mutator which can remove the content of a Block. - */ -export default class BlockStatementMutator implements NodeMutator { - public name = 'BlockStatement'; - - public mutate(node: types.Node): Array<[types.Node, types.Node | { raw: string }]> { - return types.isBlockStatement(node) && node.body.length > 0 - ? [ - [node, NodeGenerator.createMutatedCloneWithProperties(node, { body: [] })], // `{}` - ] - : []; - } -} diff --git a/packages/javascript-mutator/src/mutators/BooleanLiteralMutator.ts b/packages/javascript-mutator/src/mutators/BooleanLiteralMutator.ts deleted file mode 100644 index be36d1733f..0000000000 --- a/packages/javascript-mutator/src/mutators/BooleanLiteralMutator.ts +++ /dev/null @@ -1,22 +0,0 @@ -import * as types from '@babel/types'; - -import { NodeGenerator } from '../helpers/NodeGenerator'; - -import { NodeMutator } from './NodeMutator'; - -export default class BooleanLiteralMutator implements NodeMutator { - public name = 'BooleanLiteral'; - - private readonly unaryBooleanPrefix = '!'; - - public mutate(node: types.Node): Array<[types.Node, types.Node | { raw: string }]> { - // true -> false or false -> true - if (types.isBooleanLiteral(node)) { - return [[node, NodeGenerator.createMutatedCloneWithProperties(node, { value: !node.value })]]; - } else if (types.isUnaryExpression(node) && node.operator === this.unaryBooleanPrefix && node.prefix) { - return [[node, node.argument]]; - } - - return []; - } -} diff --git a/packages/javascript-mutator/src/mutators/ConditionalExpressionMutator.ts b/packages/javascript-mutator/src/mutators/ConditionalExpressionMutator.ts deleted file mode 100644 index 7b437146c2..0000000000 --- a/packages/javascript-mutator/src/mutators/ConditionalExpressionMutator.ts +++ /dev/null @@ -1,63 +0,0 @@ -import * as types from '@babel/types'; - -import { NodeGenerator } from '../helpers/NodeGenerator'; -import { NodeWithParent } from '../helpers/ParentNode'; - -import { NodeMutator } from './NodeMutator'; - -/** - * Represents a mutator which can remove the conditional clause from statements. - */ -export default class ConditionalExpressionMutator implements NodeMutator { - private readonly validOperators: string[] = ['!=', '!==', '&&', '<', '<=', '==', '===', '>', '>=', '||']; - - public name = 'ConditionalExpression'; - - private hasValidParent(node: NodeWithParent): boolean { - return ( - !node.parent || - !( - types.isForStatement(node.parent) || - types.isWhileStatement(node.parent) || - types.isIfStatement(node.parent) || - types.isDoWhileStatement(node.parent) - ) - ); - } - - private isValidOperator(operator: string): boolean { - return this.validOperators.includes(operator); - } - - public mutate(node: types.Node): Array<[types.Node, types.Node | { raw: string }]> { - if ((types.isBinaryExpression(node) || types.isLogicalExpression(node)) && this.hasValidParent(node) && this.isValidOperator(node.operator)) { - return [ - // raw string mutations - [node, { raw: 'true' }], - [node, { raw: 'false' }], - ]; - } else if (types.isDoWhileStatement(node) || types.isWhileStatement(node)) { - return [[node.test, { raw: 'false' }]]; - } else if (types.isForStatement(node)) { - if (!node.test) { - return [[node, NodeGenerator.createMutatedCloneWithProperties(node, { test: types.booleanLiteral(false) })]]; - } else { - return [[node.test, { raw: 'false' }]]; - } - } else if (types.isIfStatement(node)) { - return [ - // raw string mutations in the `if` condition - [node.test, { raw: 'true' }], - [node.test, { raw: 'false' }], - ]; - } else if ( - types.isSwitchCase(node) && - // if not a fallthrough case - node.consequent.length > 0 - ) { - return [[node, NodeGenerator.createMutatedCloneWithProperties(node, { consequent: [] })]]; - } - - return []; - } -} diff --git a/packages/javascript-mutator/src/mutators/EqualityOperatorMutator.ts b/packages/javascript-mutator/src/mutators/EqualityOperatorMutator.ts deleted file mode 100644 index 062c8abf37..0000000000 --- a/packages/javascript-mutator/src/mutators/EqualityOperatorMutator.ts +++ /dev/null @@ -1,38 +0,0 @@ -import * as types from '@babel/types'; - -import { NodeGenerator } from '../helpers/NodeGenerator'; - -import { NodeMutator } from './NodeMutator'; - -export default class EqualityOperatorMutator implements NodeMutator { - private readonly operators: { [targetedOperator: string]: string | string[] } = { - '<': ['<=', '>='], - '<=': ['<', '>'], - '>': ['>=', '<='], - '>=': ['>', '<'], - '==': '!=', - '!=': '==', - '===': '!==', - '!==': '===', - }; - - public name = 'EqualityOperator'; - - public mutate(node: types.Node): Array<[types.Node, types.Node | { raw: string }]> { - if (types.isBinaryExpression(node)) { - let mutatedOperators = this.operators[node.operator]; - if (mutatedOperators) { - if (typeof mutatedOperators === 'string') { - mutatedOperators = [mutatedOperators]; - } - - return mutatedOperators.map((mutatedOperator) => [ - node, - NodeGenerator.createMutatedCloneWithProperties(node, { operator: mutatedOperator as any }), - ]); - } - } - - return []; - } -} diff --git a/packages/javascript-mutator/src/mutators/LogicalOperatorMutator.ts b/packages/javascript-mutator/src/mutators/LogicalOperatorMutator.ts deleted file mode 100644 index 0fea9828b2..0000000000 --- a/packages/javascript-mutator/src/mutators/LogicalOperatorMutator.ts +++ /dev/null @@ -1,32 +0,0 @@ -import * as types from '@babel/types'; - -import { NodeGenerator } from '../helpers/NodeGenerator'; - -import { NodeMutator } from './NodeMutator'; - -export default class LogicalOperatorMutator implements NodeMutator { - private readonly operators: { [targetedOperator: string]: string | string[] } = { - '&&': '||', - '||': '&&', - }; - - public name = 'LogicalOperator'; - - public mutate(node: types.Node): Array<[types.Node, types.Node | { raw: string }]> { - if (types.isLogicalExpression(node)) { - let mutatedOperators = this.operators[node.operator]; - if (mutatedOperators) { - if (typeof mutatedOperators === 'string') { - mutatedOperators = [mutatedOperators]; - } - - return mutatedOperators.map((mutatedOperator) => [ - node, - NodeGenerator.createMutatedCloneWithProperties(node, { operator: mutatedOperator as any }), - ]); - } - } - - return []; - } -} diff --git a/packages/javascript-mutator/src/mutators/NodeMutator.ts b/packages/javascript-mutator/src/mutators/NodeMutator.ts deleted file mode 100644 index 5f017bfe94..0000000000 --- a/packages/javascript-mutator/src/mutators/NodeMutator.ts +++ /dev/null @@ -1,30 +0,0 @@ -import * as types from '@babel/types'; - -import { NodeWithParent } from '../helpers/ParentNode'; - -/** - * Represents a class which can mutate parts of an Abstract Syntax Tree. - */ -export interface NodeMutator { - /** - * The name of the Mutator which may be used by reporters. - */ - name: string; - - /** - * Applies the Mutator to a Node. This can result in one or more mutated Nodes, or null if no mutation was applied. - * This method will be called on every node of the abstract syntax tree, - * implementing mutators should decide themselves if they want to mutate this specific node. - * - * If the mutator wants to mutate the node, it should return a array of mutated nodes, - * as an array of tuples that specify which node is replaced and - * what it should be replaced with (may be a raw string); - * otherwise an empty array. - * - * A mutated node may be based on a clone of the original node or just a brand new node. - * - * @param node A FROZEN Node which could be cloned and mutated. - * @returns An array of mutations, as tuples. - */ - mutate(node: NodeWithParent): Array<[types.Node, types.Node | { raw: string }]>; -} diff --git a/packages/javascript-mutator/src/mutators/ObjectLiteralMutator.ts b/packages/javascript-mutator/src/mutators/ObjectLiteralMutator.ts deleted file mode 100644 index f5fd3cb9bd..0000000000 --- a/packages/javascript-mutator/src/mutators/ObjectLiteralMutator.ts +++ /dev/null @@ -1,16 +0,0 @@ -import * as types from '@babel/types'; - -import { NodeMutator } from './NodeMutator'; - -/** - * Represents a mutator which can remove the content of a Object. - */ -export default class ObjectLiteralMutator implements NodeMutator { - public name = 'ObjectLiteral'; - - public mutate(node: types.Node): Array<[types.Node, types.Node | { raw: string }]> { - return types.isObjectExpression(node) && node.properties.length > 0 - ? [[node, { raw: '{}' }]] // raw string replacement - : []; - } -} diff --git a/packages/javascript-mutator/src/mutators/StringLiteralMutator.ts b/packages/javascript-mutator/src/mutators/StringLiteralMutator.ts deleted file mode 100644 index 7e0dd4451d..0000000000 --- a/packages/javascript-mutator/src/mutators/StringLiteralMutator.ts +++ /dev/null @@ -1,30 +0,0 @@ -import * as types from '@babel/types'; - -import { NodeWithParent } from '../helpers/ParentNode'; - -import { NodeMutator } from './NodeMutator'; - -export default class StringLiteralMutator implements NodeMutator { - public name = 'StringLiteral'; - - public mutate(node: NodeWithParent): Array<[types.Node, types.Node | { raw: string }]> { - if (types.isTemplateLiteral(node)) { - return [ - [ - node, - { - raw: node.quasis.length === 1 && node.quasis[0].value.raw.length === 0 ? '"Stryker was here!"' : '""', - }, - ], - ]; - } else if ((!node.parent || this.isDeclarationOrJSX(node.parent)) && types.isStringLiteral(node)) { - return [[node, { raw: node.value.length === 0 ? '"Stryker was here!"' : '""' }]]; - } else { - return []; - } - } - - private isDeclarationOrJSX(parent?: types.Node) { - return !types.isImportDeclaration(parent) && !types.isExportDeclaration(parent) && !types.isJSXAttribute(parent); - } -} diff --git a/packages/javascript-mutator/src/mutators/UnaryOperatorMutator.ts b/packages/javascript-mutator/src/mutators/UnaryOperatorMutator.ts deleted file mode 100644 index 49982ac572..0000000000 --- a/packages/javascript-mutator/src/mutators/UnaryOperatorMutator.ts +++ /dev/null @@ -1,25 +0,0 @@ -import * as types from '@babel/types'; - -import { NodeGenerator } from '../helpers/NodeGenerator'; - -import { NodeMutator } from './NodeMutator'; - -export default class UnaryOperatorMutator implements NodeMutator { - public name = 'UnaryOperator'; - - private readonly operators: { [targetedOperator: string]: string } = { - '+': '-', - '-': '+', - '~': '', - }; - - public mutate(node: types.Node): Array<[types.Node, types.Node | { raw: string }]> { - if (types.isUnaryExpression(node) && this.operators[node.operator] !== undefined && node.prefix) { - return this.operators[node.operator].length > 0 - ? [[node, NodeGenerator.createMutatedCloneWithProperties(node, { operator: this.operators[node.operator] as any })]] - : [[node, node.argument]]; - } - - return []; - } -} diff --git a/packages/javascript-mutator/src/mutators/UpdateOperatorMutator.ts b/packages/javascript-mutator/src/mutators/UpdateOperatorMutator.ts deleted file mode 100644 index 7fed2731de..0000000000 --- a/packages/javascript-mutator/src/mutators/UpdateOperatorMutator.ts +++ /dev/null @@ -1,20 +0,0 @@ -import * as types from '@babel/types'; - -import { NodeGenerator } from '../helpers/NodeGenerator'; - -import { NodeMutator } from './NodeMutator'; - -export default class UpdateOperatorMutator implements NodeMutator { - public name = 'UpdateOperator'; - - private readonly operators: { [targetedOperator: string]: string } = { - '++': '--', - '--': '++', - }; - - public mutate(node: types.Node): Array<[types.Node, types.Node | { raw: string }]> { - return types.isUpdateExpression(node) && this.operators[node.operator] !== undefined - ? [[node, NodeGenerator.createMutatedCloneWithProperties(node, { operator: this.operators[node.operator] as any })]] - : []; - } -} diff --git a/packages/javascript-mutator/src/mutators/index.ts b/packages/javascript-mutator/src/mutators/index.ts deleted file mode 100644 index 7464040c3c..0000000000 --- a/packages/javascript-mutator/src/mutators/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -import ArithmeticOperatorMutator from './ArithmeticOperatorMutator'; -import ArrayDeclarationMutator from './ArrayDeclarationMutator'; -import ArrowFunctionMutator from './ArrowFunctionMutator'; -import BlockStatementMutator from './BlockStatementMutator'; -import BooleanLiteralMutator from './BooleanLiteralMutator'; -import ConditionalExpressionMutator from './ConditionalExpressionMutator'; -import EqualityOperatorMutator from './EqualityOperatorMutator'; -import ObjectLiteralMutator from './ObjectLiteralMutator'; -import StringLiteralMutator from './StringLiteralMutator'; -import LogicalOperatorMutator from './LogicalOperatorMutator'; -import UnaryOperatorMutator from './UnaryOperatorMutator'; -import UpdateOperatorMutator from './UpdateOperatorMutator'; - -export const nodeMutators = Object.freeze([ - new ArithmeticOperatorMutator(), - new ArrayDeclarationMutator(), - new ArrowFunctionMutator(), - new BlockStatementMutator(), - new BooleanLiteralMutator(), - new ConditionalExpressionMutator(), - new EqualityOperatorMutator(), - new LogicalOperatorMutator(), - new ObjectLiteralMutator(), - new StringLiteralMutator(), - new UnaryOperatorMutator(), - new UpdateOperatorMutator(), -]); diff --git a/packages/javascript-mutator/test/helpers/globals.ts b/packages/javascript-mutator/test/helpers/globals.ts deleted file mode 100644 index fe2acd2af6..0000000000 --- a/packages/javascript-mutator/test/helpers/globals.ts +++ /dev/null @@ -1,29 +0,0 @@ -declare const sandbox: sinon.SinonSandbox; -declare const logMock: LogMock; -namespace NodeJS { - export interface Global { - sandbox: sinon.SinonSandbox; - logMock: LogMock; - } -} - -type Mock = { - [P in keyof T]: sinon.SinonStub; -}; - -interface LogMock { - setLevel: sinon.SinonStub; - isLevelEnabled: sinon.SinonStub; - isTraceEnabled: sinon.SinonStub; - isDebugEnabled: sinon.SinonStub; - isInfoEnabled: sinon.SinonStub; - isWarnEnabled: sinon.SinonStub; - isErrorEnabled: sinon.SinonStub; - isFatalEnabled: sinon.SinonStub; - trace: sinon.SinonStub; - debug: sinon.SinonStub; - info: sinon.SinonStub; - warn: sinon.SinonStub; - error: sinon.SinonStub; - fatal: sinon.SinonStub; -} diff --git a/packages/javascript-mutator/test/helpers/initChai.ts b/packages/javascript-mutator/test/helpers/initChai.ts deleted file mode 100644 index 514154da42..0000000000 --- a/packages/javascript-mutator/test/helpers/initChai.ts +++ /dev/null @@ -1,6 +0,0 @@ -import * as chai from 'chai'; -import * as chaiAsPromised from 'chai-as-promised'; -import * as sinonChai from 'sinon-chai'; - -chai.use(sinonChai); -chai.use(chaiAsPromised); diff --git a/packages/javascript-mutator/test/helpers/initSinon.ts b/packages/javascript-mutator/test/helpers/initSinon.ts deleted file mode 100644 index 3f17ab7b90..0000000000 --- a/packages/javascript-mutator/test/helpers/initSinon.ts +++ /dev/null @@ -1,9 +0,0 @@ -import * as sinon from 'sinon'; - -beforeEach(() => { - global.sandbox = sinon.createSandbox(); -}); - -afterEach(() => { - global.sandbox.restore(); -}); diff --git a/packages/javascript-mutator/test/helpers/initSourceMaps.ts b/packages/javascript-mutator/test/helpers/initSourceMaps.ts deleted file mode 100644 index fcfbfda16c..0000000000 --- a/packages/javascript-mutator/test/helpers/initSourceMaps.ts +++ /dev/null @@ -1 +0,0 @@ -import 'source-map-support/register'; diff --git a/packages/javascript-mutator/test/helpers/mutatorAssertions.ts b/packages/javascript-mutator/test/helpers/mutatorAssertions.ts deleted file mode 100644 index 23500d05de..0000000000 --- a/packages/javascript-mutator/test/helpers/mutatorAssertions.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { File } from '@stryker-mutator/api/core'; -import { Mutant } from '@stryker-mutator/api/mutant'; -import ExpectMutation from '@stryker-mutator/mutator-specification/src/ExpectMutation'; -import { testInjector } from '@stryker-mutator/test-helpers'; -import { expect } from 'chai'; - -import { JavaScriptMutator } from '../../src/JavaScriptMutator'; -import { NodeMutator } from '../../src/mutators/NodeMutator'; -import { NODE_MUTATORS_TOKEN, PARSER_TOKEN } from '../../src/helpers/tokens'; -import BabelParser from '../../src/helpers/BabelParser'; - -type MutatorConstructor = new () => NodeMutator; - -export function verifySpecification(specification: (name: string, expectMutation: ExpectMutation) => void, MutatorClass: MutatorConstructor): void { - specification(new MutatorClass().name, (actual: string, ...expected: string[]) => expectMutation(new MutatorClass(), actual, ...expected)); -} - -export function expectMutation(mutator: NodeMutator, sourceText: string, ...expectedTexts: string[]) { - const javaScriptMutator = testInjector.injector - .provideValue(NODE_MUTATORS_TOKEN, [mutator]) - .provideClass(PARSER_TOKEN, BabelParser) - .injectClass(JavaScriptMutator); - const sourceFile = new File('file.js', sourceText); - const mutants = javaScriptMutator.mutate([sourceFile]); - expect(mutants).lengthOf(expectedTexts.length); - const actualMutantTexts = mutants.map((mutant) => mutantToString(mutant, sourceText)); - expectedTexts.forEach((expected) => expect(actualMutantTexts, `was: ${actualMutantTexts.join(',')}`).to.include(expected)); -} - -/** - * Place the mutant in the sourceText and remove all new-line tokens and excess whitespace in the mutant replacement - * @param mutant - * @param sourceText - */ -function mutantToString(mutant: Mutant, sourceText: string) { - return sourceText.substr(0, mutant.range[0]) + mutant.replacement.replace(/\s{2,}/g, ' ').replace(/\n/g, ' ') + sourceText.substr(mutant.range[1]); -} diff --git a/packages/javascript-mutator/test/unit/JavaScriptMutator.spec.ts b/packages/javascript-mutator/test/unit/JavaScriptMutator.spec.ts deleted file mode 100644 index 1dd711b336..0000000000 --- a/packages/javascript-mutator/test/unit/JavaScriptMutator.spec.ts +++ /dev/null @@ -1,195 +0,0 @@ -import { File } from '@stryker-mutator/api/core'; -import { testInjector } from '@stryker-mutator/test-helpers'; -import { expect } from 'chai'; - -import { JavaScriptMutator } from '../../src/JavaScriptMutator'; -import { nodeMutators } from '../../src/mutators'; -import { NodeMutator } from '../../src/mutators/NodeMutator'; -import BabelParser from '../../src/helpers/BabelParser'; -import { NODE_MUTATORS_TOKEN, PARSER_TOKEN } from '../../src/helpers/tokens'; - -describe('JavaScriptMutator', () => { - let selectedMutators: readonly NodeMutator[]; - - beforeEach(() => { - selectedMutators = nodeMutators; - }); - - function createSut() { - return testInjector.injector - .provideValue(NODE_MUTATORS_TOKEN, selectedMutators) - .provideClass(PARSER_TOKEN, BabelParser) - .injectClass(JavaScriptMutator); - } - - it('should generate a correct mutant', () => { - const mutator = createSut(); - const files: File[] = [new File('testFile.js', '"use strict"; var a = 1 + 2;')]; - - const mutants = mutator.mutate(files); - - expect(mutants.length).to.equal(1); - expect(mutants[0]).to.deep.equal({ - fileName: files[0].name, - mutatorName: 'ArithmeticOperator', - range: [22, 27], - replacement: '1 - 2', - }); - }); - - it('should generate mutant a correct mutant for jsx code', () => { - const mutator = createSut(); - const files: File[] = [ - new File( - 'testFile.jsx', - ` - "use strict"; - import React from 'react' - import { render } from 'react-dom' - import App from 'app/components/app' - - const hello = true; - if(hello) { - console.log("Hello world!"); - } - - render( - , - document.getElementById('appContainer') - ) - ` - ), - ]; - - const mutants = mutator.mutate(files); - - expect(mutants.length).to.equal(6); - expect(mutants).to.deep.include({ - fileName: 'testFile.jsx', - mutatorName: 'ConditionalExpression', - range: [197, 202], - replacement: 'true', - }); - }); - - it('should not mutate unknown extensions', () => { - const mutator = createSut(); - const files: File[] = [ - new File( - 'testFile.html', - ` - - - Test - - -

Hello World

- - - ` - ), - ]; - const mutants = mutator.mutate(files); - - expect(mutants.length).to.equal(0); - }); - - it('should generate mutants for flow code', () => { - const mutator = createSut(); - const files: File[] = [ - new File( - 'testFile.js', - ` - // @flow - import React from 'react' - - function getMessage(message: string) { - if(message) { - return message; - } - - return 'Hello!!'; - } - - const App = ({ if: message }: Props) => (
-

{ getMessage(message) }

-
) - - type Props = { - message: string - } - - export default App - ` - ), - ]; - - const mutants = mutator.mutate(files); - - expect(mutants.length).to.equal(6); - expect(mutants).to.deep.include({ - fileName: 'testFile.js', - mutatorName: 'ConditionalExpression', - range: [121, 128], - replacement: 'false', - }); - }); - - it('should generate mutants for js vnext code', () => { - const sut = createSut(); - const files: File[] = [ - new File( - 'testFile.js', - ` - function objectRestSpread(input) { - return { - ...input, - foo: true, - }; - } - - class ClassProperties { b = 1n; } - - async function* asyncGenerators(i) { - yield i; - yield i + 10; - } - - function dynamicImport(){ - import('./guy').then(a) - } - ` - ), - ]; - - const mutants = sut.mutate(files); - expect(mutants).lengthOf.above(2); - }); - - it('should generate mutants for multiple files', () => { - const mutator = createSut(); - const file: File = new File('testFile.js', '"use strict"; var a = 1 + 2;'); - const file2: File = new File('testFile2.js', '"use strict"; var a = 1 + 2;'); - const mutants = mutator.mutate([file, file2]); - - expect(mutants.length).to.equal(2); - }); - - it('should generate mutants when file contains a decorator', () => { - const sut = createSut(); - const files: File[] = [ - new File( - 'testFile.js', - ` - @decorator() - export class Foo { - bar = 'bar'; - }; - ` - ), - ]; - - const mutants = sut.mutate(files); - expect(mutants).lengthOf.above(0); - }); -}); diff --git a/packages/javascript-mutator/test/unit/helpers/BabelParser.spec.ts b/packages/javascript-mutator/test/unit/helpers/BabelParser.spec.ts deleted file mode 100644 index 21535b0eed..0000000000 --- a/packages/javascript-mutator/test/unit/helpers/BabelParser.spec.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { expect } from 'chai'; -import { testInjector } from '@stryker-mutator/test-helpers'; - -import BabelParser from '../../../src/helpers/BabelParser'; - -describe(BabelParser.name, () => { - function createSut() { - return testInjector.injector.injectClass(BabelParser); - } - - describe('getNodes', () => { - it('should get the correct amount of statements', () => { - const sut = createSut(); - const ast = sut.parse('"use strict"; var a = 1 + 2;'); - const nodes = sut.getNodes(ast); - expect(nodes.length).to.equal(9); - }); - }); - - describe('generateCode', () => { - it('should work with "use strict"', () => { - const sut = createSut(); - const ast = sut.parse('"use strict"; var a = 1 + 2;'); - - const result = sut.generateCode(ast); - - expect(result).to.equal('"use strict";\n\nvar a = 1 + 2;'); - }); - - it('should keep comments', () => { - const sut = createSut(); - const ast = sut.parse('var a = 1 + 2 /* Comment */;'); - const result = sut.generateCode(ast.program.body[0]); - expect(result).to.equal('var a = 1 + 2\n/* Comment */\n;'); - }); - }); - - describe('parse', () => { - it('should support scripts', () => { - const sut = createSut(); - const ast = sut.parse("var fs = require('fs'); var a = 1 + 2;"); - - expect(ast).exist; - }); - - it('should support modules', () => { - const sut = createSut(); - const ast = sut.parse("import fs from 'fs'; var a = 1 + 2;"); - - expect(ast).exist; - }); - - it('should allow to override plugins', () => { - // Arrange - testInjector.logger.isDebugEnabled.returns(true); - testInjector.mutatorDescriptor.plugins = ['optionalChaining']; - const sut = createSut(); - - // Act - const result = sut.parse('foo?.bar()'); - - // Assert - expect(sut.generateCode(result.program)).eq('foo?.bar();'); - expect(testInjector.logger.debug).calledWith('Using options {"plugins":["optionalChaining"],"sourceType":"unambiguous"}'); - }); - }); -}); diff --git a/packages/javascript-mutator/test/unit/helpers/initSinon.ts b/packages/javascript-mutator/test/unit/helpers/initSinon.ts deleted file mode 100644 index 79b73de392..0000000000 --- a/packages/javascript-mutator/test/unit/helpers/initSinon.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { testInjector } from '@stryker-mutator/test-helpers'; -import * as chai from 'chai'; -import * as chaiAsPromised from 'chai-as-promised'; -import * as sinon from 'sinon'; -import * as sinonChai from 'sinon-chai'; - -chai.use(chaiAsPromised); -chai.use(sinonChai); -afterEach(() => { - sinon.restore(); - testInjector.reset(); -}); diff --git a/packages/javascript-mutator/test/unit/mutators/ArithmeticOperatorMutator.spec.ts b/packages/javascript-mutator/test/unit/mutators/ArithmeticOperatorMutator.spec.ts deleted file mode 100644 index 83c96e9be9..0000000000 --- a/packages/javascript-mutator/test/unit/mutators/ArithmeticOperatorMutator.spec.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { ArithmeticOperatorMutatorSpec } from '@stryker-mutator/mutator-specification/src/index'; - -import ArithmeticOperatorMutator from '../../../src/mutators/ArithmeticOperatorMutator'; -import { verifySpecification } from '../../helpers/mutatorAssertions'; - -verifySpecification(ArithmeticOperatorMutatorSpec, ArithmeticOperatorMutator); diff --git a/packages/javascript-mutator/test/unit/mutators/ArrayDeclarationMutator.spec.ts b/packages/javascript-mutator/test/unit/mutators/ArrayDeclarationMutator.spec.ts deleted file mode 100644 index 91944a316f..0000000000 --- a/packages/javascript-mutator/test/unit/mutators/ArrayDeclarationMutator.spec.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { ArrayDeclarationMutatorSpec } from '@stryker-mutator/mutator-specification/src/index'; - -import ArrayDeclarationMutator from '../../../src/mutators/ArrayDeclarationMutator'; -import { verifySpecification } from '../../helpers/mutatorAssertions'; - -verifySpecification(ArrayDeclarationMutatorSpec, ArrayDeclarationMutator); diff --git a/packages/javascript-mutator/test/unit/mutators/ArrowFunctionMutator.spec.ts b/packages/javascript-mutator/test/unit/mutators/ArrowFunctionMutator.spec.ts deleted file mode 100644 index 861288b8be..0000000000 --- a/packages/javascript-mutator/test/unit/mutators/ArrowFunctionMutator.spec.ts +++ /dev/null @@ -1,6 +0,0 @@ -import ArrowFunctionMutatorSpec from '@stryker-mutator/mutator-specification/src/ArrowFunctionMutatorSpec'; - -import ArrowFunctionMutator from '../../../src/mutators/ArrowFunctionMutator'; -import { verifySpecification } from '../../helpers/mutatorAssertions'; - -verifySpecification(ArrowFunctionMutatorSpec, ArrowFunctionMutator); diff --git a/packages/javascript-mutator/test/unit/mutators/BlockStatementMutator.spec.ts b/packages/javascript-mutator/test/unit/mutators/BlockStatementMutator.spec.ts deleted file mode 100644 index 213626a6c1..0000000000 --- a/packages/javascript-mutator/test/unit/mutators/BlockStatementMutator.spec.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { BlockStatementMutatorSpec } from '@stryker-mutator/mutator-specification/src/index'; - -import BlockStatementMutator from '../../../src/mutators/BlockStatementMutator'; -import { verifySpecification } from '../../helpers/mutatorAssertions'; - -verifySpecification(BlockStatementMutatorSpec, BlockStatementMutator); diff --git a/packages/javascript-mutator/test/unit/mutators/BooleanLiteralMutator.spec.ts b/packages/javascript-mutator/test/unit/mutators/BooleanLiteralMutator.spec.ts deleted file mode 100644 index 0ac1dae630..0000000000 --- a/packages/javascript-mutator/test/unit/mutators/BooleanLiteralMutator.spec.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { BooleanLiteralMutatorSpec } from '@stryker-mutator/mutator-specification/src/index'; - -import BooleanLiteralMutator from '../../../src/mutators/BooleanLiteralMutator'; -import { verifySpecification } from '../../helpers/mutatorAssertions'; - -verifySpecification(BooleanLiteralMutatorSpec, BooleanLiteralMutator); diff --git a/packages/javascript-mutator/test/unit/mutators/ConditionalExpressionMutator.spec.ts b/packages/javascript-mutator/test/unit/mutators/ConditionalExpressionMutator.spec.ts deleted file mode 100644 index 2a126ed2f3..0000000000 --- a/packages/javascript-mutator/test/unit/mutators/ConditionalExpressionMutator.spec.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { ConditionalExpressionMutatorSpec } from '@stryker-mutator/mutator-specification/src/index'; - -import ConditionalExpressionMutator from '../../../src/mutators/ConditionalExpressionMutator'; -import { verifySpecification } from '../../helpers/mutatorAssertions'; - -verifySpecification(ConditionalExpressionMutatorSpec, ConditionalExpressionMutator); diff --git a/packages/javascript-mutator/test/unit/mutators/EqualityOperatorMutator.spec.ts b/packages/javascript-mutator/test/unit/mutators/EqualityOperatorMutator.spec.ts deleted file mode 100644 index a8a8f8087a..0000000000 --- a/packages/javascript-mutator/test/unit/mutators/EqualityOperatorMutator.spec.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { EqualityOperatorMutatorSpec } from '@stryker-mutator/mutator-specification/src/index'; - -import EqualityOperatorMutator from '../../../src/mutators/EqualityOperatorMutator'; -import { verifySpecification } from '../../helpers/mutatorAssertions'; - -verifySpecification(EqualityOperatorMutatorSpec, EqualityOperatorMutator); diff --git a/packages/javascript-mutator/test/unit/mutators/LogicalOperatorMutator.spec.ts b/packages/javascript-mutator/test/unit/mutators/LogicalOperatorMutator.spec.ts deleted file mode 100644 index 616dfb343f..0000000000 --- a/packages/javascript-mutator/test/unit/mutators/LogicalOperatorMutator.spec.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { LogicalOperatorMutatorSpec } from '@stryker-mutator/mutator-specification/src/index'; - -import LogicalOperatorMutator from '../../../src/mutators/LogicalOperatorMutator'; -import { verifySpecification } from '../../helpers/mutatorAssertions'; - -verifySpecification(LogicalOperatorMutatorSpec, LogicalOperatorMutator); diff --git a/packages/javascript-mutator/test/unit/mutators/ObjectLiteralMutator.spec.ts b/packages/javascript-mutator/test/unit/mutators/ObjectLiteralMutator.spec.ts deleted file mode 100644 index 7c1f36d749..0000000000 --- a/packages/javascript-mutator/test/unit/mutators/ObjectLiteralMutator.spec.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { ObjectLiteralMutatorSpec } from '@stryker-mutator/mutator-specification/src/index'; - -import ObjectLiteralMutator from '../../../src/mutators/ObjectLiteralMutator'; -import { verifySpecification } from '../../helpers/mutatorAssertions'; - -verifySpecification(ObjectLiteralMutatorSpec, ObjectLiteralMutator); diff --git a/packages/javascript-mutator/test/unit/mutators/StringLiteralMutator.spec.ts b/packages/javascript-mutator/test/unit/mutators/StringLiteralMutator.spec.ts deleted file mode 100644 index 3f1a29db54..0000000000 --- a/packages/javascript-mutator/test/unit/mutators/StringLiteralMutator.spec.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { StringLiteralMutatorSpec } from '@stryker-mutator/mutator-specification/src/index'; - -import StringLiteralMutator from '../../../src/mutators/StringLiteralMutator'; -import { verifySpecification } from '../../helpers/mutatorAssertions'; - -verifySpecification(StringLiteralMutatorSpec, StringLiteralMutator); diff --git a/packages/javascript-mutator/test/unit/mutators/UnaryOperatorMutator.spec.ts b/packages/javascript-mutator/test/unit/mutators/UnaryOperatorMutator.spec.ts deleted file mode 100644 index 482a3f11ef..0000000000 --- a/packages/javascript-mutator/test/unit/mutators/UnaryOperatorMutator.spec.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { UnaryOperatorMutatorSpec } from '@stryker-mutator/mutator-specification/src/index'; - -import UnaryOperatorMutator from '../../../src/mutators/UnaryOperatorMutator'; -import { verifySpecification } from '../../helpers/mutatorAssertions'; - -verifySpecification(UnaryOperatorMutatorSpec, UnaryOperatorMutator); diff --git a/packages/javascript-mutator/test/unit/mutators/UpdateOperatorMutator.spec.ts b/packages/javascript-mutator/test/unit/mutators/UpdateOperatorMutator.spec.ts deleted file mode 100644 index e4a2339e46..0000000000 --- a/packages/javascript-mutator/test/unit/mutators/UpdateOperatorMutator.spec.ts +++ /dev/null @@ -1,20 +0,0 @@ -import UpdateOperatorMutator from '../../../src/mutators/UpdateOperatorMutator'; -import { expectMutation } from '../../helpers/mutatorAssertions'; - -describe(UpdateOperatorMutator.name, () => { - it('should mutate a++ to a--', () => { - expectMutation(new UpdateOperatorMutator(), 'a++', 'a--'); - }); - - it('should mutate a-- to a++', () => { - expectMutation(new UpdateOperatorMutator(), 'a--', 'a++'); - }); - - it('should mutate ++a to --a', () => { - expectMutation(new UpdateOperatorMutator(), '++a', '--a'); - }); - - it('should mutate --a to ++a', () => { - expectMutation(new UpdateOperatorMutator(), '--a', '++a'); - }); -}); diff --git a/packages/javascript-mutator/tsconfig.stryker.json b/packages/javascript-mutator/tsconfig.stryker.json deleted file mode 100644 index 0f7ed99680..0000000000 --- a/packages/javascript-mutator/tsconfig.stryker.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": "./tsconfig.test.json", - "include": [ - "src", - "test" - ], -} diff --git a/packages/javascript-mutator/tsconfig.test.json b/packages/javascript-mutator/tsconfig.test.json index 5741644c40..981c6a6fc7 100644 --- a/packages/javascript-mutator/tsconfig.test.json +++ b/packages/javascript-mutator/tsconfig.test.json @@ -13,12 +13,6 @@ "references": [ { "path": "./tsconfig.src.json" - }, - { - "path": "../mutator-specification/tsconfig.src.json" - }, - { - "path": "../test-helpers/tsconfig.src.json" } ] -} \ No newline at end of file +} diff --git a/packages/jest-runner/.mocharc.jsonc b/packages/jest-runner/.mocharc.jsonc new file mode 100644 index 0000000000..dc3280aa96 --- /dev/null +++ b/packages/jest-runner/.mocharc.jsonc @@ -0,0 +1,3 @@ +{ + "require": "test/setup.js" +} diff --git a/packages/jest-runner/.nycrc.json b/packages/jest-runner/.nycrc.json new file mode 100644 index 0000000000..57ff700bda --- /dev/null +++ b/packages/jest-runner/.nycrc.json @@ -0,0 +1,11 @@ +{ + "exclude-after-remap": false, + "check-coverage": true, + "reporter": ["text", "html"], + "report-dir": "reports/coverage", + "lines": 80, + "functions": 80, + "statements": 80, + "branches": 75, + "include": "src/**/*.js" +} diff --git a/packages/jest-runner/.vscode/launch.json b/packages/jest-runner/.vscode/launch.json index 570048043d..582a321315 100644 --- a/packages/jest-runner/.vscode/launch.json +++ b/packages/jest-runner/.vscode/launch.json @@ -20,7 +20,10 @@ "outFiles": [ "${workspaceRoot}/test/**/*.js", "${workspaceRoot}/src/**/*.js" - ] + ], + "skipFiles": [ + "/**" + ], }, { "type": "node", @@ -38,7 +41,10 @@ "outFiles": [ "${workspaceRoot}/test/**/*.js", "${workspaceRoot}/src/**/*.js" - ] + ], + "skipFiles": [ + "/**" + ], } ] -} \ No newline at end of file +} diff --git a/packages/jest-runner/CHANGELOG.md b/packages/jest-runner/CHANGELOG.md index 6b7f003fa4..8fd8aabdd4 100644 --- a/packages/jest-runner/CHANGELOG.md +++ b/packages/jest-runner/CHANGELOG.md @@ -3,6 +3,121 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [4.0.0-beta.10](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.9...v4.0.0-beta.10) (2020-10-05) + +**Note:** Version bump only for package @stryker-mutator/jest-runner + + + + + +# [4.0.0-beta.9](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.8...v4.0.0-beta.9) (2020-09-30) + + +### Features + +* **jest-runner:** deprecate "create-react-app-ts" ([#2497](https://github.com/stryker-mutator/stryker/issues/2497)) ([0aacc7b](https://github.com/stryker-mutator/stryker/commit/0aacc7be5bb045887e96f0a8115b7e3e46e1a1ff)) + + + + + +# [4.0.0-beta.8](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.7...v4.0.0-beta.8) (2020-09-22) + +**Note:** Version bump only for package @stryker-mutator/jest-runner + + + + + +# [4.0.0-beta.7](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.6...v4.0.0-beta.7) (2020-09-17) + +**Note:** Version bump only for package @stryker-mutator/jest-runner + + + + + +# [4.0.0-beta.6](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.5...v4.0.0-beta.6) (2020-09-10) + +**Note:** Version bump only for package @stryker-mutator/jest-runner + + + + + +# [4.0.0-beta.5](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.4...v4.0.0-beta.5) (2020-09-09) + +**Note:** Version bump only for package @stryker-mutator/jest-runner + + + + + +# [4.0.0-beta.4](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.3...v4.0.0-beta.4) (2020-08-29) + + +### Features + +* **api:** rename test_runner2 -> test_runner ([#2442](https://github.com/stryker-mutator/stryker/issues/2442)) ([4d3ae97](https://github.com/stryker-mutator/stryker/commit/4d3ae9764dbd689c895b76e44f2eea76c82fabc8)) +* **jest-runner:** switch mutants using env ([#2416](https://github.com/stryker-mutator/stryker/issues/2416)) ([cad01ba](https://github.com/stryker-mutator/stryker/commit/cad01baf9f4fc3bab2ae5244627586133fb618be)) + + +### BREAKING CHANGES + +* **api:** Plugin creators should now use `'test_runner'` instead of `'test_runner2'`. + + + + + +# [4.0.0-beta.3](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.2...v4.0.0-beta.3) (2020-08-19) + + +### Features + +* **jest-runner:** remove deprecated project types ([#2361](https://github.com/stryker-mutator/stryker/issues/2361)) ([d0aa5c3](https://github.com/stryker-mutator/stryker/commit/d0aa5c3c2f676176d3fbceb24ab2cd17011c9ecf)) +* **test runner api:** remove `sandboxFileNames` injectable values ([#2369](https://github.com/stryker-mutator/stryker/issues/2369)) ([92f3bf5](https://github.com/stryker-mutator/stryker/commit/92f3bf528d0b01be1f6c219b37a5f90da0431686)), closes [#2351](https://github.com/stryker-mutator/stryker/issues/2351) + + +### BREAKING CHANGES + +* **jest-runner:** Project types `react` and `react-ts` has been removed. Please use `create-react-app` and `create-react-app-ts` respectively + + + + + +# [4.0.0-beta.2](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.1...v4.0.0-beta.2) (2020-08-07) + + +### Features + +* **jest-runner:** support mutation switching ([#2350](https://github.com/stryker-mutator/stryker/issues/2350)) ([9e6e6e0](https://github.com/stryker-mutator/stryker/commit/9e6e6e077731344ed0588d64b5c8ba2f19c8492e)) + + + + + +# [4.0.0-beta.1](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.0...v4.0.0-beta.1) (2020-07-17) + + +### Bug Fixes + +* **Jest:** Notify users of lacking Jest support ([#2322](https://github.com/stryker-mutator/stryker/issues/2322)) ([0bbc0c1](https://github.com/stryker-mutator/stryker/commit/0bbc0c119ba5d661ba9751d241ba548293738aa8)) + + + + + +# [4.0.0-beta.0](https://github.com/stryker-mutator/stryker/compare/v3.3.1...v4.0.0-beta.0) (2020-07-10) + +**Note:** Version bump only for package @stryker-mutator/jest-runner + + + + + ## [3.3.1](https://github.com/stryker-mutator/stryker/compare/v3.3.0...v3.3.1) (2020-07-04) **Note:** Version bump only for package @stryker-mutator/jest-runner diff --git a/packages/jest-runner/README.md b/packages/jest-runner/README.md index 6e525886a1..eb54019d53 100644 --- a/packages/jest-runner/README.md +++ b/packages/jest-runner/README.md @@ -51,7 +51,7 @@ The @stryker-mutator/jest-runner also provides a couple of configurable options |----|----|----|---| | projectType (optional) | The type of project you are working on. | `custom` | `custom` uses the `config` option (see below)| | | | | `create-react-app` when you are using [create-react-app](https://github.com/facebook/create-react-app) | -| | | | `create-react-app-ts` when you are using [create-react-app-typescript](https://github.com/wmonk/create-react-app-typescript) | +| | | | `create-react-app-ts` **DEPRECATED** when you are using [create-react-app-typescript](https://github.com/wmonk/create-react-app-typescript) (deprecated, please [follow the migration guide](https://create-react-app.dev/docs/adding-typescript/) and move to `create-react-app`) | | configFile (optional) | The path to your Jest config file. | undefined | | | config (optional) | Custom Jest config. This will override file-based config. | undefined | | | enableFindRelatedTests (optional) | Whether to run jest with the `--findRelatedTests` flag. When `true`, Jest will only run tests related to the mutated file per test. (See [_--findRelatedTests_](https://jestjs.io/docs/en/cli.html#findrelatedtests-spaceseparatedlistofsourcefiles)) | true | false | diff --git a/packages/jest-runner/package.json b/packages/jest-runner/package.json index dcf74f5f8c..9546ce5442 100644 --- a/packages/jest-runner/package.json +++ b/packages/jest-runner/package.json @@ -1,11 +1,13 @@ { "name": "@stryker-mutator/jest-runner", - "version": "3.3.1", + "version": "4.0.0-beta.10", "description": "A plugin to use the jest test runner and framework in Stryker, the JavaScript mutation testing framework", "main": "src/index.js", "scripts": { - "test": "nyc --exclude-after-remap=false --check-coverage --reporter=html --report-dir=reports/coverage --lines 80 --functions 80 --branches 75 npm run mocha", - "mocha": "mocha \"test/helpers/**/*.js\" \"test/unit/**/*.js\" && mocha --timeout 30000 \"test/helpers/**/*.js\" \"test/integration/**/*.js\"", + "test": "nyc npm run test:all", + "test:all": "npm run test:unit && npm run test:integration", + "test:unit": "mocha \"test/helpers/**/*.js\" \"test/unit/**/*.js\"", + "test:integration": "mocha --timeout 30000 \"test/helpers/**/*.js\" \"test/integration/**/*.js\"", "stryker": "node ../core/bin/stryker run" }, "repository": { @@ -38,21 +40,23 @@ }, "homepage": "https://github.com/stryker-mutator/stryker/tree/master/packages/jest-runner#readme", "devDependencies": { - "@stryker-mutator/test-helpers": "^3.3.1", + "@jest/types": "~26.5.2", + "@stryker-mutator/test-helpers": "4.0.0-beta.10", "@types/node": "^14.0.1", - "@types/semver": "~7.2.0", - "jest": "^26.0.1", + "@types/semver": "~7.3.1", + "jest": "~26.4.2", "react": "~16.13.0", "react-dom": "~16.13.0", "react-scripts": "~3.4.0", "react-scripts-ts": "~3.1.0" }, "peerDependencies": { - "@stryker-mutator/core": "^3.0.0", + "@stryker-mutator/core": "~4.0.0", "jest": ">= 22.0.0" }, "dependencies": { - "@stryker-mutator/api": "^3.3.1", + "@stryker-mutator/api": "4.0.0-beta.10", + "@stryker-mutator/util": "4.0.0-beta.10", "semver": "~6.3.0" }, "initStrykerConfig": { diff --git a/packages/jest-runner/schema/jest-runner-options.json b/packages/jest-runner/schema/jest-runner-options.json index eb184430ed..f8737f9e71 100644 --- a/packages/jest-runner/schema/jest-runner-options.json +++ b/packages/jest-runner/schema/jest-runner-options.json @@ -37,8 +37,6 @@ "enum": [ "create-react-app", "create-react-app-ts", - "react", - "react-ts", "custom" ] } diff --git a/packages/jest-runner/src/JestRunResult.ts b/packages/jest-runner/src/JestRunResult.ts new file mode 100644 index 0000000000..f35b982f41 --- /dev/null +++ b/packages/jest-runner/src/JestRunResult.ts @@ -0,0 +1,7 @@ +import type { Config } from '@jest/types'; +import type { AggregatedResult } from '@jest/test-result'; + +export interface JestRunResult { + results: AggregatedResult; + globalConfig: Config.GlobalConfig; +} diff --git a/packages/jest-runner/src/JestTestRunner.ts b/packages/jest-runner/src/JestTestRunner.ts index 5411270b77..7fb3f2256b 100644 --- a/packages/jest-runner/src/JestTestRunner.ts +++ b/packages/jest-runner/src/JestTestRunner.ts @@ -1,17 +1,31 @@ -import { StrykerOptions } from '@stryker-mutator/api/core'; +import { StrykerOptions, INSTRUMENTER_CONSTANTS } from '@stryker-mutator/api/core'; import { Logger } from '@stryker-mutator/api/logging'; -import { commonTokens, Injector, OptionsContext, tokens } from '@stryker-mutator/api/plugin'; -import { RunOptions, RunResult, RunStatus, TestResult, TestRunner, TestStatus } from '@stryker-mutator/api/test_runner'; +import { commonTokens, Injector, PluginContext, tokens } from '@stryker-mutator/api/plugin'; +import { + TestRunner, + MutantRunOptions, + DryRunResult, + MutantRunResult, + toMutantRunResult, + DryRunStatus, + TestResult, + TestStatus, +} from '@stryker-mutator/api/test_runner'; +import { notEmpty } from '@stryker-mutator/util'; +import type * as jest from '@jest/types'; +import type * as jestTestResult from '@jest/test-result'; + +import { SerializableError } from '@jest/types/build/TestResult'; import { jestTestAdapterFactory } from './jestTestAdapters'; import JestTestAdapter from './jestTestAdapters/JestTestAdapter'; -import { JestRunnerOptionsWithStrykerOptions } from './JestRunnerOptionsWithStrykerOptions'; import JestConfigLoader from './configLoaders/JestConfigLoader'; import { configLoaderToken, processEnvToken, jestTestAdapterToken, jestVersionToken } from './pluginTokens'; import { configLoaderFactory } from './configLoaders'; +import { JestRunnerOptionsWithStrykerOptions } from './JestRunnerOptionsWithStrykerOptions'; import JEST_OVERRIDE_OPTIONS from './jestOverrideOptions'; -export function jestTestRunnerFactory(injector: Injector) { +export function jestTestRunnerFactory(injector: Injector) { return injector .provideValue(processEnvToken, process.env) .provideValue(jestVersionToken, require('jest/package.json').version as string) @@ -22,8 +36,7 @@ export function jestTestRunnerFactory(injector: Injector) { jestTestRunnerFactory.inject = tokens(commonTokens.injector); export default class JestTestRunner implements TestRunner { - private readonly jestConfig: Jest.Configuration; - + private readonly jestConfig: jest.Config.InitialOptions; private readonly enableFindRelatedTests: boolean; public static inject = tokens(commonTokens.logger, commonTokens.options, processEnvToken, jestTestAdapterToken, configLoaderToken); @@ -40,10 +53,7 @@ export default class JestTestRunner implements TestRunner { this.jestConfig = this.mergeConfigSettings(configFromFile, (jestOptions.jest.config as any) || {}); // Get enableFindRelatedTests from stryker jest options or default to true - this.enableFindRelatedTests = jestOptions.jest.enableFindRelatedTests; - if (this.enableFindRelatedTests === undefined) { - this.enableFindRelatedTests = true; - } + this.enableFindRelatedTests = jestOptions.jest.enableFindRelatedTests ?? true; if (this.enableFindRelatedTests) { this.log.debug('Running jest with --findRelatedTests flag. Set jest.enableFindRelatedTests to false to run all tests on every mutant.'); @@ -60,69 +70,108 @@ export default class JestTestRunner implements TestRunner { this.log.debug(`Project root is ${this.jestConfig.rootDir}`); } - public async run(options: RunOptions): Promise { - this.setNodeEnv(); - const { results } = await this.jestTestAdapter.run( - this.jestConfig, - process.cwd(), - this.enableFindRelatedTests ? options.mutatedFileName : undefined - ); + public dryRun(): Promise { + return this.run(); + } + public async mutantRun({ activeMutant, sandboxFileName }: MutantRunOptions): Promise { + const fileUnderTest = this.enableFindRelatedTests ? sandboxFileName : undefined; + process.env[INSTRUMENTER_CONSTANTS.ACTIVE_MUTANT_ENV_VARIABLE] = activeMutant.id.toString(); + const dryRunResult = await this.run(fileUnderTest); + return toMutantRunResult(dryRunResult); + } - // Get the non-empty errorMessages from the jest RunResult, it's safe to cast to Array here because we filter the empty error messages - const errorMessages = results.testResults - .map((testSuite: Jest.TestResult) => testSuite.failureMessage) - .filter((errorMessage) => errorMessage) as string[]; + private async run(fileUnderTest: string | undefined = undefined): Promise { + this.setEnv(); + const all = await this.jestTestAdapter.run(this.jestConfig, process.cwd(), fileUnderTest); + return this.collectRunResult(all.results); + } - return { - errorMessages, - status: results.numRuntimeErrorTestSuites > 0 ? RunStatus.Error : RunStatus.Complete, - tests: this.processTestResults(results.testResults), - }; + private collectRunResult(results: jestTestResult.AggregatedResult): DryRunResult { + if (results.numRuntimeErrorTestSuites) { + const errorMessage = results.testResults + .map((testSuite) => this.collectSerializableErrorText(testSuite.testExecError)) + .filter(notEmpty) + .join(', '); + return { + status: DryRunStatus.Error, + errorMessage, + }; + } else { + return { + status: DryRunStatus.Complete, + tests: this.processTestResults(results.testResults), + }; + } } - private setNodeEnv() { + private collectSerializableErrorText(error: SerializableError | undefined): string | undefined { + return error && `${error.code && `${error.code} `}${error.message} ${error.stack}`; + } + + private setEnv() { // Jest CLI will set process.env.NODE_ENV to 'test' when it's null, do the same here // https://github.com/facebook/jest/blob/master/packages/jest-cli/bin/jest.js#L12-L14 if (!this.processEnvRef.NODE_ENV) { this.processEnvRef.NODE_ENV = 'test'; } + + // Force colors off: https://github.com/chalk/supports-color#info + process.env.FORCE_COLOR = '0'; } - private processTestResults(suiteResults: Jest.TestResult[]): TestResult[] { + private processTestResults(suiteResults: jestTestResult.TestResult[]): TestResult[] { const testResults: TestResult[] = []; for (const suiteResult of suiteResults) { for (const testResult of suiteResult.testResults) { - testResults.push({ - failureMessages: testResult.failureMessages, - name: testResult.fullName, - status: this.determineTestResultStatus(testResult.status), - timeSpentMs: testResult.duration ? testResult.duration : 0, - }); + let result: TestResult; + let timeSpentMs = testResult.duration ?? 0; + + switch (testResult.status) { + case 'passed': + result = { + id: testResult.fullName, + name: testResult.fullName, + status: TestStatus.Success, + timeSpentMs, + }; + break; + case 'failed': + result = { + id: testResult.fullName, + name: testResult.fullName, + failureMessage: testResult.failureMessages.join(', '), + status: TestStatus.Failed, + timeSpentMs, + }; + break; + default: + result = { + id: testResult.fullName, + name: testResult.fullName, + status: TestStatus.Skipped, + timeSpentMs, + }; + break; + } + testResults.push(result); } } return testResults; } - private determineTestResultStatus(status: Jest.Status) { - switch (status) { - case 'passed': - return TestStatus.Success; - case 'failed': - return TestStatus.Failed; - default: - return TestStatus.Skipped; - } - } - - private mergeConfigSettings(configFromFile: Jest.Configuration, config: Jest.Configuration) { - const stringify = (obj: object) => JSON.stringify(obj, null, 2); - this.log.trace( + private mergeConfigSettings(configFromFile: jest.Config.InitialOptions, config: jest.Config.InitialOptions): jest.Config.InitialOptions { + const stringify = (obj: jest.Config.InitialOptions) => JSON.stringify(obj, null, 2); + this.log.debug( `Merging file-based config ${stringify(configFromFile)} with custom config ${stringify(config)} and default (internal) stryker config ${JEST_OVERRIDE_OPTIONS}` ); - return Object.assign(configFromFile, config, JEST_OVERRIDE_OPTIONS); + return { + ...configFromFile, + ...config, + ...JEST_OVERRIDE_OPTIONS, + }; } } diff --git a/packages/jest-runner/src/configLoaders/CustomJestConfigLoader.ts b/packages/jest-runner/src/configLoaders/CustomJestConfigLoader.ts index 889110c368..68be9fa8a0 100644 --- a/packages/jest-runner/src/configLoaders/CustomJestConfigLoader.ts +++ b/packages/jest-runner/src/configLoaders/CustomJestConfigLoader.ts @@ -4,6 +4,7 @@ import path from 'path'; import { Logger } from '@stryker-mutator/api/logging'; import { tokens, commonTokens } from '@stryker-mutator/api/plugin'; import { StrykerOptions } from '@stryker-mutator/api/core'; +import { Config } from '@jest/types'; import { loaderToken, projectRootToken } from '../pluginTokens'; import { JestRunnerOptionsWithStrykerOptions } from '../JestRunnerOptionsWithStrykerOptions'; @@ -24,7 +25,7 @@ export default class CustomJestConfigLoader implements JestConfigLoader { private readonly projectRoot: string ) {} - public loadConfig(): Jest.Configuration { + public loadConfig(): Config.InitialOptions { const jestConfig = this.readConfigFromJestConfigFile() || this.readConfigFromPackageJson() || {}; return jestConfig; } diff --git a/packages/jest-runner/src/configLoaders/JestConfigLoader.ts b/packages/jest-runner/src/configLoaders/JestConfigLoader.ts index 1e80a99f38..ecd2e5246d 100644 --- a/packages/jest-runner/src/configLoaders/JestConfigLoader.ts +++ b/packages/jest-runner/src/configLoaders/JestConfigLoader.ts @@ -6,11 +6,13 @@ * The loaderConfig method will return a usable config for Jest to use. */ +import { Config } from '@jest/types'; + export default interface JestConfigLoader { /* * Load the JSON representation of a Jest Configuration. * * @return {JestConfiguration} an object containing the Jest configuration. */ - loadConfig(): Jest.Configuration; + loadConfig(): Config.InitialOptions; } diff --git a/packages/jest-runner/src/configLoaders/ReactScriptsJestConfigLoader.ts b/packages/jest-runner/src/configLoaders/ReactScriptsJestConfigLoader.ts index 6c65db7c46..ab52c5cba1 100644 --- a/packages/jest-runner/src/configLoaders/ReactScriptsJestConfigLoader.ts +++ b/packages/jest-runner/src/configLoaders/ReactScriptsJestConfigLoader.ts @@ -1,6 +1,7 @@ import path from 'path'; import { tokens } from '@stryker-mutator/api/plugin'; +import { Config } from '@jest/types'; import { createReactJestConfig } from '../utils/createReactJestConfig'; import { projectRootToken, resolveToken } from '../pluginTokens'; @@ -12,7 +13,7 @@ export default class ReactScriptsJestConfigLoader implements JestConfigLoader { constructor(private readonly resolve: RequireResolve, private readonly projectRoot: string) {} - public loadConfig(): Jest.Configuration { + public loadConfig(): Config.InitialOptions { try { // Get the location of react script, this is later used to generate the Jest configuration used for React projects. const reactScriptsLocation = path.join(this.resolve('react-scripts/package.json'), '..'); @@ -33,7 +34,7 @@ export default class ReactScriptsJestConfigLoader implements JestConfigLoader { return arg.code !== undefined; } - private createJestConfig(reactScriptsLocation: string): Jest.Configuration { + private createJestConfig(reactScriptsLocation: string): Config.InitialOptions { return createReactJestConfig((relativePath: string): string => path.join(reactScriptsLocation, relativePath), this.projectRoot, false); } } diff --git a/packages/jest-runner/src/configLoaders/ReactScriptsTSJestConfigLoader.ts b/packages/jest-runner/src/configLoaders/ReactScriptsTSJestConfigLoader.ts index 512d4e99ba..ca78bdc9f7 100644 --- a/packages/jest-runner/src/configLoaders/ReactScriptsTSJestConfigLoader.ts +++ b/packages/jest-runner/src/configLoaders/ReactScriptsTSJestConfigLoader.ts @@ -1,6 +1,9 @@ import * as path from 'path'; -import { tokens } from '@stryker-mutator/api/plugin'; +import { Logger } from '@stryker-mutator/api/logging'; +import { tokens, commonTokens } from '@stryker-mutator/api/plugin'; + +import { Config } from '@jest/types'; import { createReactTsJestConfig } from '../utils/createReactJestConfig'; import { projectRootToken, resolveToken } from '../pluginTokens'; @@ -8,11 +11,11 @@ import { projectRootToken, resolveToken } from '../pluginTokens'; import JestConfigLoader from './JestConfigLoader'; export default class ReactScriptsTSJestConfigLoader implements JestConfigLoader { - public static inject = tokens(resolveToken, projectRootToken); + public static inject = tokens(commonTokens.logger, resolveToken, projectRootToken); - constructor(private readonly resolve: RequireResolve, private readonly projectRoot: string) {} + constructor(private readonly log: Logger, private readonly resolve: RequireResolve, private readonly projectRoot: string) {} - public loadConfig(): Jest.Configuration { + public loadConfig(): Config.InitialOptions { try { // Get the location of react-ts script, this is later used to generate the Jest configuration used for React projects. const reactScriptsTsLocation = path.join(this.resolve('react-scripts-ts/package.json'), '..'); @@ -20,6 +23,9 @@ export default class ReactScriptsTSJestConfigLoader implements JestConfigLoader // Create the React configuration for Jest const jestConfiguration = this.createJestConfig(reactScriptsTsLocation); jestConfiguration.testEnvironment = 'jsdom'; + this.log.warn( + 'DEPRECATED: The support for create-react-app-ts projects is deprecated and will be removed in the future. Please migrate your project to create-react-app and update your Stryker config setting to "create-react-app" (see https://create-react-app.dev/docs/adding-typescript/)' + ); return jestConfiguration; } catch (e) { if (this.isNodeErrnoException(e) && e.code === 'MODULE_NOT_FOUND') { @@ -33,7 +39,7 @@ export default class ReactScriptsTSJestConfigLoader implements JestConfigLoader return arg.code !== undefined; } - private createJestConfig(reactScriptsTsLocation: string): Jest.Configuration { + private createJestConfig(reactScriptsTsLocation: string): Config.InitialOptions { return createReactTsJestConfig((relativePath: string): string => path.join(reactScriptsTsLocation, relativePath), this.projectRoot, false); } } diff --git a/packages/jest-runner/src/configLoaders/index.ts b/packages/jest-runner/src/configLoaders/index.ts index 90c28deb5e..ac90052828 100644 --- a/packages/jest-runner/src/configLoaders/index.ts +++ b/packages/jest-runner/src/configLoaders/index.ts @@ -1,4 +1,4 @@ -import { tokens, commonTokens, Injector, OptionsContext } from '@stryker-mutator/api/plugin'; +import { tokens, commonTokens, Injector, PluginContext } from '@stryker-mutator/api/plugin'; import { StrykerOptions } from '@stryker-mutator/api/core'; import { Logger } from '@stryker-mutator/api/logging'; @@ -10,7 +10,7 @@ import ReactScriptsJestConfigLoader from './ReactScriptsJestConfigLoader'; import ReactScriptsTSJestConfigLoader from './ReactScriptsTSJestConfigLoader'; configLoaderFactory.inject = tokens(commonTokens.options, commonTokens.injector, commonTokens.logger); -export function configLoaderFactory(options: StrykerOptions, injector: Injector, log: Logger) { +export function configLoaderFactory(options: StrykerOptions, injector: Injector, log: Logger) { const warnAboutConfigFile = (projectType: string, configFile: string | undefined) => { if (configFile) { log.warn(`Config setting "configFile" is not supported for projectType "${projectType}"`); @@ -32,18 +32,6 @@ export function configLoaderFactory(options: StrykerOptions, injector: Injector< case 'create-react-app-ts': warnAboutConfigFile(optionsWithJest.jest.projectType, optionsWithJest.jest.configFile); return configLoaderInjector.injectClass(ReactScriptsTSJestConfigLoader); - case 'react': - log.warn( - 'DEPRECATED: The projectType "react" is deprecated. Use projectType "create-react-app" for react projects created by "create-react-app" or use "custom" for other react projects.' - ); - warnAboutConfigFile(optionsWithJest.jest.projectType, optionsWithJest.jest.configFile); - return configLoaderInjector.injectClass(ReactScriptsJestConfigLoader); - case 'react-ts': - log.warn( - 'DEPRECATED: The projectType "react-ts" is deprecated. Use projectType "create-react-app-ts" for react projects created by "create-react-app" or use "custom" for other react projects.' - ); - warnAboutConfigFile(optionsWithJest.jest.projectType, optionsWithJest.jest.configFile); - return configLoaderInjector.injectClass(ReactScriptsTSJestConfigLoader); default: throw new Error(`No configLoader available for ${optionsWithJest.jest.projectType}`); } diff --git a/packages/jest-runner/src/jestOverrideOptions.ts b/packages/jest-runner/src/jestOverrideOptions.ts index 3df4896646..159d60ecb2 100644 --- a/packages/jest-runner/src/jestOverrideOptions.ts +++ b/packages/jest-runner/src/jestOverrideOptions.ts @@ -15,6 +15,6 @@ const JEST_OVERRIDE_OPTIONS = Object.freeze({ // Disable notifications for test results, this will otherwise show a notification about // the results each time Stryker runs the tests notify: false, -}); +} as const); export default JEST_OVERRIDE_OPTIONS; diff --git a/packages/jest-runner/src/jestTestAdapters/JestGreaterThan25Adapter.ts b/packages/jest-runner/src/jestTestAdapters/JestGreaterThan25Adapter.ts index 2eca1cad88..f486fda35c 100644 --- a/packages/jest-runner/src/jestTestAdapters/JestGreaterThan25Adapter.ts +++ b/packages/jest-runner/src/jestTestAdapters/JestGreaterThan25Adapter.ts @@ -1,7 +1,10 @@ import { Logger } from '@stryker-mutator/api/logging'; import { commonTokens, tokens } from '@stryker-mutator/api/plugin'; +import { Config } from '@jest/types'; + import { jestWrapper } from '../utils/jestWrapper'; +import { JestRunResult } from '../JestRunResult'; import JestTestAdapter from './JestTestAdapter'; @@ -9,14 +12,13 @@ export default class JestGreaterThan25Adapter implements JestTestAdapter { public static inject = tokens(commonTokens.logger); constructor(private readonly log: Logger) {} - public async run(jestConfig: Jest.Configuration, projectRoot: string, fileNameUnderTest?: string): Promise { + public async run(jestConfig: Config.InitialOptions, projectRoot: string, fileNameUnderTest?: string): Promise { jestConfig.reporters = []; const config = JSON.stringify(jestConfig); this.log.trace(`Invoking Jest with config ${config}`); if (fileNameUnderTest) { this.log.trace(`Only running tests related to ${fileNameUnderTest}`); } - const result = await jestWrapper.runCLI( { $0: 'stryker', diff --git a/packages/jest-runner/src/jestTestAdapters/JestLessThan25Adapter.ts b/packages/jest-runner/src/jestTestAdapters/JestLessThan25Adapter.ts index 2925a252e2..aaab9d11ff 100644 --- a/packages/jest-runner/src/jestTestAdapters/JestLessThan25Adapter.ts +++ b/packages/jest-runner/src/jestTestAdapters/JestLessThan25Adapter.ts @@ -2,6 +2,8 @@ import { Logger } from '@stryker-mutator/api/logging'; import { commonTokens, tokens } from '@stryker-mutator/api/plugin'; import jest from 'jest'; +import { JestRunResult } from '../JestRunResult'; + import JestTestAdapter from './JestTestAdapter'; /** @@ -12,7 +14,7 @@ export default class JestLessThan25TestAdapter implements JestTestAdapter { public static inject = tokens(commonTokens.logger); constructor(private readonly log: Logger) {} - public run(jestConfig: any, projectRoot: string, fileNameUnderTest?: string): Promise { + public run(jestConfig: Record, projectRoot: string, fileNameUnderTest?: string): Promise { jestConfig.reporters = []; const config = JSON.stringify(jestConfig); this.log.trace(`Invoking Jest with config ${config}`); diff --git a/packages/jest-runner/src/jestTestAdapters/JestTestAdapter.ts b/packages/jest-runner/src/jestTestAdapters/JestTestAdapter.ts index 6f4e1657d9..7ba0ef3a6e 100644 --- a/packages/jest-runner/src/jestTestAdapters/JestTestAdapter.ts +++ b/packages/jest-runner/src/jestTestAdapters/JestTestAdapter.ts @@ -1,3 +1,7 @@ +import { Config } from '@jest/types'; + +import { JestRunResult } from '../JestRunResult'; + export default interface JestTestAdapter { - run(config: object, projectRoot: string, fileNameUnderTest?: string): Promise; + run(config: Config.InitialOptions, projectRoot: string, fileNameUnderTest?: string): Promise; } diff --git a/packages/jest-runner/src/utils/createReactJestConfig.ts b/packages/jest-runner/src/utils/createReactJestConfig.ts index 1ef25041c4..eb58395ef3 100644 --- a/packages/jest-runner/src/utils/createReactJestConfig.ts +++ b/packages/jest-runner/src/utils/createReactJestConfig.ts @@ -1,13 +1,25 @@ -const resolveCreateJestConfig = (path: string, loader?: NodeRequire): Function => { +import { Config } from '@jest/types'; + +const resolveCreateJestConfig = (path: string, loader?: NodeRequire): ((...args: any[]) => any) => { loader = loader || /* istanbul ignore next */ require; return loader(path); }; -export function createReactJestConfig(resolve: Function, projectRoot: string, ejected: boolean, loader?: NodeRequire): Jest.Configuration { +export function createReactJestConfig( + resolve: (...args: any[]) => any, + projectRoot: string, + ejected: boolean, + loader?: NodeRequire +): Config.InitialOptions { return resolveCreateJestConfig('react-scripts/scripts/utils/createJestConfig', loader)(resolve, projectRoot, ejected); } -export function createReactTsJestConfig(resolve: Function, projectRoot: string, ejected: boolean, loader?: NodeRequire): Jest.Configuration { +export function createReactTsJestConfig( + resolve: (...args: any[]) => any, + projectRoot: string, + ejected: boolean, + loader?: NodeRequire +): Config.InitialOptions { return resolveCreateJestConfig('react-scripts-ts/scripts/utils/createJestConfig', loader)(resolve, projectRoot, ejected); } diff --git a/packages/jest-runner/stryker.conf.js b/packages/jest-runner/stryker.conf.js index 5f801069f7..ad5af4549f 100644 --- a/packages/jest-runner/stryker.conf.js +++ b/packages/jest-runner/stryker.conf.js @@ -1,6 +1,7 @@ const path = require('path'); const settings = require('../../stryker.parent.conf'); const moduleName = __dirname.split(path.sep).pop(); +settings.plugins = settings.plugins.map(p => path.resolve(p)); settings.dashboard.module = moduleName; -settings.coverageAnalysis = 'off'; +settings.files = ['{src-generated,src,test,schema}/**/*.{ts,json}', '*.{ts,json}', '!**/*.d.ts'] module.exports = settings; diff --git a/packages/jest-runner/test/helpers/initChai.ts b/packages/jest-runner/test/helpers/initChai.ts deleted file mode 100644 index 3707545700..0000000000 --- a/packages/jest-runner/test/helpers/initChai.ts +++ /dev/null @@ -1,6 +0,0 @@ -import chai from 'chai'; -import chaiAsPromised from 'chai-as-promised'; -import sinonChai from 'sinon-chai'; - -chai.use(sinonChai); -chai.use(chaiAsPromised); diff --git a/packages/jest-runner/test/helpers/initSinon.ts b/packages/jest-runner/test/helpers/initSinon.ts deleted file mode 100644 index 96cb3f7e59..0000000000 --- a/packages/jest-runner/test/helpers/initSinon.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { testInjector } from '@stryker-mutator/test-helpers'; -import * as sinon from 'sinon'; - -afterEach(() => { - sinon.restore(); - testInjector.reset(); -}); diff --git a/packages/jest-runner/test/helpers/initSourceMaps.ts b/packages/jest-runner/test/helpers/initSourceMaps.ts deleted file mode 100644 index fcfbfda16c..0000000000 --- a/packages/jest-runner/test/helpers/initSourceMaps.ts +++ /dev/null @@ -1 +0,0 @@ -import 'source-map-support/register'; diff --git a/packages/jest-runner/test/helpers/producers.ts b/packages/jest-runner/test/helpers/producers.ts index 826cf3512d..bedb8a8aee 100644 --- a/packages/jest-runner/test/helpers/producers.ts +++ b/packages/jest-runner/test/helpers/producers.ts @@ -1,3 +1,5 @@ +import { TestResult, AggregatedResult, AssertionResult, SerializableError } from '@jest/test-result'; + import { JestOptions } from '../../src-generated/jest-runner-options'; export const createJestOptions = (overrides?: Partial): JestOptions => { @@ -8,210 +10,184 @@ export const createJestOptions = (overrides?: Partial): JestOptions }; }; -export const createFailResult = () => ({ - numFailedTests: 2, - numFailedTestSuites: 1, - numPassedTests: 0, - numPassedTestSuites: 0, - numPendingTests: 0, - numPendingTestSuites: 0, - numRuntimeErrorTestSuites: 0, - numTotalTests: 2, - numTotalTestSuites: 1, - startTime: 1513852010583, - success: false, - testResults: [ - { - console: null, - coverage: undefined, - failureMessage: 'test failed - App.test.js', - numFailingTests: 2, - numPassingTests: 0, - numPendingTests: 0, - skipped: false, - sourceMaps: {}, - testFilePath: 'App.test.js', - testResults: [ - { - ancestorTitles: ['App'], - duration: 2, - failureMessages: ['Fail message 1', 'Fail message 2'], - fullName: 'App render renders without crashing', - numPassingAsserts: 0, - status: 'failed', - title: 'renders without crashing', - }, - { - ancestorTitles: ['App'], - duration: 0, - failureMessages: ['Fail message 3', 'Fail message 4'], - fullName: 'App render renders without crashing', - numPassingAsserts: 0, - status: 'failed', - title: 'renders without crashing', - }, - ], - }, - { - console: null, - coverage: undefined, - failureMessage: null, - numFailingTests: 0, - numPassingTests: 1, - numPendingTests: 0, - perfStats: [Object], - skipped: false, - snapshot: [Object], - sourceMaps: {}, - testFilePath: 'App.test.js', - testResults: [ - { - ancestorTitles: ['App'], - duration: 23, - failureMessages: [], - fullName: 'App renders without crashing', - numPassingAsserts: 0, - status: 'passed', - title: 'renders without crashing', - }, - ], - }, - ], - wasInterrupted: false, -}); +export function createAssertionResult(overrides?: Partial): AssertionResult { + return { + ancestorTitles: [], + failureMessages: [], + fullName: 'foo should be bar', + numPassingAsserts: 1, + status: 'passed', + title: 'should be bar', + duration: 25, + failureDetails: [], + ...overrides, + }; +} -export const createSuccessResult = () => ({ - numFailedTests: 0, - numFailedTestSuites: 0, - numPassedTests: 1, - numPassedTestSuites: 1, - numPendingTests: 0, - numPendingTestSuites: 0, - numRuntimeErrorTestSuites: 0, - numTotalTests: 1, - numTotalTestSuites: 1, - startTime: 1513857548132, - success: true, - testResults: [ - { - console: null, - coverage: undefined, - failureMessage: null, - numFailingTests: 0, - numPassingTests: 1, - numPendingTests: 0, - perfStats: [Object], - skipped: false, - snapshot: [Object], - sourceMaps: {}, - testFilePath: 'App.test.js', - testResults: [ - { - ancestorTitles: ['App'], - duration: 23, - failureMessages: [], - fullName: 'App renders without crashing', - numPassingAsserts: 0, - status: 'passed', - title: 'renders without crashing', - }, - ], +export function createJestAggregatedResult(overrides?: Partial): AggregatedResult { + return { + numFailedTestSuites: 0, + numFailedTests: 0, + numPassedTestSuites: 0, + numPassedTests: 0, + numPendingTestSuites: 0, + numPendingTests: 0, + numRuntimeErrorTestSuites: 0, + numTodoTests: 0, + numTotalTestSuites: 0, + numTotalTests: 0, + openHandles: [], + snapshot: { + added: 0, + didUpdate: false, + failure: false, + filesAdded: 0, + filesRemoved: 0, + filesRemovedList: [], + filesUnmatched: 0, + filesUpdated: 0, + matched: 0, + total: 0, + unchecked: 0, + uncheckedKeysByFile: [], + unmatched: 0, + updated: 0, }, - ], - wasInterrupted: false, -}); + startTime: 0, + success: true, + testResults: [], + wasInterrupted: false, + ...overrides, + }; +} -export const createPendingResult = () => ({ - numFailedTests: 0, - numFailedTestSuites: 0, - numPassedTests: 1, - numPassedTestSuites: 1, - numPendingTests: 0, - numPendingTestSuites: 0, - numRuntimeErrorTestSuites: 0, - numTotalTests: 1, - numTotalTestSuites: 1, - startTime: 1513857548132, - success: true, - testResults: [ - { - console: null, - coverage: undefined, - failureMessage: null, - numFailingTests: 0, - numPassingTests: 1, - numPendingTests: 0, - perfStats: [Object], - skipped: false, - snapshot: [Object], - sourceMaps: {}, - testResults: [ - { - ancestorTitles: ['App'], - duration: 0, - failureMessages: [], - fullName: 'App renders without crashing', - numPassingAsserts: 0, - status: 'pending', - title: 'renders without crashing', - }, - ], +export function createJestTestResult(overrides?: Partial): TestResult { + return { + leaks: false, + numFailingTests: 0, + numPassingTests: 0, + numPendingTests: 0, + numTodoTests: 0, + openHandles: [], + perfStats: { + runtime: 0, + slow: false, + end: 0, + start: 0, }, - ], - wasInterrupted: false, -}); - -export const createTodoResult = () => ({ - numFailedTests: 0, - numFailedTestSuites: 0, - numPassedTests: 1, - numPassedTestSuites: 1, - numPendingTests: 0, - numPendingTestSuites: 0, - numRuntimeErrorTestSuites: 0, - numTodoTests: 1, - numTotalTests: 2, - numTotalTestSuites: 1, - startTime: 1551045971122, - success: true, - testResults: [ - { - console: null, - coverage: undefined, - displayName: undefined, - failureMessage: null, - leaks: false, - numFailingTests: 0, - numPassingTests: 1, - numPendingTests: 0, - numTodoTests: 1, - perfStats: [Object], - skipped: false, - snapshot: [Object], - sourceMaps: {}, - testResults: [ - { - ancestorTitles: ['App'], - duration: 4, - failureMessages: [], - fullName: 'App renders without crashing', - location: null, - numPassingAsserts: 0, - status: 'passed', - title: 'renders without crashing', - }, - { - ancestorTitles: ['App'], - duration: 0, - failureMessages: [], - fullName: 'App renders without crashing with children', - location: null, - numPassingAsserts: 0, - status: 'todo', - title: 'renders without crashing with children', - }, - ], + skipped: false, + snapshot: { + added: 0, + fileDeleted: false, + matched: 0, + unchecked: 0, + uncheckedKeys: [], + unmatched: 0, + updated: 0, }, - ], - wasInterrupted: false, -}); + testFilePath: '', + testResults: [], + ...overrides, + }; +} + +export function createSerializableError(overrides?: Partial): SerializableError { + return { + message: 'message', + stack: 'stack', + code: 'TEST', + type: 'FooError', + ...overrides, + }; +} + +export const createFailResult = (): AggregatedResult => + createJestAggregatedResult({ + success: false, + testResults: [ + createJestTestResult({ + testResults: [ + createAssertionResult({ + failureMessages: ['Fail message 1', 'Fail message 2'], + fullName: 'App render renders without crashing', + duration: 2, + status: 'failed', + }), + createAssertionResult({ + duration: 0, + failureMessages: ['Fail message 3', 'Fail message 4'], + fullName: 'App render renders without crashing', + status: 'failed', + }), + ], + }), + createJestTestResult({ + testResults: [ + createAssertionResult({ + ancestorTitles: ['App'], + duration: 23, + failureMessages: [], + fullName: 'App renders without crashing', + numPassingAsserts: 0, + status: 'passed', + title: 'renders without crashing', + }), + ], + }), + ], + }); + +export const createSuccessResult = (): AggregatedResult => + createJestAggregatedResult({ + success: true, + testResults: [ + createJestTestResult({ + testResults: [ + createAssertionResult({ + fullName: 'App renders without crashing', + status: 'passed', + duration: 23, + }), + ], + }), + ], + wasInterrupted: false, + }); + +export const createPendingResult = (): AggregatedResult => + createJestAggregatedResult({ + success: true, + testResults: [ + createJestTestResult({ + testResults: [ + createAssertionResult({ + duration: 0, + fullName: 'App renders without crashing', + status: 'pending', + }), + ], + }), + ], + }); + +export const createTodoResult = (): AggregatedResult => + createJestAggregatedResult({ + success: true, + testResults: [ + createJestTestResult({ + skipped: false, + testResults: [ + createAssertionResult({ + duration: 4, + fullName: 'App renders without crashing', + status: 'passed', + }), + createAssertionResult({ + duration: 0, + fullName: 'App renders without crashing with children', + status: 'todo', + }), + ], + }), + ], + }); diff --git a/packages/jest-runner/test/integration/JestTestRunner.it.spec.ts b/packages/jest-runner/test/integration/JestTestRunner.it.spec.ts index 48c75655cd..452b8a4327 100644 --- a/packages/jest-runner/test/integration/JestTestRunner.it.spec.ts +++ b/packages/jest-runner/test/integration/JestTestRunner.it.spec.ts @@ -1,10 +1,9 @@ import * as path from 'path'; import { expect } from 'chai'; -import { RunOptions, RunStatus, TestStatus } from '@stryker-mutator/api/test_runner'; -import * as sinon from 'sinon'; import { commonTokens } from '@stryker-mutator/api/plugin'; -import { factory, testInjector } from '@stryker-mutator/test-helpers'; +import { factory, testInjector, assertions } from '@stryker-mutator/test-helpers'; +import { CompleteDryRunResult, TestStatus } from '@stryker-mutator/api/test_runner'; import JestTestRunner, { jestTestRunnerFactory } from '../../src/JestTestRunner'; import { JestRunnerOptionsWithStrykerOptions } from '../../src/JestRunnerOptionsWithStrykerOptions'; @@ -22,10 +21,7 @@ const jestProjectRoot = process.cwd(); process.env.BABEL_ENV = 'test'; describe(`${JestTestRunner.name} integration test`, () => { - // Set timeout for integration tests to 10 seconds for travis - let processCwdStub: sinon.SinonStub; - - const runOptions: RunOptions = { timeout: 0 }; + const initialCwd = process.cwd(); // Names of the tests in the example projects const testNames = [ @@ -33,12 +29,11 @@ describe(`${JestTestRunner.name} integration test`, () => { 'Add should be able to add one to a number', 'Add should be able negate a number', 'Add should be able to recognize a negative number', - 'Add should be able to recognize that 0 is not a negative number', 'Circle should have a circumference of 2PI when the radius is 1', ]; - beforeEach(() => { - processCwdStub = sinon.stub(process, 'cwd'); + afterEach(() => { + process.chdir(initialCwd); }); function createSut(overrides?: Partial) { @@ -48,61 +43,108 @@ describe(`${JestTestRunner.name} integration test`, () => { return testInjector.injector.provideValue(commonTokens.options, options).injectFunction(jestTestRunnerFactory); } - it('should run tests on the example React + TypeScript project', async () => { - processCwdStub.returns(getProjectRoot('reactTsProject')); - const jestTestRunner = createSut({ projectType: 'react-ts' }); + const expectToHaveSuccessfulTests = (result: CompleteDryRunResult, n: number) => { + expect(result.tests.filter((t) => t.status === TestStatus.Success)).to.have.length(n); + }; - const result = await jestTestRunner.run(runOptions); + describe('dryRun', () => { + it('should run tests on the example React + TypeScript project', async () => { + // TODO: Get a proper React TS project that works on Windows + process.chdir(getProjectRoot('reactTsProject')); + const jestTestRunner = createSut({ projectType: 'create-react-app-ts' }); - expect(result.status).to.equal(RunStatus.Complete); - expect(result).to.have.property('tests'); - expect(result.tests).to.be.an('array').that.is.not.empty; - expect(result.tests[0].name).to.equal('renders without crashing'); - expect(result.tests[0].status).to.equal(TestStatus.Success); - expect(result.tests[0].timeSpentMs).to.be.above(-1); - expect(result.tests[0].failureMessages).to.be.an('array').that.is.empty; - expect(result.status).to.equal(RunStatus.Complete); - }); + const runResult = await jestTestRunner.dryRun(); + + assertions.expectCompleted(runResult); + expectToHaveSuccessfulTests(runResult, 1); + }); - it('should run tests on the example custom project using package.json', async () => { - processCwdStub.returns(getProjectRoot('exampleProject')); - const jestTestRunner = createSut(); + it('should set the test name and timeSpentMs', async () => { + process.chdir(getProjectRoot('reactTsProject')); + const jestTestRunner = createSut({ projectType: 'create-react-app-ts' }); - const result = await jestTestRunner.run(runOptions); + const runResult = await jestTestRunner.dryRun(); - expect(result.errorMessages, `Errors were: ${result.errorMessages}`).lengthOf(0); - expect(result).to.have.property('tests'); - expect(result.tests).to.be.an('array').with.length(testNames.length); + assertions.expectCompleted(runResult); + expect(runResult.tests[0].name).to.equal('renders without crashing'); + expect(runResult.tests[0].timeSpentMs).to.be.above(-1); + }); - for (const test of result.tests) { - expect(testNames).to.include(test.name); - expect(test.status).to.equal(TestStatus.Success); - expect(test.timeSpentMs).to.be.above(-1); - expect(test.failureMessages).to.be.an('array').that.is.empty; - } + it('should run tests on the example custom project using package.json', async () => { + process.chdir(getProjectRoot('exampleProject')); + const jestTestRunner = createSut(); - expect(result.status).to.equal(RunStatus.Complete); - }); + const runResult = await jestTestRunner.dryRun(); + + assertions.expectCompleted(runResult); + expectToHaveSuccessfulTests(runResult, testNames.length); + }); - it('should run tests on the example custom project using jest.config.js', async () => { - processCwdStub.returns(getProjectRoot('exampleProjectWithExplicitJestConfig')); + it('should run tests on the example custom project using jest.config.js', async () => { + process.chdir(getProjectRoot('exampleProjectWithExplicitJestConfig')); - const jestTestRunner = createSut(); + const jestTestRunner = createSut(); - const result = await jestTestRunner.run(runOptions); + const runResult = await jestTestRunner.dryRun(); - expect(result.errorMessages, `Errors were: ${result.errorMessages}`).lengthOf(0); - expect(result).to.have.property('tests'); - expect(result.tests).to.be.an('array').with.length(testNames.length); + assertions.expectCompleted(runResult); + expectToHaveSuccessfulTests(runResult, testNames.length); + }); + }); + + describe('mutantRun', () => { + it('should kill mutant 1', async () => { + const exampleProjectRoot = getProjectRoot('exampleProject'); + process.chdir(exampleProjectRoot); + const jestTestRunner = createSut(); + const mutantRunOptions = factory.mutantRunOptions({ + activeMutant: factory.mutant({ + id: 1, + }), + sandboxFileName: require.resolve(path.resolve(exampleProjectRoot, 'src', 'Add.js')), + }); + mutantRunOptions.activeMutant.id = 1; + + const runResult = await jestTestRunner.mutantRun(mutantRunOptions); + + assertions.expectKilled(runResult); + expect(runResult.killedBy).eq('Add should be able to add two numbers'); + expect(runResult.failureMessage).contains('Expected: 7').contains('Received: -3'); + }); - for (const test of result.tests) { - expect(testNames).to.include(test.name); - expect(test.status).to.equal(TestStatus.Success); - expect(test.timeSpentMs).to.be.above(-1); - expect(test.failureMessages).to.be.an('array').that.is.empty; - } + it('should let mutant 11 survive', async () => { + const exampleProjectRoot = getProjectRoot('exampleProject'); + process.chdir(getProjectRoot('exampleProject')); + const jestTestRunner = createSut(); + const mutantRunOptions = factory.mutantRunOptions({ + sandboxFileName: require.resolve(path.resolve(exampleProjectRoot, 'src', 'Circle.js')), + }); + mutantRunOptions.activeMutant.id = 11; - expect(result.status).to.equal(RunStatus.Complete); + const runResult = await jestTestRunner.mutantRun(mutantRunOptions); + + assertions.expectSurvived(runResult); + }); + + it('should be able to let a mutant survive after killing mutant 1', async () => { + // Arrange + const exampleProjectRoot = getProjectRoot('exampleProject'); + process.chdir(getProjectRoot('exampleProject')); + const jestTestRunner = createSut(); + const mutantRunOptions = factory.mutantRunOptions({ + sandboxFileName: require.resolve(path.resolve(exampleProjectRoot, 'src', 'Add.js')), + }); + mutantRunOptions.activeMutant.id = 1; + + // Act + const firstResult = await jestTestRunner.mutantRun(mutantRunOptions); + mutantRunOptions.activeMutant.id = 5; + const secondResult = await jestTestRunner.mutantRun(mutantRunOptions); + + // Assert + assertions.expectKilled(firstResult); + assertions.expectSurvived(secondResult); + }); }); }); diff --git a/packages/jest-runner/test/setup.ts b/packages/jest-runner/test/setup.ts new file mode 100644 index 0000000000..be7fbec401 --- /dev/null +++ b/packages/jest-runner/test/setup.ts @@ -0,0 +1,16 @@ +import 'source-map-support/register'; +import chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import sinonChai from 'sinon-chai'; +import * as sinon from 'sinon'; +import { testInjector } from '@stryker-mutator/test-helpers'; + +chai.use(sinonChai); +chai.use(chaiAsPromised); + +export const mochaHooks = { + afterEach() { + sinon.restore(); + testInjector.reset(); + }, +}; diff --git a/packages/jest-runner/test/unit/JestTestRunner.spec.ts b/packages/jest-runner/test/unit/JestTestRunner.spec.ts index 9fde80ad24..502515fe33 100644 --- a/packages/jest-runner/test/unit/JestTestRunner.spec.ts +++ b/packages/jest-runner/test/unit/JestTestRunner.spec.ts @@ -1,184 +1,257 @@ -import { RunOptions, RunStatus, TestStatus } from '@stryker-mutator/api/test_runner'; -import { testInjector } from '@stryker-mutator/test-helpers'; +import { testInjector, factory } from '@stryker-mutator/test-helpers'; import { expect } from 'chai'; import sinon from 'sinon'; +import { DryRunStatus, TestStatus, CompleteDryRunResult, ErrorDryRunResult } from '@stryker-mutator/api/test_runner'; +import { INSTRUMENTER_CONSTANTS } from '@stryker-mutator/api/core'; +import { Config } from '@jest/types'; import { JestTestAdapter } from '../../src/jestTestAdapters'; import JestTestRunner from '../../src/JestTestRunner'; import * as producers from '../helpers/producers'; import { processEnvToken, jestTestAdapterToken, configLoaderToken } from '../../src/pluginTokens'; import JestConfigLoader from '../../src/configLoaders/JestConfigLoader'; +import { JestRunnerOptionsWithStrykerOptions } from '../../src/JestRunnerOptionsWithStrykerOptions'; -describe('JestTestRunner', () => { +describe(JestTestRunner.name, () => { const basePath = '/path/to/project/root'; - const runOptions: RunOptions = { timeout: 0 }; let jestTestAdapterMock: sinon.SinonStubbedInstance; let jestConfigLoaderMock: sinon.SinonStubbedInstance; - let jestTestRunner: JestTestRunner; let processEnvMock: NodeJS.ProcessEnv; + let options: JestRunnerOptionsWithStrykerOptions; beforeEach(() => { + options = testInjector.options as JestRunnerOptionsWithStrykerOptions; jestTestAdapterMock = { run: sinon.stub() }; jestTestAdapterMock.run.resolves({ results: { testResults: [] } }); jestConfigLoaderMock = { loadConfig: sinon.stub() }; jestConfigLoaderMock.loadConfig.resolves({}); - testInjector.options.jest = { config: { property: 'value' } }; - testInjector.options.basePath = basePath; + options.jest = { + enableFindRelatedTests: true, + projectType: 'custom', + }; + options.basePath = basePath; processEnvMock = { NODE_ENV: undefined, }; - - jestTestRunner = testInjector.injector - .provideValue(processEnvToken, processEnvMock) - .provideValue(jestTestAdapterToken, (jestTestAdapterMock as unknown) as JestTestAdapter) - .provideValue(configLoaderToken, jestConfigLoaderMock) - .injectClass(JestTestRunner); }); - it('should log the project root when constructing the JestTestRunner', () => { - expect(testInjector.logger.debug).calledWith(`Project root is ${basePath}`); - }); - - it('should call the run function with the provided config and the projectRoot', async () => { - await jestTestRunner.run(runOptions); + describe('dryRun', () => { + let sut: JestTestRunner; + beforeEach(() => { + sut = createSut(); + }); - expect(jestTestAdapterMock.run).called; - }); + it('should log the project root when constructing the JestTestRunner', () => { + expect(testInjector.logger.debug).calledWith(`Project root is ${basePath}`); + }); - it('should call the jestTestRunner run method and return a correct runResult', async () => { - jestTestAdapterMock.run.resolves({ results: producers.createSuccessResult() }); + it('should call the run function with the provided config and the projectRoot', async () => { + await sut.dryRun(); - const result = await jestTestRunner.run(runOptions); + expect(jestTestAdapterMock.run).called; + }); - expect(result).to.deep.equal({ - errorMessages: [], - status: RunStatus.Complete, - tests: [ - { - failureMessages: [], - name: 'App renders without crashing', - status: TestStatus.Success, - timeSpentMs: 23, - }, - ], + it('should call the jestTestRunner run method and return a correct runResult', async () => { + jestTestAdapterMock.run.resolves({ results: producers.createSuccessResult() }); + + const result = await sut.dryRun(); + + const expectedRunResult: CompleteDryRunResult = { + status: DryRunStatus.Complete, + tests: [ + { + id: 'App renders without crashing', + name: 'App renders without crashing', + status: TestStatus.Success, + timeSpentMs: 23, + }, + ], + }; + expect(result).to.deep.equal(expectedRunResult); }); - }); - it('should call the jestTestRunner run method and return a skipped runResult', async () => { - jestTestAdapterMock.run.resolves({ results: producers.createPendingResult() }); + it('should call the jestTestRunner run method and return a skipped runResult', async () => { + jestTestAdapterMock.run.resolves({ results: producers.createPendingResult() }); - const result = await jestTestRunner.run(runOptions); + const result = await sut.dryRun(); - expect(result).to.deep.equal({ - errorMessages: [], - status: RunStatus.Complete, - tests: [ - { - failureMessages: [], - name: 'App renders without crashing', - status: TestStatus.Skipped, - timeSpentMs: 0, - }, - ], - }); - }); + const expectedRunResult: CompleteDryRunResult = { + status: DryRunStatus.Complete, + tests: [ + { + id: 'App renders without crashing', + name: 'App renders without crashing', + status: TestStatus.Skipped, + timeSpentMs: 0, + }, + ], + }; - it('should call the jestTestRunner run method and return a todo runResult', async () => { - jestTestAdapterMock.run.resolves({ results: producers.createTodoResult() }); + expect(result).to.deep.equal(expectedRunResult); + }); - const result = await jestTestRunner.run(runOptions); + it('should call the jestTestRunner run method and return a todo runResult', async () => { + jestTestAdapterMock.run.resolves({ results: producers.createTodoResult() }); + + const result = await sut.dryRun(); + const expectedRunResult: CompleteDryRunResult = { + status: DryRunStatus.Complete, + tests: [ + { + id: 'App renders without crashing', + name: 'App renders without crashing', + status: TestStatus.Success, + timeSpentMs: 4, + }, + { + id: 'App renders without crashing with children', + name: 'App renders without crashing with children', + status: TestStatus.Skipped, + timeSpentMs: 0, + }, + ], + }; + expect(result).to.deep.equal(expectedRunResult); + }); - expect(result).to.deep.equal({ - errorMessages: [], - status: RunStatus.Complete, - tests: [ - { - failureMessages: [], - name: 'App renders without crashing', - status: TestStatus.Success, - timeSpentMs: 4, - }, - { - failureMessages: [], - name: 'App renders without crashing with children', - status: TestStatus.Skipped, - timeSpentMs: 0, - }, - ], + it('should call the jestTestRunner run method and return a negative runResult', async () => { + jestTestAdapterMock.run.resolves({ results: producers.createFailResult() }); + + const result = await sut.dryRun(); + + const expectedRunResult: CompleteDryRunResult = { + status: DryRunStatus.Complete, + tests: [ + { + id: 'App render renders without crashing', + name: 'App render renders without crashing', + failureMessage: 'Fail message 1, Fail message 2', + status: TestStatus.Failed, + timeSpentMs: 2, + }, + { + id: 'App render renders without crashing', + name: 'App render renders without crashing', + failureMessage: 'Fail message 3, Fail message 4', + status: TestStatus.Failed, + timeSpentMs: 0, + }, + { + id: 'App renders without crashing', + name: 'App renders without crashing', + status: TestStatus.Success, + timeSpentMs: 23, + }, + ], + }; + expect(result).to.deep.equal(expectedRunResult); }); - }); - it('should call the jestTestRunner run method and return a negative runResult', async () => { - jestTestAdapterMock.run.resolves({ results: producers.createFailResult() }); + it('should return an error result when a runtime error occurs', async () => { + const jestResult = producers.createJestAggregatedResult({ + numRuntimeErrorTestSuites: 2, + testResults: [ + producers.createJestTestResult({ + testExecError: producers.createSerializableError({ + code: 'ENOENT', + stack: + 'Error\n at [eval]:1:1\n at Script.runInThisContext (vm.js:120:20)\n at Object.runInThisContext (vm.js:311:38)\n at Object. ([eval]-wrapper:10:26)', + message: 'test message', + type: 'test', + }), + }), + ], + }); + jestTestAdapterMock.run.resolves({ results: jestResult }); + + const result = await sut.dryRun(); + + const expectedRunResult: ErrorDryRunResult = { + status: DryRunStatus.Error, + errorMessage: + 'ENOENT test message Error\n at [eval]:1:1\n at Script.runInThisContext (vm.js:120:20)\n at Object.runInThisContext (vm.js:311:38)\n at Object. ([eval]-wrapper:10:26)', + }; + expect(result).to.deep.equal(expectedRunResult); + }); - const result = await jestTestRunner.run(runOptions); + it("should set process.env.NODE_ENV to 'test' when process.env.NODE_ENV is null", async () => { + await sut.dryRun(); - expect(result).to.deep.equal({ - errorMessages: ['test failed - App.test.js'], - status: RunStatus.Complete, - tests: [ - { - failureMessages: ['Fail message 1', 'Fail message 2'], - name: 'App render renders without crashing', - status: TestStatus.Failed, - timeSpentMs: 2, - }, - { - failureMessages: ['Fail message 3', 'Fail message 4'], - name: 'App render renders without crashing', - status: TestStatus.Failed, - timeSpentMs: 0, - }, - { - failureMessages: [], - name: 'App renders without crashing', - status: TestStatus.Success, - timeSpentMs: 23, - }, - ], + expect(processEnvMock.NODE_ENV).to.equal('test'); }); - }); - it('should return an error result when a runtime error occurs', async () => { - jestTestAdapterMock.run.resolves({ results: { testResults: [], numRuntimeErrorTestSuites: 1 } }); + it('should keep the value set in process.env.NODE_ENV if not null', async () => { + processEnvMock.NODE_ENV = 'stryker'; - const result = await jestTestRunner.run(runOptions); + await sut.dryRun(); - expect(result).to.deep.equal({ - errorMessages: [], - status: RunStatus.Error, - tests: [], + expect(processEnvMock.NODE_ENV).to.equal('stryker'); }); - }); - - it("should set process.env.NODE_ENV to 'test' when process.env.NODE_ENV is null", async () => { - await jestTestRunner.run(runOptions); - expect(processEnvMock.NODE_ENV).to.equal('test'); + it('should override verbose, collectCoverage, testResultsProcessor, notify and bail on all loaded configs', async () => { + await sut.dryRun(); + + expect( + jestTestAdapterMock.run.calledWith({ + bail: false, + collectCoverage: false, + notify: false, + testResultsProcessor: undefined, + verbose: false, + }) + ); + }); }); - it('should keep the value set in process.env.NODE_ENV if not null', async () => { - processEnvMock.NODE_ENV = 'stryker'; + describe('mutantRun', () => { + it('should use correct fileUnderTest if findRelatedTests = true', async () => { + options.jest.enableFindRelatedTests = true; + const sut = createSut(); + await sut.mutantRun( + factory.mutantRunOptions({ activeMutant: factory.mutant({ fileName: 'foo.js' }), sandboxFileName: '.stryker-tmp/sandbox2/foo.js' }) + ); + expect(jestTestAdapterMock.run).calledWithExactly(sinon.match.object, sinon.match.string, '.stryker-tmp/sandbox2/foo.js'); + }); + + it('should not set fileUnderTest if findRelatedTests = false', async () => { + options.jest.enableFindRelatedTests = false; + const sut = createSut(); + await sut.mutantRun(factory.mutantRunOptions({ activeMutant: factory.mutant() })); + expect(jestTestAdapterMock.run).calledWithExactly(sinon.match.object, sinon.match.string, undefined); + }); - await jestTestRunner.run(runOptions); + it('should set the active mutant in environment variables', async () => { + const sut = createSut(); + await sut.mutantRun(factory.mutantRunOptions({ activeMutant: factory.mutant({ id: 25 }) })); + expect(process.env[INSTRUMENTER_CONSTANTS.ACTIVE_MUTANT_ENV_VARIABLE]).to.equal('25'); + }); - expect(processEnvMock.NODE_ENV).to.equal('stryker'); + it('should allow for other globals', async () => { + const customConfig: Config.InitialOptions = { + globals: { + foo: 'bar', + }, + }; + options.jest.config = customConfig; + const sut = createSut(); + await sut.mutantRun(factory.mutantRunOptions({ activeMutant: factory.mutant({ id: 25 }) })); + expect(jestTestAdapterMock.run).calledWithMatch( + sinon.match({ + globals: { foo: 'bar' }, + }), + sinon.match.string + ); + }); }); - it('should override verbose, collectCoverage, testResultsProcessor, notify and bail on all loaded configs', async () => { - await jestTestRunner.run(runOptions); - - expect( - jestTestAdapterMock.run.calledWith({ - bail: false, - collectCoverage: false, - notify: false, - testResultsProcessor: undefined, - verbose: false, - }) - ); - }); + function createSut() { + return testInjector.injector + .provideValue(processEnvToken, processEnvMock) + .provideValue(jestTestAdapterToken, (jestTestAdapterMock as unknown) as JestTestAdapter) + .provideValue(configLoaderToken, jestConfigLoaderMock) + .injectClass(JestTestRunner); + } }); diff --git a/packages/jest-runner/test/unit/configLoaders/CustomConfigLoader.spec.ts b/packages/jest-runner/test/unit/configLoaders/CustomConfigLoader.spec.ts index 9e83dbac8f..e7b27ed91b 100644 --- a/packages/jest-runner/test/unit/configLoaders/CustomConfigLoader.spec.ts +++ b/packages/jest-runner/test/unit/configLoaders/CustomConfigLoader.spec.ts @@ -9,7 +9,7 @@ import CustomJestConfigLoader from '../../../src/configLoaders/CustomJestConfigL describe(CustomJestConfigLoader.name, () => { let defaultConfigLoader: CustomJestConfigLoader; - const projectRoot: string = '/path/to/project/root'; + const projectRoot = '/path/to/project/root'; let readFileSyncStub: sinon.SinonStub; let requireStub: sinon.SinonStub; diff --git a/packages/jest-runner/test/unit/configLoaders/DefaultConfigLoader.spec.ts b/packages/jest-runner/test/unit/configLoaders/DefaultConfigLoader.spec.ts index 53ab255670..535f929049 100644 --- a/packages/jest-runner/test/unit/configLoaders/DefaultConfigLoader.spec.ts +++ b/packages/jest-runner/test/unit/configLoaders/DefaultConfigLoader.spec.ts @@ -9,7 +9,7 @@ import CustomJestConfigLoader from '../../../src/configLoaders/CustomJestConfigL describe(`${CustomJestConfigLoader.name} integration`, () => { let sut: CustomJestConfigLoader; - const projectRoot: string = '/path/to/project/root'; + const projectRoot = '/path/to/project/root'; const fsStub: FsStub = {}; let requireStub: sinon.SinonStub; diff --git a/packages/jest-runner/test/unit/configLoaders/ReactScriptsTsJestConfigLoader.spec.ts b/packages/jest-runner/test/unit/configLoaders/ReactScriptsTsJestConfigLoader.spec.ts index 57f8946beb..7d367f4536 100644 --- a/packages/jest-runner/test/unit/configLoaders/ReactScriptsTsJestConfigLoader.spec.ts +++ b/packages/jest-runner/test/unit/configLoaders/ReactScriptsTsJestConfigLoader.spec.ts @@ -1,5 +1,9 @@ import path from 'path'; +import { Logger } from '@stryker-mutator/api/logging'; + +import { logger } from '@stryker-mutator/test-helpers/src/factory'; + import { assert, expect } from 'chai'; import sinon from 'sinon'; @@ -10,6 +14,7 @@ describe(ReactScriptsTSJestConfigLoader.name, () => { let sut: ReactScriptsTSJestConfigLoader; let requireResolveStub: sinon.SinonStub; let createReactJestConfigStub: sinon.SinonStub; + let loggerStub: sinon.SinonStubbedInstance; const projectRoot = '/path/to/project'; const reactScriptsTsPackagePath = './node_modules/react-scripts-ts/package.json'; @@ -25,7 +30,9 @@ describe(ReactScriptsTSJestConfigLoader.name, () => { requireResolveStub = sinon.stub(); requireResolveStub.returns(reactScriptsTsPackagePath); - sut = new ReactScriptsTSJestConfigLoader((requireResolveStub as unknown) as RequireResolve, projectRoot); + loggerStub = logger(); + + sut = new ReactScriptsTSJestConfigLoader(loggerStub, (requireResolveStub as unknown) as RequireResolve, projectRoot); }); it('should load the configuration via the createJestConfig method provided by react-scripts-ts', () => { @@ -34,6 +41,16 @@ describe(ReactScriptsTSJestConfigLoader.name, () => { assert(requireResolveStub.calledWith('react-scripts-ts/package.json')); }); + it('should log a deprecation warning', () => { + sut.loadConfig(); + + assert( + loggerStub.warn.calledWith( + 'DEPRECATED: The support for create-react-app-ts projects is deprecated and will be removed in the future. Please migrate your project to create-react-app and update your Stryker config setting to "create-react-app" (see https://create-react-app.dev/docs/adding-typescript/)' + ) + ); + }); + it('should generate a configuration', () => { const config = sut.loadConfig(); diff --git a/packages/jest-runner/test/unit/configLoaders/configLoaderFactory.spec.ts b/packages/jest-runner/test/unit/configLoaders/configLoaderFactory.spec.ts index 9cfedc174b..0b8ec6eec5 100644 --- a/packages/jest-runner/test/unit/configLoaders/configLoaderFactory.spec.ts +++ b/packages/jest-runner/test/unit/configLoaders/configLoaderFactory.spec.ts @@ -2,6 +2,7 @@ import { testInjector, factory } from '@stryker-mutator/test-helpers'; import { expect } from 'chai'; import Sinon, * as sinon from 'sinon'; import { commonTokens } from '@stryker-mutator/api/plugin'; +import { Config } from '@jest/types'; import CustomJestConfigLoader, * as defaultJestConfigLoader from '../../../src/configLoaders/CustomJestConfigLoader'; import ReactScriptsJestConfigLoader, * as reactScriptsJestConfigLoader from '../../../src/configLoaders/ReactScriptsJestConfigLoader'; @@ -24,7 +25,7 @@ describe(configLoaderFactory.name, () => { sinon.stub(reactScriptsJestConfigLoader, 'default').returns(reactScriptsJestConfigLoaderStub); sinon.stub(reactScriptsTSJestConfigLoader, 'default').returns(reactScriptsTSJestConfigLoaderStub); - const defaultOptions: Partial = { + const defaultOptions: Partial = { collectCoverage: true, verbose: true, bail: false, @@ -48,9 +49,9 @@ describe(configLoaderFactory.name, () => { expect(sut).eq(customConfigLoaderStub); }); - describe('with "projectType": "react"', () => { + describe('with "projectType": "create-react-app"', () => { beforeEach(() => { - options.jest.projectType = 'react'; + options.jest.projectType = 'create-react-app'; }); it('should create a ReactScriptsJestConfigLoader', () => { @@ -62,19 +63,11 @@ describe(configLoaderFactory.name, () => { it('should warn when a configFile is set', () => { testConfigFileWarning(options); }); - - it('should log a deprecation warning', () => { - testInjector.injector.provideValue(commonTokens.options, options).injectFunction(configLoaderFactory); - - expect(testInjector.logger.warn).calledWith( - 'DEPRECATED: The projectType "react" is deprecated. Use projectType "create-react-app" for react projects created by "create-react-app" or use "custom" for other react projects.' - ); - }); }); - describe('with "projectType": "react-ts"', () => { + describe('with "projectType": "create-react-app-ts"', () => { beforeEach(() => { - options.jest.projectType = 'react-ts'; + options.jest.projectType = 'create-react-app-ts'; }); it('should create a ReactScriptsTSJestConfigLoader', () => { @@ -86,14 +79,6 @@ describe(configLoaderFactory.name, () => { it('should warn when a configFile is set', () => { testConfigFileWarning(options); }); - - it('should log a deprecation warning', () => { - testInjector.injector.provideValue(commonTokens.options, options).injectFunction(configLoaderFactory); - - expect(testInjector.logger.warn).calledWith( - 'DEPRECATED: The projectType "react-ts" is deprecated. Use projectType "create-react-app-ts" for react projects created by "create-react-app" or use "custom" for other react projects.' - ); - }); }); }); diff --git a/packages/jest-runner/test/unit/jestTestAdapters/JestGreaterThan25Adapter.spec.ts b/packages/jest-runner/test/unit/jestTestAdapters/JestGreaterThan25Adapter.spec.ts index 5221ab1e4b..7a0b82443d 100644 --- a/packages/jest-runner/test/unit/jestTestAdapters/JestGreaterThan25Adapter.spec.ts +++ b/packages/jest-runner/test/unit/jestTestAdapters/JestGreaterThan25Adapter.spec.ts @@ -2,6 +2,8 @@ import { testInjector } from '@stryker-mutator/test-helpers'; import { expect } from 'chai'; import sinon from 'sinon'; +import { Config } from '@jest/types'; + import JestGreaterThan25Adapter from '../../../src/jestTestAdapters/JestGreaterThan25Adapter'; import { jestWrapper } from '../../../src/utils/jestWrapper'; @@ -11,16 +13,14 @@ describe(JestGreaterThan25Adapter.name, () => { const projectRoot = '/path/to/project'; const fileNameUnderTest = '/path/to/file'; - const jestConfig: any = { rootDir: projectRoot }; + const jestConfig: Config.InitialOptions = { rootDir: projectRoot }; beforeEach(() => { runCLIStub = sinon.stub(jestWrapper, 'runCLI'); - runCLIStub.callsFake((config: object) => - Promise.resolve({ - config, - result: 'testResult', - }) - ); + runCLIStub.resolves({ + config: jestConfig, + result: 'testResult', + }); sut = testInjector.injector.injectClass(JestGreaterThan25Adapter); }); @@ -67,14 +67,7 @@ describe(JestGreaterThan25Adapter.name, () => { const result = await sut.run(jestConfig, projectRoot); expect(result).to.deep.equal({ - config: { - $0: 'stryker', - _: [], - config: JSON.stringify({ rootDir: projectRoot, reporters: [] }), - runInBand: true, - silent: true, - findRelatedTests: false, - }, + config: jestConfig, result: 'testResult', }); }); @@ -83,14 +76,7 @@ describe(JestGreaterThan25Adapter.name, () => { const result = await sut.run(jestConfig, projectRoot, fileNameUnderTest); expect(result).to.deep.equal({ - config: { - $0: 'stryker', - _: [fileNameUnderTest], - config: JSON.stringify({ rootDir: projectRoot, reporters: [] }), - findRelatedTests: true, - runInBand: true, - silent: true, - }, + config: jestConfig, result: 'testResult', }); }); diff --git a/packages/jest-runner/testResources/exampleProject/src/Add.js b/packages/jest-runner/testResources/exampleProject/src/Add.js index 58d562ec25..f849cc5cfe 100644 --- a/packages/jest-runner/testResources/exampleProject/src/Add.js +++ b/packages/jest-runner/testResources/exampleProject/src/Add.js @@ -1,20 +1,96 @@ -exports.add = function(num1, num2) { - return num1 + num2; +// @ts-nocheck +var __global_69fa48 = (function(g){ + if (g.__activeMutant__ === undefined && g.process && g.process.env && g.process.env.__STRYKER_ACTIVE_MUTANT__) { + g.__activeMutant__ = Number(g.process.env.__STRYKER_ACTIVE_MUTANT__); + } + g.__mutantCoverage__ = g.__mutantCoverage__ || { static: {}, perTest: {} }; + g.__coverMutant__ = g.__coverMutant__ || function () { + var c = g.__mutantCoverage__.static; + if (g.__currentTestId__) { + c = g.__mutantCoverage__.perTest[g.__currentTestId__] = g.__mutantCoverage__.perTest[g.__currentTestId__] || {}; + } + var a = arguments; + for(var i=0; i < a.length; i++){ + c[a[i]] = (c[a[i]] || 0) + 1; + } + }; + return g; +})(new Function("return this")()) + +exports.add = function (num1, num2) { + switch (__global_69fa48.__activeMutant__) { + case 0: + {} + break; + + default: + __global_69fa48.__coverMutant__(0); + { + return __global_69fa48.__activeMutant__ === 1 ? num1 - num2 : (__global_69fa48.__coverMutant__(1), num1 + num2); + } + break; + } }; -exports.addOne = function(number) { - number++; - return number; +exports.addOne = function (number) { + switch (__global_69fa48.__activeMutant__) { + case 2: + {} + break; + + default: + __global_69fa48.__coverMutant__(2); + { + number++; + return number; + } + break; + } }; -exports.negate = function(number) { - return -number; +exports.negate = function (number) { + switch (__global_69fa48.__activeMutant__) { + case 3: + {} + break; + + default: + __global_69fa48.__coverMutant__(3); + { + return -number; + } + break; + } }; -exports.isNegativeNumber = function(number) { - var isNegative = false; - if(number < 0){ - isNegative = true; +exports.isNegativeNumber = function (number) { + switch (__global_69fa48.__activeMutant__) { + case 4: + {} + break; + + default: + __global_69fa48.__coverMutant__(4); + { + var isNegative = false; + + if (__global_69fa48.__activeMutant__ === 6 ? false : __global_69fa48.__activeMutant__ === 5 ? true : (__global_69fa48.__coverMutant__(5, 6), number < 0)) { + switch (__global_69fa48.__activeMutant__) { + case 7: + {} + break; + + default: + __global_69fa48.__coverMutant__(7); + { + isNegative = true; + } + break; + } + } + + return isNegative; + } + break; } - return isNegative; -}; \ No newline at end of file +}; diff --git a/packages/jest-runner/testResources/exampleProject/src/Circle.js b/packages/jest-runner/testResources/exampleProject/src/Circle.js index 616d48643f..407d7cb05b 100644 --- a/packages/jest-runner/testResources/exampleProject/src/Circle.js +++ b/packages/jest-runner/testResources/exampleProject/src/Circle.js @@ -1,8 +1,49 @@ -exports.getCircumference = function(radius) { - //Function to test multiple math mutations in a single function. - return 2 * Math.PI * radius; +// @ts-nocheck +var __global_69fa48 = (function(g){ + if (g.__activeMutant__ === undefined && g.process && g.process.env && g.process.env.__STRYKER_ACTIVE_MUTANT__) { + g.__activeMutant__ = Number(g.process.env.__STRYKER_ACTIVE_MUTANT__); + } + g.__mutantCoverage__ = g.__mutantCoverage__ || { static: {}, perTest: {} }; + g.__coverMutant__ = g.__coverMutant__ || function () { + var c = g.__mutantCoverage__.static; + if (g.__currentTestId__) { + c = g.__mutantCoverage__.perTest[g.__currentTestId__] = g.__mutantCoverage__.perTest[g.__currentTestId__] || {}; + } + var a = arguments; + for(var i=0; i < a.length; i++){ + c[a[i]] = (c[a[i]] || 0) + 1; + } + }; + return g; +})(new Function("return this")()) + +exports.getCircumference = function (radius) { + switch (__global_69fa48.__activeMutant__) { + case 8: + {} + break; + + default: + __global_69fa48.__coverMutant__(8); + { + //Function to test multiple math mutations in a single function. + return __global_69fa48.__activeMutant__ === 9 ? 2 * Math.PI / radius : (__global_69fa48.__coverMutant__(9), (__global_69fa48.__activeMutant__ === 10 ? 2 / Math.PI : (__global_69fa48.__coverMutant__(10), 2 * Math.PI)) * radius); + } + break; + } }; -exports.untestedFunction = function() { - var i = 5 / 2 * 3; -}; \ No newline at end of file +var untestedFunction = function () { + switch (__global_69fa48.__activeMutant__) { + case 11: + {} + break; + + default: + __global_69fa48.__coverMutant__(11); + { + var i = __global_69fa48.__activeMutant__ === 12 ? 5 / 2 / 3 : (__global_69fa48.__coverMutant__(12), (__global_69fa48.__activeMutant__ === 13 ? 5 * 2 : (__global_69fa48.__coverMutant__(13), 5 / 2)) * 3); + } + break; + } +}; diff --git a/packages/jest-runner/testResources/exampleProject/src/__tests__/AddSpec.js b/packages/jest-runner/testResources/exampleProject/src/__tests__/AddSpec.js index c31f82d7dd..afaedcd539 100644 --- a/packages/jest-runner/testResources/exampleProject/src/__tests__/AddSpec.js +++ b/packages/jest-runner/testResources/exampleProject/src/__tests__/AddSpec.js @@ -40,11 +40,4 @@ describe('Add', function() { expect(isNegative).toBe(true); }); - it('should be able to recognize that 0 is not a negative number', function() { - var number = 0; - - var isNegative = isNegativeNumber(number); - - expect(isNegative).toBe(false); - }); -}); \ No newline at end of file +}); diff --git a/packages/jest-runner/testResources/exampleProjectWithDefaultJestConfig/src/__tests__/AddSpec.js b/packages/jest-runner/testResources/exampleProjectWithDefaultJestConfig/src/__tests__/AddSpec.js index c31f82d7dd..afaedcd539 100644 --- a/packages/jest-runner/testResources/exampleProjectWithDefaultJestConfig/src/__tests__/AddSpec.js +++ b/packages/jest-runner/testResources/exampleProjectWithDefaultJestConfig/src/__tests__/AddSpec.js @@ -40,11 +40,4 @@ describe('Add', function() { expect(isNegative).toBe(true); }); - it('should be able to recognize that 0 is not a negative number', function() { - var number = 0; - - var isNegative = isNegativeNumber(number); - - expect(isNegative).toBe(false); - }); -}); \ No newline at end of file +}); diff --git a/packages/jest-runner/testResources/exampleProjectWithExplicitJestConfig/src/__tests__/AddSpec.js b/packages/jest-runner/testResources/exampleProjectWithExplicitJestConfig/src/__tests__/AddSpec.js index c31f82d7dd..afaedcd539 100644 --- a/packages/jest-runner/testResources/exampleProjectWithExplicitJestConfig/src/__tests__/AddSpec.js +++ b/packages/jest-runner/testResources/exampleProjectWithExplicitJestConfig/src/__tests__/AddSpec.js @@ -40,11 +40,4 @@ describe('Add', function() { expect(isNegative).toBe(true); }); - it('should be able to recognize that 0 is not a negative number', function() { - var number = 0; - - var isNegative = isNegativeNumber(number); - - expect(isNegative).toBe(false); - }); -}); \ No newline at end of file +}); diff --git a/packages/jest-runner/testResources/reactTsProject/package.json b/packages/jest-runner/testResources/reactTsProject/package.json index 6adea42fcf..87e8032e40 100644 --- a/packages/jest-runner/testResources/reactTsProject/package.json +++ b/packages/jest-runner/testResources/reactTsProject/package.json @@ -3,9 +3,9 @@ "version": "0.1.0", "private": true, "dependencies": { - "react": "^16.3.1", - "react-dom": "^16.3.1", - "react-scripts-ts": "2.14.0" + "react": "~16.13.1", + "react-dom": "~16.13.1", + "react-scripts-ts": "~2.14.0" }, "scripts": { "start": "react-scripts-ts start", @@ -14,8 +14,8 @@ "eject": "react-scripts-ts eject" }, "devDependencies": { - "@types/jest": "^22.2.3", - "@types/react": "^16.3.9", - "@types/react-dom": "^16.0.5" + "@types/jest": "~22.2.3", + "@types/react": "~16.9.48", + "@types/react-dom": "~16.9.8" } } diff --git a/packages/jest-runner/tsconfig.src.json b/packages/jest-runner/tsconfig.src.json index 8273a9ffad..a9e7c61a47 100644 --- a/packages/jest-runner/tsconfig.src.json +++ b/packages/jest-runner/tsconfig.src.json @@ -13,6 +13,9 @@ "references": [ { "path": "../api/tsconfig.src.json", + }, + { + "path": "../util/tsconfig.src.json", } ] } diff --git a/packages/jest-runner/tsconfig.stryker.json b/packages/jest-runner/tsconfig.stryker.json deleted file mode 100644 index 97966f860e..0000000000 --- a/packages/jest-runner/tsconfig.stryker.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "./tsconfig.test.json", - "include": [ - "src", - "test", - "typings" - ], -} diff --git a/packages/jest-runner/typings/jest/index.d.ts b/packages/jest-runner/typings/jest/index.d.ts deleted file mode 100644 index 2b06eed42a..0000000000 --- a/packages/jest-runner/typings/jest/index.d.ts +++ /dev/null @@ -1,54 +0,0 @@ -declare namespace Jest { - // RunCLI does not have any official types, this will do for our implementation - function runCLI(cliParams: RunCliParameters, projectRoots: string[]): any; - - // Taken from https://goo.gl/qHifyP, removed all stuff that we are not using - // Also added 'runInBand' which does not exist in the official types - interface RunCliParameters { - config: string; - runInBand: boolean; - silent: boolean; - findRelatedTests?: boolean; - _?: string[]; - } - - // Taken from https://goo.gl/qHifyP, removed all stuff that we are not using - interface Configuration { - rootDir?: Path; - reporters: string[]; - bail: boolean; - collectCoverage: boolean; - verbose: boolean; - testResultsProcessor?: string; - testEnvironment: string; - } - - interface RunResult { - results: AggregatedResult; - } - - // Taken from https://goo.gl/h48ajP, removed all stuff that we are not using - interface AggregatedResult { - numRuntimeErrorTestSuites: number; - testResults: TestResult[]; - } - - // Taken from https://goo.gl/nAzQ4J, removed all stuff that we are not using - interface TestResult { - failureMessage?: string | null; - testResults: AssertionResult[]; - } - - // Taken from https://goo.gl/drWMCB, removed all stuff that we are not using - interface AssertionResult { - duration?: Milliseconds | null; - failureMessages: string[]; - fullName: string; - status: Status; - } - - // - type Milliseconds = number; - type Status = 'passed' | 'failed' | 'skipped' | 'pending' | 'todo' | 'disabled'; - type Path = string; -} diff --git a/packages/karma-runner/.mocharc.jsonc b/packages/karma-runner/.mocharc.jsonc new file mode 100644 index 0000000000..dc3280aa96 --- /dev/null +++ b/packages/karma-runner/.mocharc.jsonc @@ -0,0 +1,3 @@ +{ + "require": "test/setup.js" +} diff --git a/packages/karma-runner/.nycrc.json b/packages/karma-runner/.nycrc.json new file mode 100644 index 0000000000..404e2f0916 --- /dev/null +++ b/packages/karma-runner/.nycrc.json @@ -0,0 +1,11 @@ +{ + "exclude-after-remap": false, + "check-coverage": true, + "reporter": ["text", "html"], + "report-dir": "reports/coverage", + "lines": 95, + "functions": 95, + "statements": 95, + "branches": 85, + "include": "src/**/*.js" +} diff --git a/packages/karma-runner/.vscode/launch.json b/packages/karma-runner/.vscode/launch.json index c139f57d7b..fef31f0c4d 100644 --- a/packages/karma-runner/.vscode/launch.json +++ b/packages/karma-runner/.vscode/launch.json @@ -1,53 +1,45 @@ { "version": "0.2.0", "configurations": [ - { - "type": "node", - "request": "launch", - "name": "Karma with angular", - "program": "${workspaceFolder}/run-angular.js", - "cwd": "C:\\z\\github\\nicojs\\angular-stryker-example", - "outFiles": [ - "${workspaceRoot}/src/**/*.js", - "${workspaceRoot}/run-angular.js" - ] - }, { "type": "node", "request": "launch", "name": "Unit tests", "program": "${workspaceRoot}/../../node_modules/mocha/bin/_mocha", "args": [ - "--timeout", - "999999", - "--colors", - "${workspaceRoot}/test/helpers/**/*.js", + "--no-timeout", "${workspaceRoot}/test/unit/**/*.js" ], + "cwd": "${workspaceFolder}", "internalConsoleOptions": "openOnSessionStart", "outFiles": [ "${workspaceRoot}/test/**/*.js", "${workspaceRoot}/src/**/*.js" - ] + ], + "skipFiles": [ + "/**" + ], }, { "type": "node", "request": "launch", "name": "Integration tests", "program": "${workspaceRoot}/../../node_modules/mocha/bin/_mocha", + "cwd": "${workspaceFolder}", "args": [ - "--timeout", - "999999", - "--colors", - "${workspaceRoot}/test/helpers/**/*.js", + "--no-timeout", + "--exit", "${workspaceRoot}/test/integration/**/*.js" ], "internalConsoleOptions": "openOnSessionStart", "outFiles": [ "${workspaceRoot}/test/**/*.js", "${workspaceRoot}/src/**/*.js" - ] + ], + "skipFiles": [ + "/**" + ], } ], "compounds": [] -} \ No newline at end of file +} diff --git a/packages/karma-runner/CHANGELOG.md b/packages/karma-runner/CHANGELOG.md index 1b943d7c95..c7bdfaddb6 100644 --- a/packages/karma-runner/CHANGELOG.md +++ b/packages/karma-runner/CHANGELOG.md @@ -3,6 +3,106 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [4.0.0-beta.10](https://github.io/stryker-mutator/stryker/compare/v4.0.0-beta.9...v4.0.0-beta.10) (2020-10-05) + +**Note:** Version bump only for package @stryker-mutator/karma-runner + + + + + +# [4.0.0-beta.9](https://github.io/stryker-mutator/stryker/compare/v4.0.0-beta.8...v4.0.0-beta.9) (2020-09-30) + +**Note:** Version bump only for package @stryker-mutator/karma-runner + + + + + +# [4.0.0-beta.8](https://github.io/stryker-mutator/stryker/compare/v4.0.0-beta.7...v4.0.0-beta.8) (2020-09-22) + +**Note:** Version bump only for package @stryker-mutator/karma-runner + + + + + +# [4.0.0-beta.7](https://github.io/stryker-mutator/stryker/compare/v4.0.0-beta.6...v4.0.0-beta.7) (2020-09-17) + +**Note:** Version bump only for package @stryker-mutator/karma-runner + + + + + +# [4.0.0-beta.6](https://github.io/stryker-mutator/stryker/compare/v4.0.0-beta.5...v4.0.0-beta.6) (2020-09-10) + +**Note:** Version bump only for package @stryker-mutator/karma-runner + + + + + +# [4.0.0-beta.5](https://github.io/stryker-mutator/stryker/compare/v4.0.0-beta.4...v4.0.0-beta.5) (2020-09-09) + +**Note:** Version bump only for package @stryker-mutator/karma-runner + + + + + +# [4.0.0-beta.4](https://github.io/stryker-mutator/stryker/compare/v4.0.0-beta.3...v4.0.0-beta.4) (2020-08-29) + + +### Features + +* **api:** rename test_runner2 -> test_runner ([#2442](https://github.io/stryker-mutator/stryker/issues/2442)) ([4d3ae97](https://github.io/stryker-mutator/stryker/commit/4d3ae9764dbd689c895b76e44f2eea76c82fabc8)) +* **karma-runner:** force bail = true in all cases ([ba928a1](https://github.io/stryker-mutator/stryker/commit/ba928a10d9e4c67ade9648927fb6b281ad2e3d55)) + + +### BREAKING CHANGES + +* **api:** Plugin creators should now use `'test_runner'` instead of `'test_runner2'`. + + + + + +# [4.0.0-beta.3](https://github.io/stryker-mutator/stryker/compare/v4.0.0-beta.2...v4.0.0-beta.3) (2020-08-19) + +**Note:** Version bump only for package @stryker-mutator/karma-runner + + + + + +# [4.0.0-beta.2](https://github.io/stryker-mutator/stryker/compare/v4.0.0-beta.1...v4.0.0-beta.2) (2020-08-07) + +**Note:** Version bump only for package @stryker-mutator/karma-runner + + + + + +# [4.0.0-beta.1](https://github.io/stryker-mutator/stryker/compare/v4.0.0-beta.0...v4.0.0-beta.1) (2020-07-17) + +**Note:** Version bump only for package @stryker-mutator/karma-runner + + + + + +# [4.0.0-beta.0](https://github.io/stryker-mutator/stryker/compare/v3.3.1...v4.0.0-beta.0) (2020-07-10) + + +### Bug Fixes + +* **karma-runner:** mocha filtering with `/` ([#2290](https://github.io/stryker-mutator/stryker/issues/2290)) ([3918633](https://github.io/stryker-mutator/stryker/commit/3918633b21ff37d2e950df2cc14b8557ee7eb6b3)) + + + + + ## [3.3.1](https://github.io/stryker-mutator/stryker/compare/v3.3.0...v3.3.1) (2020-07-04) **Note:** Version bump only for package @stryker-mutator/karma-runner diff --git a/packages/karma-runner/package.json b/packages/karma-runner/package.json index 074edfb0e9..9516883d4b 100644 --- a/packages/karma-runner/package.json +++ b/packages/karma-runner/package.json @@ -1,13 +1,13 @@ { "name": "@stryker-mutator/karma-runner", - "version": "3.3.1", + "version": "4.0.0-beta.10", "description": "A plugin to use the karma test runner in Stryker, the JavaScript mutation testing framework", "main": "src/index.js", "scripts": { - "test": "nyc --exclude-after-remap=false --check-coverage --reporter=html --report-dir=reports/coverage --lines 80 --functions 80 --branches 75 npm run mocha", - "mocha": "npm run test:unit && npm run test:integration", - "test:unit": "mocha \"test/helpers/**/*.js\" \"test/unit/**/*.js\"", - "test:integration": "mocha --timeout 30000 --exit \"test/helpers/**/*.js\" \"test/integration/**/*.js\"", + "test": "nyc npm run test:all", + "test:all": "npm run test:unit && npm run test:integration", + "test:unit": "mocha \"test/unit/**/*.js\"", + "test:integration": "mocha --timeout 30000 --exit \"test/integration/**/*.js\"", "stryker": "node ../core/bin/stryker run" }, "repository": { @@ -32,26 +32,24 @@ }, "homepage": "https://github.com/stryker-mutator/stryker/tree/master/packages/karma-runner#readme", "devDependencies": { - "@stryker-mutator/jasmine-framework": "^3.3.1", - "@stryker-mutator/mocha-framework": "^3.3.1", - "@stryker-mutator/test-helpers": "^3.3.1", - "@stryker-mutator/util": "^3.3.1", + "@stryker-mutator/test-helpers": "4.0.0-beta.10", "@types/express": "~4.17.0", "@types/node": "^14.0.1", - "@types/semver": "~7.2.0", - "jasmine-core": "~3.5.0", - "karma": "~5.0.1", - "karma-chai": "^0.1.0", + "@types/semver": "~7.3.1", + "jasmine-core": "~3.6.0", + "karma": "~5.1.0", + "karma-chai": "~0.1.0", "karma-chrome-launcher": "~3.1.0", "karma-jasmine": "~3.0.1", - "karma-mocha": "^2.0.0" + "karma-mocha": "~2.0.0" }, "peerDependencies": { - "@stryker-mutator/core": "^3.0.0" + "@stryker-mutator/core": "~4.0.0" }, "dependencies": { - "@stryker-mutator/api": "^3.3.1", - "decamelize": "^4.0.0", + "@stryker-mutator/api": "4.0.0-beta.10", + "@stryker-mutator/util": "4.0.0-beta.10", + "decamelize": "~4.0.0", "semver": "~6.3.0", "tslib": "~2.0.0" }, diff --git a/packages/karma-runner/src/KarmaTestRunner.ts b/packages/karma-runner/src/KarmaTestRunner.ts index 56dbfe240f..0a86e15d17 100644 --- a/packages/karma-runner/src/KarmaTestRunner.ts +++ b/packages/karma-runner/src/KarmaTestRunner.ts @@ -1,16 +1,25 @@ -import { StrykerOptions } from '@stryker-mutator/api/core'; +import * as karma from 'karma'; +import { StrykerOptions, MutantCoverage } from '@stryker-mutator/api/core'; import { Logger, LoggerFactoryMethod } from '@stryker-mutator/api/logging'; import { commonTokens, tokens } from '@stryker-mutator/api/plugin'; -import { CoverageCollection, CoveragePerTestResult, RunResult, RunStatus, TestResult, TestRunner } from '@stryker-mutator/api/test_runner'; -import * as karma from 'karma'; +import { + TestRunner, + TestResult, + DryRunStatus, + DryRunOptions, + MutantRunOptions, + DryRunResult, + MutantRunResult, + toMutantRunResult, +} from '@stryker-mutator/api/test_runner'; -import strykerKarmaConf = require('./starters/stryker-karma.conf'); import { StrykerKarmaSetup } from '../src-generated/karma-runner-options'; +import strykerKarmaConf = require('./starters/stryker-karma.conf'); import ProjectStarter from './starters/ProjectStarter'; -import StrykerReporter from './StrykerReporter'; -import TestHooksMiddleware from './TestHooksMiddleware'; +import StrykerReporter from './karma-plugins/StrykerReporter'; import { KarmaRunnerOptionsWithStrykerOptions } from './KarmaRunnerOptionsWithStrykerOptions'; +import TestHooksMiddleware from './karma-plugins/TestHooksMiddleware'; export interface ConfigOptions extends karma.ConfigOptions { detached?: boolean; @@ -18,10 +27,8 @@ export interface ConfigOptions extends karma.ConfigOptions { export default class KarmaTestRunner implements TestRunner { private currentTestResults: TestResult[]; - private currentErrorMessages: string[]; - private currentCoverageReport?: CoverageCollection | CoveragePerTestResult; - private currentRunStatus: RunStatus; - private readonly testHooksMiddleware = TestHooksMiddleware.instance; + private currentErrorMessage: string | undefined; + private currentCoverageReport?: MutantCoverage; private readonly starter: ProjectStarter; public port: undefined | number; @@ -32,27 +39,31 @@ export default class KarmaTestRunner implements TestRunner { this.setGlobals(setup, getLogger); this.cleanRun(); this.listenToServerStart(); - this.listenToRunComplete(); this.listenToSpecComplete(); this.listenToCoverage(); this.listenToError(); } - public init(): Promise { + public async init(): Promise { return new Promise((res, rej) => { - StrykerReporter.instance.once('browsers_ready', res); - this.starter - .start() - .then(() => { - /*noop*/ - }) - .catch(rej); + StrykerReporter.instance.once('browsers_ready', () => res()); + this.starter.start().catch(rej); }); } - public async run({ testHooks }: { testHooks?: string }): Promise { - this.testHooksMiddleware.currentTestHooks = testHooks || ''; - if (this.currentRunStatus !== RunStatus.Error) { + public dryRun(options: DryRunOptions): Promise { + TestHooksMiddleware.instance.configureCoverageAnalysis(options.coverageAnalysis); + return this.run(); + } + + public async mutantRun(options: MutantRunOptions): Promise { + TestHooksMiddleware.instance.configureActiveMutant(options); + const dryRunResult = await this.run(); + return toMutantRunResult(dryRunResult); + } + + private async run(): Promise { + if (!this.currentErrorMessage) { // Only run when there was no compile error // An compile error can happen in case of angular-cli await this.runServer(); @@ -79,9 +90,8 @@ export default class KarmaTestRunner implements TestRunner { private cleanRun() { this.currentTestResults = []; - this.currentErrorMessages = []; + this.currentErrorMessage = undefined; this.currentCoverageReport = undefined; - this.currentRunStatus = RunStatus.Complete; } // Don't use dispose() to stop karma (using karma.stopper.stop) @@ -100,24 +110,17 @@ export default class KarmaTestRunner implements TestRunner { } private listenToCoverage() { - StrykerReporter.instance.on('coverage_report', (coverageReport: CoverageCollection | CoveragePerTestResult) => { + StrykerReporter.instance.on('coverage_report', (coverageReport: MutantCoverage) => { this.currentCoverageReport = coverageReport; }); } - private listenToRunComplete() { - StrykerReporter.instance.on('run_complete', (runStatus: RunStatus) => { - this.currentRunStatus = runStatus; - }); - } - private listenToError() { StrykerReporter.instance.on('browser_error', (error: string) => { - this.currentErrorMessages.push(error); + this.currentErrorMessage = error; }); StrykerReporter.instance.on('compile_error', (errors: string[]) => { - errors.forEach((error) => this.currentErrorMessages.push(error)); - this.currentRunStatus = RunStatus.Error; + this.currentErrorMessage = errors.join(', '); }); } @@ -130,25 +133,18 @@ export default class KarmaTestRunner implements TestRunner { }); } - private collectRunResult(): RunResult { - return { - coverage: this.currentCoverageReport, - errorMessages: this.currentErrorMessages, - status: this.determineRunState(), - tests: this.currentTestResults, - }; - } - - private determineRunState() { - // Karma will report an Error if no tests had executed. - // This is not an "error" in Stryker terms - if (this.currentRunStatus === RunStatus.Error && !this.currentErrorMessages.length && !this.currentTestResults.length) { - return RunStatus.Complete; - } else if (this.currentErrorMessages.length) { - // Karma will return Complete when there are runtime errors - return RunStatus.Error; + private collectRunResult(): DryRunResult { + if (this.currentErrorMessage) { + return { + status: DryRunStatus.Error, + errorMessage: this.currentErrorMessage, + }; } else { - return this.currentRunStatus; + return { + status: DryRunStatus.Complete, + tests: this.currentTestResults, + mutantCoverage: this.currentCoverageReport, + }; } } } diff --git a/packages/karma-runner/src/StrykerReporter.ts b/packages/karma-runner/src/StrykerReporter.ts deleted file mode 100644 index 256feba586..0000000000 --- a/packages/karma-runner/src/StrykerReporter.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { EventEmitter } from 'events'; - -import { CoverageCollection, CoverageCollectionPerTest, RunStatus, TestResult, TestStatus } from '@stryker-mutator/api/test_runner'; -import * as karma from 'karma'; - -export interface KarmaSpec { - description: string; - id: string; - skipped: boolean; - success: boolean; - time: number; - suite: string[]; - log: string[]; -} - -/** - * This is a singleton implementation of a KarmaReporter. - * It is loaded by karma and functions as a bridge between the karma world and the stryker world - * - * It uses properties as functions because karma is not able to find actual methods. - * - * i.e. use `public readonly onFoo = () => {}` instead of `onFoo() { }`. - */ -export default class StrykerReporter extends EventEmitter implements karma.Reporter { - public adapters: any[] = []; - - private constructor() { - super(); - } - - private static _instance = new StrykerReporter(); - public static get instance(): StrykerReporter { - if (!this._instance) { - this._instance = new StrykerReporter(); - } - return this._instance; - } - - public readonly onListening = (port: number) => { - this.emit('server_start', port); - }; - - public readonly onSpecComplete = (_browser: any, spec: KarmaSpec) => { - const name = spec.suite.reduce((name, suite) => name + suite + ' ', '') + spec.description; - let status = TestStatus.Failed; - if (spec.skipped) { - status = TestStatus.Skipped; - } else if (spec.success) { - status = TestStatus.Success; - } - const testResult: TestResult = { - failureMessages: spec.log, - name, - status, - timeSpentMs: spec.time, - }; - this.emit('test_result', testResult); - }; - - public readonly onRunComplete = (runResult: karma.TestResults) => { - this.emit('run_complete', this.collectRunState(runResult)); - }; - - public readonly onLoadError = (...args: any[]) => { - this.emit('load_error', ...args); - }; - - public readonly onBrowserComplete = (_browser: any, result: { coverage: CoverageCollection | CoverageCollectionPerTest }) => { - this.emit('coverage_report', result.coverage); - }; - - public readonly onBrowsersReady = () => { - this.emit('browsers_ready'); - }; - - public readonly onBrowserError = (_browser: any, error: any) => { - // Karma 2.0 has different error messages - if (error.message) { - this.emit('browser_error', error.message); - } else { - this.emit('browser_error', error.toString()); - } - }; - - public readonly onCompileError = (errors: string[]) => { - // This is called from angular cli logic - // https://github.com/angular/angular-cli/blob/012672161087a05ae5ecffbed5d1ee307ce1e0ad/packages/angular_devkit/build_angular/src/angular-cli-files/plugins/karma.ts#L96 - this.emit('compile_error', errors); - }; - - private collectRunState(runResult: karma.TestResults): RunStatus { - if (runResult.disconnected) { - return RunStatus.Timeout; - } else if (runResult.error) { - return RunStatus.Error; - } else { - return RunStatus.Complete; - } - } -} diff --git a/packages/karma-runner/src/TestHooksMiddleware.ts b/packages/karma-runner/src/TestHooksMiddleware.ts deleted file mode 100644 index ec2048d1c0..0000000000 --- a/packages/karma-runner/src/TestHooksMiddleware.ts +++ /dev/null @@ -1,36 +0,0 @@ -import * as path from 'path'; -import * as url from 'url'; - -import { RequestHandler } from 'express'; - -export const TEST_HOOKS_FILE_NAME = require.resolve('./testHooksForStryker'); - -export default class TestHooksMiddleware { - private constructor() { - // This `.bind` call is important! The `handler` will be executed with `.apply` (or friends) and otherwise the `this` won't point to this instance! - this.handler = this.handler.bind(this); - } - - private static _instance: TestHooksMiddleware; - public static get instance(): TestHooksMiddleware { - if (!this._instance) { - this._instance = new TestHooksMiddleware(); - } - return this._instance; - } - - public currentTestHooks: string = ''; - - public handler: RequestHandler = (request, response, next) => { - const pathName = url.parse(request.url).pathname; - if (pathName && path.normalize(pathName).endsWith(path.join('src', path.basename(TEST_HOOKS_FILE_NAME)))) { - response.writeHead(200, { - 'Cache-Control': 'no-cache', - 'Content-Type': 'application/javascript', - }); - response.end(this.currentTestHooks); - } else { - next(); - } - }; -} diff --git a/packages/karma-runner/src/karma-plugins/StrykerMutantCoverageAdapter.ts b/packages/karma-runner/src/karma-plugins/StrykerMutantCoverageAdapter.ts new file mode 100644 index 0000000000..2f952070e2 --- /dev/null +++ b/packages/karma-runner/src/karma-plugins/StrykerMutantCoverageAdapter.ts @@ -0,0 +1,16 @@ +// THIS FILE IS LOADED IN THE BROWSER AND SHOULD NOT BE A NODE / ES MODULE + +// @ts-expect-error +const originalComplete = window.__karma__.complete.bind(window.__karma__); +// @ts-expect-error +window.__karma__.complete = (...args) => { + // @ts-expect-error + if (window.__strykerShouldReportCoverage__) { + if (!args.length) { + args.push({}); + } + // @ts-expect-error + args[0].mutantCoverage = window.__stryker__ && window.__stryker__.mutantCoverage; + } + originalComplete(...args); +}; diff --git a/packages/karma-runner/src/karma-plugins/StrykerReporter.ts b/packages/karma-runner/src/karma-plugins/StrykerReporter.ts new file mode 100644 index 0000000000..5c09884e4f --- /dev/null +++ b/packages/karma-runner/src/karma-plugins/StrykerReporter.ts @@ -0,0 +1,111 @@ +import { EventEmitter } from 'events'; + +import { DryRunStatus, TestResult, TestStatus } from '@stryker-mutator/api/test_runner'; +import { MutantCoverage } from '@stryker-mutator/api/core'; +import * as karma from 'karma'; + +export interface KarmaSpec { + description: string; + id: string; + skipped: boolean; + success: boolean; + time: number; + suite: string[]; + log: string[]; +} + +/** + * This is a singleton implementation of a KarmaReporter. + * It is loaded by karma and functions as a bridge between the karma world and the stryker world + * + * It uses properties as functions because karma is not able to find actual methods. + * + * i.e. use `public readonly onFoo = () => {}` instead of `onFoo() { }`. + */ +export default class StrykerReporter extends EventEmitter implements karma.Reporter { + public adapters: any[] = []; + + private constructor() { + super(); + } + + private static readonly _instance = new StrykerReporter(); + public static get instance(): StrykerReporter { + return this._instance; + } + + public readonly onListening = (port: number) => { + this.emit('server_start', port); + }; + + public readonly onSpecComplete = (_browser: any, spec: KarmaSpec) => { + const name = spec.suite.reduce((name, suite) => name + suite + ' ', '') + spec.description; + const id = spec.id || name; + let testResult: TestResult; + if (spec.skipped) { + testResult = { + id, + name, + timeSpentMs: spec.time, + status: TestStatus.Skipped, + }; + } else if (spec.success) { + testResult = { + id, + name, + timeSpentMs: spec.time, + status: TestStatus.Success, + }; + } else { + testResult = { + id, + name, + timeSpentMs: spec.time, + status: TestStatus.Failed, + failureMessage: spec.log.join(','), + }; + } + this.emit('test_result', testResult); + }; + + public readonly onRunComplete = (runResult: karma.TestResults) => { + this.emit('run_complete', this.collectRunState(runResult)); + }; + + public readonly onLoadError = (...args: any[]) => { + this.emit('load_error', ...args); + }; + + public readonly onBrowserComplete = (_browser: any, result: { mutantCoverage: MutantCoverage }) => { + this.emit('coverage_report', result.mutantCoverage); + }; + + public readonly onBrowsersReady = () => { + this.emit('browsers_ready'); + }; + + public readonly onBrowserError = (_browser: any, error: any) => { + // Karma 2.0 has different error messages + if (error.message) { + this.emit('browser_error', error.message); + } else { + this.emit('browser_error', error.toString()); + } + }; + + public readonly onCompileError = (errors: string[]) => { + // This is called from angular cli logic + // https://github.com/angular/angular-cli/blob/012672161087a05ae5ecffbed5d1ee307ce1e0ad/packages/angular_devkit/build_angular/src/angular-cli-files/plugins/karma.ts#L96 + this.emit('compile_error', errors); + }; + + private collectRunState(runResult: karma.TestResults): DryRunStatus { + if (runResult.disconnected) { + return DryRunStatus.Timeout; + } else if (runResult.error) { + return DryRunStatus.Error; + } else { + return DryRunStatus.Complete; + } + } +} diff --git a/packages/karma-runner/src/karma-plugins/TestHooksMiddleware.ts b/packages/karma-runner/src/karma-plugins/TestHooksMiddleware.ts new file mode 100644 index 0000000000..5683258fa9 --- /dev/null +++ b/packages/karma-runner/src/karma-plugins/TestHooksMiddleware.ts @@ -0,0 +1,115 @@ +import * as path from 'path'; +import * as url from 'url'; + +import { RequestHandler } from 'express'; +import { CoverageAnalysis, INSTRUMENTER_CONSTANTS } from '@stryker-mutator/api/core'; +import { MutantRunOptions } from '@stryker-mutator/api/test_runner'; +import { escapeRegExpLiteral } from '@stryker-mutator/util'; + +export const TEST_HOOKS_FILE_NAME = __filename; + +const SUPPORTED_FRAMEWORKS = Object.freeze(['mocha', 'jasmine'] as const); + +type SupportedFramework = 'mocha' | 'jasmine'; + +function isSupportedFramework(framework: string): framework is SupportedFramework { + return (SUPPORTED_FRAMEWORKS as readonly string[]).includes(framework); +} + +/** + * Keep in sync with StrykerMutantCoverageAdapter.ts + */ +const SHOULD_REPORT_COVERAGE_FLAG = '__strykerShouldReportCoverage__'; + +const { ACTIVE_MUTANT, NAMESPACE, CURRENT_TEST_ID } = INSTRUMENTER_CONSTANTS; + +export default class TestHooksMiddleware { + private static _instance?: TestHooksMiddleware; + private testFramework: 'mocha' | 'jasmine' | undefined; + public currentTestHooks = ''; + + public static get instance(): TestHooksMiddleware { + if (!this._instance) { + this._instance = new TestHooksMiddleware(); + } + return this._instance; + } + + public configureTestFramework(frameworks?: string[]) { + this.testFramework = frameworks?.filter(isSupportedFramework)[0]; + } + + public configureCoverageAnalysis(coverageAnalysis: CoverageAnalysis) { + switch (coverageAnalysis) { + case 'perTest': + this.configurePerTestCoverageAnalysis(); + break; + case 'all': + this.currentTestHooks = `window.${SHOULD_REPORT_COVERAGE_FLAG} = true;`; + break; + case 'off': + this.currentTestHooks = `window.${SHOULD_REPORT_COVERAGE_FLAG} = false;`; + break; + } + } + + public configureActiveMutant({ activeMutant, testFilter }: MutantRunOptions) { + this.configureCoverageAnalysis('off'); + this.currentTestHooks += `window.${NAMESPACE} = window.${NAMESPACE} || {}; + window.${NAMESPACE}.${ACTIVE_MUTANT} = ${activeMutant.id};`; + if (testFilter) { + switch (this.testFramework) { + case 'jasmine': + this.currentTestHooks += `jasmine.getEnv().configure({ specFilter: function(spec) { + return ${JSON.stringify(testFilter)}.indexOf(spec.id) !== -1; + }})`; + break; + case 'mocha': + const metaRegExp = testFilter.map((testId) => `(${escapeRegExpLiteral(testId)})`).join('|'); + this.currentTestHooks += `mocha.grep(/${metaRegExp}/)`; + break; + } + } + } + + private configurePerTestCoverageAnalysis() { + switch (this.testFramework) { + case 'jasmine': + this.currentTestHooks = ` + window.${SHOULD_REPORT_COVERAGE_FLAG} = true; + jasmine.getEnv().addReporter({ + specStarted: function (spec) { + window.${NAMESPACE}.${CURRENT_TEST_ID} = spec.id; + } + });`; + break; + case 'mocha': + this.currentTestHooks = ` + window.${SHOULD_REPORT_COVERAGE_FLAG} = true; + beforeEach(function() { + window.${NAMESPACE}.${CURRENT_TEST_ID} = this.currentTest && this.currentTest.fullTitle(); + }); + `; + break; + case undefined: + throw new Error( + `Could not configure coverageAnalysis "perTest". Your test framework is not supported by the \`@stryker-mutator/karma-runner\`. Supported test frameworks: ${SUPPORTED_FRAMEWORKS.join( + ', ' + )}.` + ); + } + } + + public handler: RequestHandler = (request, response, next) => { + const pathName = url.parse(request.url).pathname; + if (pathName && path.normalize(pathName).endsWith(TEST_HOOKS_FILE_NAME)) { + response.writeHead(200, { + 'Cache-Control': 'no-cache', + 'Content-Type': 'application/javascript', + }); + response.end(this.currentTestHooks); + } else { + next(); + } + }; +} diff --git a/packages/karma-runner/src/starters/stryker-karma.conf.ts b/packages/karma-runner/src/starters/stryker-karma.conf.ts index 1b135076ea..777abe067d 100644 --- a/packages/karma-runner/src/starters/stryker-karma.conf.ts +++ b/packages/karma-runner/src/starters/stryker-karma.conf.ts @@ -1,11 +1,11 @@ import * as path from 'path'; import { Logger, LoggerFactoryMethod } from '@stryker-mutator/api/logging'; -import { Config, ConfigOptions } from 'karma'; +import { Config, ConfigOptions, ClientOptions, InlinePluginType } from 'karma'; import { noopLogger } from '@stryker-mutator/util'; -import StrykerReporter from '../StrykerReporter'; -import TestHooksMiddleware, { TEST_HOOKS_FILE_NAME } from '../TestHooksMiddleware'; +import StrykerReporter from '../karma-plugins/StrykerReporter'; +import TestHooksMiddleware, { TEST_HOOKS_FILE_NAME } from '../karma-plugins/TestHooksMiddleware'; import { requireModule } from '../utils'; function setDefaultOptions(config: Config) { @@ -62,7 +62,21 @@ function setClientOptions(config: Config) { // Enabling clearContext (default true) will load "about:blank" in the iFrame after a test run. // As far as I can see clearing the context only has a visible effect (you don't see the result of the last test). // If this is true, disabling it is safe to do and solves the race condition issue. - config.set({ client: { clearContext: false } }); + const clientOptions: Partial = { clearContext: false }; + + // Disable randomized tests with using jasmine. Stryker doesn't play nice with a random test order, since spec id's tent to move around + // Also set failFast, so that we're not waiting on more than 1 failed test + if (config.frameworks?.includes('jasmine')) { + (clientOptions as any).jasmine = { + random: false, + failFast: true, + }; + } + + if (config.frameworks?.includes('mocha')) { + (clientOptions as any).mocha = { bail: true }; + } + config.set({ client: clientOptions }); } function setUserKarmaConfig(config: Config) { @@ -82,7 +96,7 @@ function setBasePath(config: Config) { } } -function addPlugin(karmaConfig: ConfigOptions, karmaPlugin: any) { +function addPlugin(karmaConfig: ConfigOptions, karmaPlugin: string | Record) { karmaConfig.plugins = karmaConfig.plugins || ['karma-*']; karmaConfig.plugins.push(karmaPlugin); } @@ -97,11 +111,25 @@ function configureTestHooksMiddleware(config: Config) { config.files = config.files || []; config.files.unshift({ pattern: TEST_HOOKS_FILE_NAME, included: true, watched: false, served: false, nocache: true }); // Add a custom hooks file to provide hooks - const middleware: string[] = (config as any).middleware || ((config as any).middleware = []); + const middleware: string[] = config.beforeMiddleware || (config.beforeMiddleware = []); middleware.unshift(TestHooksMiddleware.name); + + TestHooksMiddleware.instance.configureTestFramework(config.frameworks); + addPlugin(config, { [`middleware:${TestHooksMiddleware.name}`]: ['value', TestHooksMiddleware.instance.handler] }); } +function configureStrykerMutantCoverageAdapter(config: Config) { + config.files = config.files || []; + config.files.unshift({ + pattern: require.resolve('../karma-plugins/StrykerMutantCoverageAdapter'), + included: true, + watched: false, + served: true, + nocache: true, + }); +} + function configureStrykerReporter(config: Config) { addPlugin(config, { [`reporter:${StrykerReporter.name}`]: ['value', StrykerReporter.instance] }); if (!config.reporters) { @@ -120,28 +148,28 @@ const globalSettings: { }, }; -export = Object.assign( - (config: Config) => { - const log = globalSettings.getLogger(path.basename(__filename)); - setDefaultOptions(config); - setUserKarmaConfigFile(config, log); - setUserKarmaConfig(config); - setBasePath(config); - setLifeCycleOptions(config); - setClientOptions(config); - configureTestHooksMiddleware(config); - configureStrykerReporter(config); - }, - { - /** - * Provide global settings for next configuration - * This is the only way we can pass through any values between the `KarmaTestRunner` and the stryker-karma.conf file. - * (not counting environment variables) - */ - setGlobals(globals: { karmaConfig?: ConfigOptions; karmaConfigFile?: string; getLogger?: LoggerFactoryMethod }) { - globalSettings.karmaConfig = globals.karmaConfig; - globalSettings.karmaConfigFile = globals.karmaConfigFile; - globalSettings.getLogger = globals.getLogger || (() => noopLogger); - }, - } -); +function configureKarma(config: Config) { + const log = globalSettings.getLogger(path.basename(__filename)); + setDefaultOptions(config); + setUserKarmaConfigFile(config, log); + setUserKarmaConfig(config); + setBasePath(config); + setLifeCycleOptions(config); + setClientOptions(config); + configureTestHooksMiddleware(config); + configureStrykerMutantCoverageAdapter(config); + configureStrykerReporter(config); +} + +/** + * Provide global settings for next configuration + * This is the only way we can pass through any values between the `KarmaTestRunner` and the stryker-karma.conf file. + * (not counting environment variables) + */ +configureKarma.setGlobals = (globals: { karmaConfig?: ConfigOptions; karmaConfigFile?: string; getLogger?: LoggerFactoryMethod }) => { + globalSettings.karmaConfig = globals.karmaConfig; + globalSettings.karmaConfigFile = globals.karmaConfigFile; + globalSettings.getLogger = globals.getLogger || (() => noopLogger); +}; + +export = configureKarma; diff --git a/packages/karma-runner/src/testHooksForStryker.ts b/packages/karma-runner/src/testHooksForStryker.ts deleted file mode 100644 index 7625c7398a..0000000000 --- a/packages/karma-runner/src/testHooksForStryker.ts +++ /dev/null @@ -1 +0,0 @@ -// Keep empty file to makes sure __test_hooks_for_stryker__.js exists diff --git a/packages/karma-runner/stryker.conf.js b/packages/karma-runner/stryker.conf.js index 5f801069f7..0654f25d75 100644 --- a/packages/karma-runner/stryker.conf.js +++ b/packages/karma-runner/stryker.conf.js @@ -1,6 +1,7 @@ const path = require('path'); const settings = require('../../stryker.parent.conf'); const moduleName = __dirname.split(path.sep).pop(); +settings.plugins = settings.plugins.map(p => path.resolve(p)); settings.dashboard.module = moduleName; -settings.coverageAnalysis = 'off'; +settings.files = ['{typings,src-generated,src,test,schema}/**/*.{ts,json}', '*.{ts,json}'] module.exports = settings; diff --git a/packages/karma-runner/test/helpers/assertions.ts b/packages/karma-runner/test/helpers/assertions.ts index 3c7255cd2e..e220a23224 100644 --- a/packages/karma-runner/test/helpers/assertions.ts +++ b/packages/karma-runner/test/helpers/assertions.ts @@ -1,8 +1,22 @@ -import { RunResult, TestStatus } from '@stryker-mutator/api/test_runner'; +import { CompleteDryRunResult, TestStatus, SkippedTestResult, FailedTestResult, SuccessTestResult } from '@stryker-mutator/api/test_runner'; import { expect } from 'chai'; -export function expectTestResults(result: RunResult, expectedTestResults: Array<{ name: string; status: TestStatus }>) { - const actualTestResults = result.tests.map((test) => ({ name: test.name, status: test.status })); +export type TimelessTestResult = + | Omit + | Omit + | Omit; + +/** + * Compares test results without comparing the time it took to run them + */ +export function expectTestResults(result: CompleteDryRunResult, expectedTestResults: TimelessTestResult[]) { + const actualTestResults: TimelessTestResult[] = result.tests.map((test) => { + const { timeSpentMs, ...timeless } = test; + if (timeless.status === TestStatus.Failed) { + timeless.failureMessage = timeless.failureMessage.split('\n')[0]; + } + return timeless; + }); expect(actualTestResults).to.have.length(expectedTestResults.length); expectedTestResults.forEach((expectedTestResult) => { const actualTestResult = actualTestResults.find((test) => test.name === expectedTestResult.name); diff --git a/packages/karma-runner/test/helpers/initChai.ts b/packages/karma-runner/test/helpers/initChai.ts deleted file mode 100644 index 514154da42..0000000000 --- a/packages/karma-runner/test/helpers/initChai.ts +++ /dev/null @@ -1,6 +0,0 @@ -import * as chai from 'chai'; -import * as chaiAsPromised from 'chai-as-promised'; -import * as sinonChai from 'sinon-chai'; - -chai.use(sinonChai); -chai.use(chaiAsPromised); diff --git a/packages/karma-runner/test/helpers/initSinon.ts b/packages/karma-runner/test/helpers/initSinon.ts deleted file mode 100644 index b3631699bb..0000000000 --- a/packages/karma-runner/test/helpers/initSinon.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { testInjector } from '@stryker-mutator/test-helpers'; -import * as sinon from 'sinon'; - -afterEach(() => { - testInjector.reset(); - sinon.restore(); -}); diff --git a/packages/karma-runner/test/helpers/initSourceMaps.ts b/packages/karma-runner/test/helpers/initSourceMaps.ts deleted file mode 100644 index fcfbfda16c..0000000000 --- a/packages/karma-runner/test/helpers/initSourceMaps.ts +++ /dev/null @@ -1 +0,0 @@ -import 'source-map-support/register'; diff --git a/packages/karma-runner/test/integration/KarmaTestRunner.it.spec.ts b/packages/karma-runner/test/integration/KarmaTestRunner.it.spec.ts index c8ac5add9d..2b0d305c5e 100644 --- a/packages/karma-runner/test/integration/KarmaTestRunner.it.spec.ts +++ b/packages/karma-runner/test/integration/KarmaTestRunner.it.spec.ts @@ -1,33 +1,20 @@ import { promisify } from 'util'; import * as http from 'http'; -import { CoverageCollection, RunResult, RunStatus, TestStatus } from '@stryker-mutator/api/test_runner'; -import JasmineTestFramework from '@stryker-mutator/jasmine-framework/src/JasmineTestFramework'; -import MochaTestFramework from '@stryker-mutator/mocha-framework/src/MochaTestFramework'; -import { testInjector } from '@stryker-mutator/test-helpers'; +import { DryRunStatus, TestStatus, CompleteDryRunResult, TestResult, FailedTestResult } from '@stryker-mutator/api/test_runner'; +import { testInjector, assertions, factory } from '@stryker-mutator/test-helpers'; import { expect } from 'chai'; import { FilePattern } from 'karma'; -import { TestSelection } from '@stryker-mutator/api/test_framework'; import KarmaTestRunner from '../../src/KarmaTestRunner'; -import { expectTestResults } from '../helpers/assertions'; -import { KarmaRunnerOptionsWithStrykerOptions } from '../../src/KarmaRunnerOptionsWithStrykerOptions'; - -function wrapInClosure(codeFragment: string) { - return ` - (function (window) { - ${codeFragment} - })((Function('return this'))());`; -} +import StrykerReporter from '../../src/karma-plugins/StrykerReporter'; function setOptions( files: ReadonlyArray = [ 'testResources/sampleProject/src-instrumented/Add.js', 'testResources/sampleProject/test-jasmine/AddSpec.js', - ], - coverageAnalysis: 'all' | 'perTest' | 'off' = 'off' + ] ): void { - testInjector.options.coverageAnalysis = coverageAnalysis; testInjector.options.karma = { config: { files, @@ -44,96 +31,46 @@ function createSut() { describe(`${KarmaTestRunner.name} integration`, () => { let sut: KarmaTestRunner; - const expectToHaveSuccessfulTests = (result: RunResult, n: number) => { + const expectToHaveSuccessfulTests = (result: CompleteDryRunResult, n: number) => { expect(result.tests.filter((t) => t.status === TestStatus.Success)).to.have.length(n); }; - const expectToHaveFailedTests = (result: RunResult, expectedFailureMessages: string[]) => { - const actualFailedTests = result.tests.filter((t) => t.status === TestStatus.Failed); + const expectToHaveFailedTests = (result: CompleteDryRunResult, expectedFailureMessages: string[]) => { + const actualFailedTests = result.tests.filter(isFailed); expect(actualFailedTests).to.have.length(expectedFailureMessages.length); actualFailedTests.forEach((failedTest) => { - const actualFailedMessage = failedTest.failureMessages ? failedTest.failureMessages[0].split('\n')[0] : ''; + const actualFailedMessage = failedTest.failureMessage.split('\n')[0]; expect(actualFailedMessage).to.be.oneOf(expectedFailureMessages); }); }; - describe('with mocha', () => { - let testFramework: MochaTestFramework; - - const test0: Readonly = Object.freeze({ - id: 0, - name: 'Add should be able to add two numbers', - }); - - const test3: Readonly = { - id: 3, - name: 'Add should be able to recognize a negative number', - }; - + describe('when all tests succeed', () => { before(() => { - testFramework = new MochaTestFramework(); - setOptions(['testResources/sampleProject/src/Add.js', 'testResources/sampleProject/test-mocha/AddSpec.js']); - (testInjector.options as KarmaRunnerOptionsWithStrykerOptions).karma.config!.frameworks = ['mocha', 'chai']; + setOptions(['testResources/sampleProject/src/Add.js', 'testResources/sampleProject/test-jasmine/AddSpec.js']); sut = createSut(); return sut.init(); }); - - it('should report completed tests', async () => { - const runResult = await sut.run({}); - expectToHaveSuccessfulTests(runResult, 5); - expectToHaveFailedTests(runResult, []); - expect(RunStatus[runResult.status]).to.be.eq(RunStatus[RunStatus.Complete]); - }); - - it('should be able to filter tests', async () => { - const testHooks = wrapInClosure(testFramework.filter([test0, test3])); - const actualResult = await sut.run({ testHooks }); - expectToHaveSuccessfulTests(actualResult, 2); - expect(actualResult.tests[0].name).eq(test0.name); - expect(actualResult.tests[1].name).eq(test3.name); - }); - - it('should be able to clear the filter after a filtered run', async () => { - await sut.run({ testHooks: wrapInClosure(testFramework.filter([test0, test3])) }); - const actualResult = await sut.run({ testHooks: wrapInClosure(testFramework.filter([])) }); - expect(actualResult.tests).lengthOf(5); + after(() => { + StrykerReporter.instance.removeAllListeners(); }); - }); - describe('when all tests succeed', () => { - describe('with simple add function to test', () => { - before(() => { - setOptions(['testResources/sampleProject/src/Add.js', 'testResources/sampleProject/test-jasmine/AddSpec.js']); - sut = createSut(); - return sut.init(); + describe('dryRun()', () => { + it('should report completed tests', async () => { + const runResult = await sut.dryRun(factory.dryRunOptions()); + assertions.expectCompleted(runResult); + expectToHaveSuccessfulTests(runResult, 5); + expectToHaveFailedTests(runResult, []); }); - it('should report completed tests', () => { - return expect(sut.run({})).to.eventually.satisfy((runResult: RunResult) => { - expectToHaveSuccessfulTests(runResult, 5); - expectToHaveFailedTests(runResult, []); - expect(RunStatus[runResult.status]).to.be.eq(RunStatus[RunStatus.Complete]); - return true; - }); + it('should be able to run twice in quick succession', async () => { + const actualResult = await sut.dryRun(factory.dryRunOptions()); + assertions.expectCompleted(actualResult); }); + }); - it('should be able to run twice in quick succession', () => - expect(sut.run({}).then(() => sut.run({}))).to.eventually.have.property('status', RunStatus.Complete)); - - it('should be able to filter tests', async () => { - const testHooks = wrapInClosure( - new JasmineTestFramework().filter([ - { id: 0, name: 'Add should be able to add two numbers' }, - { id: 3, name: 'Add should be able to recognize a negative number' }, - ]) - ); - const result = await sut.run({ testHooks }); - expectTestResults(result, [ - { name: 'Add should be able to add two numbers', status: TestStatus.Success }, - { name: 'Add should be able 1 to a number', status: TestStatus.Skipped }, - { name: 'Add should be able negate a number', status: TestStatus.Skipped }, - { name: 'Add should be able to recognize a negative number', status: TestStatus.Success }, - { name: 'Add should be able to recognize that 0 is not a negative number', status: TestStatus.Skipped }, - ]); + describe('runMutant()', () => { + it('should report the mutant as survived', async () => { + const mutantResult = await sut.mutantRun(factory.mutantRunOptions()); + assertions.expectSurvived(mutantResult); }); }); }); @@ -148,13 +85,24 @@ describe(`${KarmaTestRunner.name} integration`, () => { sut = createSut(); return sut.init(); }); - - it('should report failed tests', () => { - return expect(sut.run({})).to.eventually.satisfy((runResult: RunResult) => { + after(() => { + StrykerReporter.instance.removeAllListeners(); + }); + describe('dryRun', () => { + it('should report the first failed test (bail)', async () => { + const runResult = await sut.dryRun(factory.dryRunOptions()); + assertions.expectCompleted(runResult); expectToHaveSuccessfulTests(runResult, 5); - expectToHaveFailedTests(runResult, ['Error: Expected 7 to be 8.', 'Error: Expected 3 to be 4.']); - expect(runResult.status).to.be.eq(RunStatus.Complete); - return true; + expectToHaveFailedTests(runResult, ['Error: Expected 7 to be 8.']); + expect(runResult.status).to.be.eq(DryRunStatus.Complete); + }); + }); + describe('runMutant()', () => { + it('should report the mutant as killed', async () => { + const mutantResult = await sut.mutantRun(factory.mutantRunOptions()); + assertions.expectKilled(mutantResult); + expect(mutantResult.killedBy).eq('spec5'); + expect(mutantResult.failureMessage.split('\n')[0]).eq('Error: Expected 7 to be 8.'); }); }); }); @@ -169,12 +117,23 @@ describe(`${KarmaTestRunner.name} integration`, () => { sut = createSut(); return sut.init(); }); + after(() => { + StrykerReporter.instance.removeAllListeners(); + }); + describe('dryRun', () => { + it('should report Error with the error message', async () => { + const runResult = await sut.dryRun(factory.dryRunOptions()); + assertions.expectErrored(runResult); + expect(runResult.errorMessage).include('ReferenceError: someGlobalVariableThatIsNotDeclared is not defined'); + }); + }); - it('should report Error with the error message', async () => { - const runResult = await sut.run({}); - expect(RunStatus[runResult.status]).to.be.eq(RunStatus[RunStatus.Error]); - expect((runResult.errorMessages as string[]).length).to.equal(1); - expect((runResult.errorMessages as string[])[0]).include('ReferenceError: someGlobalVariableThatIsNotDeclared is not defined'); + describe('runMutant()', () => { + it('should report Error with the error message', async () => { + const runResult = await sut.mutantRun(factory.mutantRunOptions()); + assertions.expectErrored(runResult); + expect(runResult.errorMessage).include('ReferenceError: someGlobalVariableThatIsNotDeclared is not defined'); + }); }); }); @@ -184,16 +143,14 @@ describe(`${KarmaTestRunner.name} integration`, () => { sut = createSut(); return sut.init(); }); - - it('should report Complete without errors', () => { - return expect(sut.run({})).to.eventually.satisfy((runResult: RunResult) => { - expectToHaveSuccessfulTests(runResult, 0); - expectToHaveFailedTests(runResult, []); - expect(runResult.status).to.be.eq(RunStatus.Complete); - expect((runResult.errorMessages as string[]).length).to.equal(0); - - return true; - }); + after(() => { + StrykerReporter.instance.removeAllListeners(); + }); + it('should report Complete without errors', async () => { + const runResult = await sut.dryRun(factory.dryRunOptions()); + assertions.expectCompleted(runResult); + expectToHaveSuccessfulTests(runResult, 0); + expectToHaveFailedTests(runResult, []); }); }); @@ -207,33 +164,15 @@ describe(`${KarmaTestRunner.name} integration`, () => { sut = createSut(); return sut.init(); }); - - it('should report Complete without errors', () => { - return expect(sut.run({})).to.eventually.satisfy((runResult: RunResult) => { - expect(runResult.status, JSON.stringify(runResult.errorMessages)).to.be.eq(RunStatus.Complete); - return true; - }); + after(() => { + StrykerReporter.instance.removeAllListeners(); }); - }); - - describe('when coverage data is available', () => { - before(() => { - setOptions(['testResources/sampleProject/src-instrumented/Add.js', 'testResources/sampleProject/test-jasmine/AddSpec.js'], 'all'); - sut = createSut(); - return sut.init(); + it('should report Complete without errors', async () => { + const runResult = await sut.dryRun(factory.dryRunOptions()); + assertions.expectCompleted(runResult); }); - - it('should report coverage data', () => - expect(sut.run({})).to.eventually.satisfy((runResult: RunResult) => { - expect(runResult.coverage).to.be.ok; - expect(runResult.status).to.be.eq(RunStatus.Complete); - const files = Object.keys(runResult.coverage || {}); - expect(files).to.have.length(1); - const coverageResult = (runResult.coverage as CoverageCollection)[files[0]]; - expect(coverageResult.s).to.be.ok; - return true; - })); }); + describe('when specified port is not available', () => { let dummyServer: DummyServer; @@ -248,12 +187,13 @@ describe(`${KarmaTestRunner.name} integration`, () => { if (dummyServer) { await dummyServer.dispose(); } + StrykerReporter.instance.removeAllListeners(); }); it('should choose different port automatically and report Complete without errors', async () => { - const actualResult = await sut.run({}); + const actualResult = await sut.dryRun(factory.dryRunOptions()); expect(sut.port).not.eq(dummyServer.port); - expect(actualResult.status, JSON.stringify(actualResult.errorMessages)).eq(RunStatus.Complete); + assertions.expectCompleted(actualResult); }); }); }); @@ -288,3 +228,6 @@ class DummyServer { return promisify(this.httpServer.close.bind(this.httpServer))(); } } +function isFailed(t: TestResult): t is FailedTestResult { + return t.status === TestStatus.Failed; +} diff --git a/packages/karma-runner/test/integration/instrumented.it.spec.ts b/packages/karma-runner/test/integration/instrumented.it.spec.ts new file mode 100644 index 0000000000..df771e0641 --- /dev/null +++ b/packages/karma-runner/test/integration/instrumented.it.spec.ts @@ -0,0 +1,290 @@ +import path = require('path'); + +import { testInjector, factory, assertions } from '@stryker-mutator/test-helpers'; +import { expect } from 'chai'; +import { KilledMutantRunResult, MutantRunStatus } from '@stryker-mutator/api/test_runner'; + +import KarmaTestRunner from '../../src/KarmaTestRunner'; +import { KarmaRunnerOptionsWithStrykerOptions } from '../../src/KarmaRunnerOptionsWithStrykerOptions'; +import StrykerReporter from '../../src/karma-plugins/StrykerReporter'; + +function createSut() { + return testInjector.injector.injectClass(KarmaTestRunner); +} + +describe(`${KarmaTestRunner.name} running on instrumented code`, () => { + let sut: KarmaTestRunner; + + describe('with jasmine', () => { + before(async () => { + (testInjector.options as KarmaRunnerOptionsWithStrykerOptions).karma = { + projectType: 'custom', + configFile: path.resolve(__dirname, '..', '..', 'testResources', 'instrumented', 'karma-jasmine.conf.js'), + }; + sut = createSut(); + await sut.init(); + }); + + after(() => { + StrykerReporter.instance.removeAllListeners(); + }); + + describe('dryRun', () => { + it('should only report static coverage if coverage analysis is "all"', async () => { + const result = await sut.dryRun(factory.dryRunOptions({ coverageAnalysis: 'all' })); + assertions.expectCompleted(result); + expect(result.mutantCoverage).ok; + expect(result.mutantCoverage!.static).deep.eq({ + '0': 1, + '1': 1, + '2': 1, + '3': 1, + '4': 1, + '5': 1, + '6': 2, + '7': 2, + '8': 2, + '9': 2, + '10': 2, + '11': 2, + '12': 1, + '13': 1, + '14': 1, + '15': 1, + '16': 1, + }); + expect(result.mutantCoverage!.perTest).deep.eq({}); + }); + + it('should report "perTest" coverage if coverage analysis is "perTest"', async () => { + const result = await sut.dryRun(factory.dryRunOptions({ coverageAnalysis: 'perTest' })); + assertions.expectCompleted(result); + expect(result.mutantCoverage).ok; + expect(result.mutantCoverage!.static).deep.eq({}); + expect(result.mutantCoverage!.perTest).deep.eq({ + spec0: { + '0': 1, + '1': 1, + }, + spec1: { + '2': 1, + '3': 1, + }, + spec2: { + '4': 1, + '5': 1, + }, + spec3: { + '6': 1, + '7': 1, + '8': 1, + '9': 1, + '10': 1, + '11': 1, + '12': 1, + '13': 1, + }, + spec4: { + '6': 1, + '7': 1, + '8': 1, + '9': 1, + '10': 1, + '11': 1, + }, + spec5: { + '14': 1, + '15': 1, + '16': 1, + }, + }); + }); + + it('should not report coverage when coverage analysis is "off"', async () => { + const result = await sut.dryRun(factory.dryRunOptions({ coverageAnalysis: 'off' })); + assertions.expectCompleted(result); + expect(result.mutantCoverage).not.ok; + }); + }); + + describe('mutantRun', () => { + it('should be able to kill a mutant', async () => { + const result = await sut.mutantRun(factory.mutantRunOptions({ activeMutant: factory.mutant({ id: 0 }) })); + assertions.expectKilled(result); + expect(result.killedBy).eq('spec0'); + expect(result.failureMessage.split('\n')[0]).eq('Error: Expected undefined to be 7.'); + }); + + it('should survive if the filtered tests do not kill the mutant', async () => { + const result = await sut.mutantRun( + factory.mutantRunOptions({ + activeMutant: factory.mutant({ id: 2 }), + testFilter: [ + 'spec0', + //'spec1' => would kill the mutant + 'spec2', + ], + }) + ); + assertions.expectSurvived(result); + }); + + it('should be able to kill again after a mutant survived', async () => { + await sut.mutantRun(factory.mutantRunOptions({ activeMutant: factory.mutant({ id: 11 }) })); + const result = await sut.mutantRun(factory.mutantRunOptions({ activeMutant: factory.mutant({ id: 2 }), testFilter: ['spec1'] })); + assertions.expectKilled(result); + result.failureMessage = result.failureMessage.split('\n')[0]; + const expected = factory.killedMutantRunResult({ + killedBy: 'spec1', + status: MutantRunStatus.Killed, + failureMessage: 'Error: Expected undefined to be 3.', + nrOfTests: 1, + }); + expect(result).deep.eq(expected); + }); + + it('should be able to clear the test filter', async () => { + await sut.mutantRun(factory.mutantRunOptions({ activeMutant: factory.mutant({ id: 2 }), testFilter: ['spec1'] })); + const result = await sut.mutantRun(factory.mutantRunOptions({ activeMutant: factory.mutant({ id: 1 }), testFilter: undefined })); + assertions.expectKilled(result); + }); + }); + }); + describe('with mocha', () => { + before(async () => { + (testInjector.options as KarmaRunnerOptionsWithStrykerOptions).karma = { + projectType: 'custom', + configFile: path.resolve(__dirname, '..', '..', 'testResources', 'instrumented', 'karma-mocha.conf.js'), + }; + sut = createSut(); + await sut.init(); + }); + after(() => { + StrykerReporter.instance.removeAllListeners(); + }); + + describe('dryRun', () => { + it('should only report static coverage if coverage analysis is "all"', async () => { + const result = await sut.dryRun(factory.dryRunOptions({ coverageAnalysis: 'all' })); + assertions.expectCompleted(result); + expect(result.mutantCoverage).ok; + expect(result.mutantCoverage!.static).deep.eq({ + '0': 1, + '1': 1, + '2': 1, + '3': 1, + '4': 1, + '5': 1, + '6': 2, + '7': 2, + '8': 2, + '9': 2, + '10': 2, + '11': 2, + '12': 1, + '13': 1, + '14': 1, + '15': 1, + '16': 1, + }); + expect(result.mutantCoverage!.perTest).deep.eq({}); + }); + + it('should report "perTest" coverage if coverage analysis is "perTest"', async () => { + const result = await sut.dryRun(factory.dryRunOptions({ coverageAnalysis: 'perTest' })); + assertions.expectCompleted(result); + expect(result.mutantCoverage).ok; + expect(result.mutantCoverage!.static).deep.eq({}); + expect(result.mutantCoverage!.perTest).deep.eq({ + 'Add should be able to add two numbers': { + '0': 1, + '1': 1, + }, + 'Add should be able 1 to a number': { + '2': 1, + '3': 1, + }, + 'Add should be able negate a number': { + '4': 1, + '5': 1, + }, + 'Add should be able to recognize a negative number': { + '6': 1, + '7': 1, + '8': 1, + '9': 1, + '10': 1, + '11': 1, + '12': 1, + '13': 1, + }, + 'Add should be able to recognize that 0 is not a negative number': { + '6': 1, + '7': 1, + '8': 1, + '9': 1, + '10': 1, + '11': 1, + }, + 'Circle should have a circumference of 2PI when the radius is 1': { + '14': 1, + '15': 1, + '16': 1, + }, + }); + }); + }); + + describe('mutantRun', () => { + it('should be able to kill a mutant', async () => { + const result = await sut.mutantRun(factory.mutantRunOptions({ activeMutant: factory.mutant({ id: 0 }) })); + assertions.expectKilled(result); + expect(result.killedBy).eq('Add should be able to add two numbers'); + expect(result.failureMessage.split('\n')[0]).eq('AssertionError: expected undefined to equal 7'); + }); + + it('should bail after first failing test', async () => { + const result = await sut.mutantRun(factory.mutantRunOptions({ activeMutant: factory.mutant({ id: 0 }) })); + assertions.expectKilled(result); + expect(result.nrOfTests).eq(1); + }); + + it('should survive if the filtered tests do not kill the mutant', async () => { + const result = await sut.mutantRun( + factory.mutantRunOptions({ + activeMutant: factory.mutant({ id: 2 }), + testFilter: [ + 'Add should be able to add two numbers', + //'Add should be able 1 to a number' => would kill the mutant + 'Add should be able negate a number', + ], + }) + ); + assertions.expectSurvived(result); + expect(result.nrOfTests).eq(2); + }); + + it('should be able to kill again after a mutant survived', async () => { + await sut.mutantRun(factory.mutantRunOptions({ activeMutant: factory.mutant({ id: 11 }) })); + const result = await sut.mutantRun( + factory.mutantRunOptions({ activeMutant: factory.mutant({ id: 2 }), testFilter: ['Add should be able 1 to a number'] }) + ); + assertions.expectKilled(result); + result.failureMessage = result.failureMessage.split('\n')[0]; + const expected: KilledMutantRunResult = { + killedBy: 'Add should be able 1 to a number', + status: MutantRunStatus.Killed, + failureMessage: 'AssertionError: expected undefined to equal 3', + nrOfTests: 1, + }; + expect(result).deep.eq(expected); + }); + + it('should be able to clear the test filter', async () => { + await sut.mutantRun(factory.mutantRunOptions({ activeMutant: factory.mutant({ id: 2 }), testFilter: ['Add should be able 1 to a number'] })); + const result = await sut.mutantRun(factory.mutantRunOptions({ activeMutant: factory.mutant({ id: 1 }), testFilter: undefined })); + assertions.expectKilled(result); + }); + }); + }); +}); diff --git a/packages/karma-runner/test/integration/read-config.it.spec.ts b/packages/karma-runner/test/integration/read-config.it.spec.ts new file mode 100644 index 0000000000..ae4bb496c1 --- /dev/null +++ b/packages/karma-runner/test/integration/read-config.it.spec.ts @@ -0,0 +1,49 @@ +import path = require('path'); + +import { testInjector, factory, assertions } from '@stryker-mutator/test-helpers'; +import { TestStatus } from '@stryker-mutator/api/test_runner'; +import { expect } from 'chai'; + +import KarmaTestRunner from '../../src/KarmaTestRunner'; +import StrykerReporter from '../../src/karma-plugins/StrykerReporter'; + +describe('read config integration', () => { + afterEach(() => { + StrykerReporter.instance.removeAllListeners(); + }); + it('should not override client options in a mocha project', async () => { + testInjector.options.karma = { + configFile: path.resolve(__dirname, '..', '..', 'testResources', 'configs', 'mocha-client-options-karma.conf.js'), + }; + const runner = testInjector.injector.injectClass(KarmaTestRunner); + await runner.init(); + const dryRunResult = await runner.dryRun(factory.dryRunOptions()); + assertions.expectCompleted(dryRunResult); + expect(dryRunResult.tests).lengthOf(2); + const [test1, test2] = dryRunResult.tests; + expect(test1.status).eq(TestStatus.Success); + expect(test1.id).eq('mocha client options should not override client options'); + assertions.expectFailed(test2); + expect(test2.id).eq('mocha client options should override bail'); + expect(test2.failureMessage).contains('Expected exception'); + }); + it('should not override client options in a jasmine project', async () => { + testInjector.options.karma = { + configFile: path.resolve(__dirname, '..', '..', 'testResources', 'configs', 'jasmine-client-options-karma.conf.js'), + }; + const runner = testInjector.injector.injectClass(KarmaTestRunner); + await runner.init(); + const dryRunResult = await runner.dryRun(factory.dryRunOptions()); + assertions.expectCompleted(dryRunResult); + expect(dryRunResult.tests).lengthOf(3); + const [test1, test2, test3] = dryRunResult.tests; + expect([test1.name, test2.name, test3.name]).deep.eq([ + 'jasmine client options should not override client options', + 'jasmine client options should override "random" options', + 'jasmine client options should override "failFast" options', + ]); + expect(test1.status).eq(TestStatus.Success); + expect(test2.status).eq(TestStatus.Success); + expect(test3.status).eq(TestStatus.Success); + }); +}); diff --git a/packages/karma-runner/test/integration/sample.it.spec.ts b/packages/karma-runner/test/integration/sample.it.spec.ts index fb448623a5..f2275fa175 100644 --- a/packages/karma-runner/test/integration/sample.it.spec.ts +++ b/packages/karma-runner/test/integration/sample.it.spec.ts @@ -1,54 +1,102 @@ import * as path from 'path'; import { TestStatus } from '@stryker-mutator/api/test_runner'; -import { testInjector } from '@stryker-mutator/test-helpers'; +import { testInjector, assertions, factory } from '@stryker-mutator/test-helpers'; import KarmaTestRunner from '../../src/KarmaTestRunner'; -import { expectTestResults } from '../helpers/assertions'; +import { expectTestResults, TimelessTestResult } from '../helpers/assertions'; +import { KarmaRunnerOptionsWithStrykerOptions } from '../../src/KarmaRunnerOptionsWithStrykerOptions'; +import StrykerReporter from '../../src/karma-plugins/StrykerReporter'; describe('Sample project', () => { - it('should be able to run karma', async () => { - testInjector.options.karma = { configFile: path.resolve(__dirname, '..', '..', 'testResources', 'sampleProject', 'karma.conf.js') }; + afterEach(() => { + StrykerReporter.instance.removeAllListeners(); + }); + + it('should be able to run karma with jasmine', async () => { + testInjector.options.karma = { configFile: path.resolve(__dirname, '..', '..', 'testResources', 'sampleProject', 'karma-jasmine.conf.js') }; const runner = testInjector.injector.injectClass(KarmaTestRunner); await runner.init(); - const result = await runner.run({}); - expectTestResults(result, [ - { - name: 'Add should be able to add two numbers and add one', - status: TestStatus.Failed, - }, - { - name: 'Add should be to add able 1 to a number and actually add 2', - status: TestStatus.Failed, - }, + const result = await runner.dryRun(factory.dryRunOptions()); + assertions.expectCompleted(result); + const expectedTestResults: TimelessTestResult[] = [ { + id: 'spec0', name: 'Add should be able to add two numbers', status: TestStatus.Success, }, { + id: 'spec1', name: 'Add should be able 1 to a number', status: TestStatus.Success, }, { + id: 'spec2', name: 'Add should be able negate a number', status: TestStatus.Success, }, { + id: 'spec3', name: 'Add should be able to recognize a negative number', status: TestStatus.Success, }, { + id: 'spec4', name: 'Add should be able to recognize that 0 is not a negative number', status: TestStatus.Success, }, { + id: 'spec5', name: 'Circle should have a circumference of 2PI when the radius is 1', status: TestStatus.Success, }, { + id: 'spec6', name: 'Add this test should fail', status: TestStatus.Failed, + failureMessage: 'Error: Expected 7 to be 0.', + }, + ]; + expectTestResults(result, expectedTestResults); + }); + + it('should be able to run karma with mocha', async () => { + (testInjector.options as KarmaRunnerOptionsWithStrykerOptions).karma = { + projectType: 'custom', + configFile: path.resolve(__dirname, '..', '..', 'testResources', 'sampleProject', 'karma-mocha.conf.js'), + }; + + const runner = testInjector.injector.injectClass(KarmaTestRunner); + await runner.init(); + const result = await runner.dryRun(factory.dryRunOptions()); + assertions.expectCompleted(result); + const expectedTestResults: TimelessTestResult[] = [ + { + id: 'Add should be able to add two numbers', + name: 'Add should be able to add two numbers', + status: TestStatus.Success, + }, + { + id: 'Add should be able 1 to a number', + name: 'Add should be able 1 to a number', + status: TestStatus.Success, + }, + { + id: 'Add should be able negate a number', + name: 'Add should be able negate a number', + status: TestStatus.Success, + }, + { + id: 'Add should be able to recognize a negative number', + name: 'Add should be able to recognize a negative number', + status: TestStatus.Success, + }, + { + id: 'Add should be able to recognize that 0 is not a negative number', + name: 'Add should be able to recognize that 0 is not a negative number', + status: TestStatus.Success, }, - ]); + ]; + expectTestResults(result, expectedTestResults); }); }); diff --git a/packages/karma-runner/test/setup.ts b/packages/karma-runner/test/setup.ts new file mode 100644 index 0000000000..9fa0e1dbfd --- /dev/null +++ b/packages/karma-runner/test/setup.ts @@ -0,0 +1,24 @@ +import 'source-map-support/register'; +import { testInjector } from '@stryker-mutator/test-helpers'; +import * as chai from 'chai'; +import * as chaiAsPromised from 'chai-as-promised'; +import * as sinonChai from 'sinon-chai'; + +import sinon = require('sinon'); + +chai.use(sinonChai); +chai.use(chaiAsPromised); + +/** + * During integration testing we're creating many karma instances. + * Each instance of karma wants to register a SIGINT and SIGTERM handlers. + * We want them to allow doing so, since that will make sure browsers are closed when the integration test process is closed + */ +process.setMaxListeners(40); + +export const mochaHooks = { + afterEach() { + testInjector.reset(); + sinon.restore(); + }, +}; diff --git a/packages/karma-runner/test/unit/KarmaTestRunner.spec.ts b/packages/karma-runner/test/unit/KarmaTestRunner.spec.ts index 52ca220cd8..9c989882b1 100644 --- a/packages/karma-runner/test/unit/KarmaTestRunner.spec.ts +++ b/packages/karma-runner/test/unit/KarmaTestRunner.spec.ts @@ -2,8 +2,8 @@ import { EventEmitter } from 'events'; import { LoggerFactoryMethod } from '@stryker-mutator/api/logging'; import { commonTokens } from '@stryker-mutator/api/plugin'; -import { RunStatus, TestResult, TestStatus } from '@stryker-mutator/api/test_runner'; -import { testInjector } from '@stryker-mutator/test-helpers'; +import { DryRunStatus } from '@stryker-mutator/api/test_runner'; +import { testInjector, assertions, factory } from '@stryker-mutator/test-helpers'; import { expect } from 'chai'; import * as karma from 'karma'; import * as sinon from 'sinon'; @@ -12,24 +12,26 @@ import strykerKarmaConf = require('../../src/starters/stryker-karma.conf'); import KarmaTestRunner from '../../src/KarmaTestRunner'; import ProjectStarter, * as projectStarterModule from '../../src/starters/ProjectStarter'; import { StrykerKarmaSetup, NgConfigOptions } from '../../src-generated/karma-runner-options'; -import StrykerReporter from '../../src/StrykerReporter'; -import TestHooksMiddleware from '../../src/TestHooksMiddleware'; +import StrykerReporter from '../../src/karma-plugins/StrykerReporter'; +import TestHooksMiddleware from '../../src/karma-plugins/TestHooksMiddleware'; -describe('KarmaTestRunner', () => { +describe(KarmaTestRunner.name, () => { let projectStarterMock: sinon.SinonStubbedInstance; let setGlobalsStub: sinon.SinonStub; let reporterMock: EventEmitter; let karmaRunStub: sinon.SinonStub; let getLogger: LoggerFactoryMethod; + let testHooksMiddlewareMock: sinon.SinonStubbedInstance; beforeEach(() => { reporterMock = new EventEmitter(); projectStarterMock = sinon.createStubInstance(ProjectStarter); + testHooksMiddlewareMock = sinon.createStubInstance(TestHooksMiddleware); sinon.stub(projectStarterModule, 'default').returns(projectStarterMock); sinon.stub(StrykerReporter, 'instance').value(reporterMock); setGlobalsStub = sinon.stub(strykerKarmaConf, 'setGlobals'); karmaRunStub = sinon.stub(karma.runner, 'run'); - sinon.stub(TestHooksMiddleware, 'instance').value({}); + sinon.stub(TestHooksMiddleware, 'instance').value(testHooksMiddlewareMock); getLogger = testInjector.injector.resolve(commonTokens.getLogger); }); @@ -111,7 +113,7 @@ describe('KarmaTestRunner', () => { }); }); - describe('run', () => { + describe('dryRun', () => { let sut: KarmaTestRunner; beforeEach(() => { @@ -121,92 +123,77 @@ describe('KarmaTestRunner', () => { it('should not execute "karma run" when results are already clear', async () => { reporterMock.emit('compile_error', ['foobar']); - await sut.run({}); + await sut.dryRun(factory.dryRunOptions()); expect(karmaRunStub).not.called; }); it('should clear run results between runs', async () => { - const firstTestResult = testResult(); + const firstTestResult = factory.testResult(); reporterMock.emit('test_result', firstTestResult); - const actualFirstResult = await sut.run({}); - const actualSecondResult = await sut.run({}); + const actualFirstResult = await sut.dryRun(factory.dryRunOptions()); + const actualSecondResult = await sut.dryRun(factory.dryRunOptions()); + assertions.expectCompleted(actualFirstResult); + assertions.expectCompleted(actualSecondResult); expect(actualFirstResult.tests).deep.eq([firstTestResult]); expect(actualSecondResult.tests).lengthOf(0); }); - it('should set testHooks middleware to empty if no testHooks provided', async () => { - await sut.run({}); - expect(TestHooksMiddleware.instance.currentTestHooks).eq(''); - }); - - it('should set testHooks middleware when testHooks are provided', async () => { - await sut.run({ testHooks: 'foobar' }); - expect(TestHooksMiddleware.instance.currentTestHooks).eq('foobar'); + it('should configure the coverage analysis in the test hooks middleware', async () => { + await sut.dryRun(factory.dryRunOptions({ coverageAnalysis: 'all' })); + expect(testHooksMiddlewareMock.configureCoverageAnalysis).calledWithExactly('all'); }); it('should add a test result when the on reporter raises the "test_result" event', async () => { - const expected = testResult(); + const expected = factory.testResult(); reporterMock.emit('test_result', expected); - const actualResult = await sut.run({}); + const actualResult = await sut.dryRun(factory.dryRunOptions()); + assertions.expectCompleted(actualResult); expect(actualResult.tests).deep.eq([expected]); }); it('should add coverage report when the reporter raises the "coverage_report" event', async () => { const expectedCoverageReport = { some: 'coverage' }; reporterMock.emit('coverage_report', expectedCoverageReport); - const actualResult = await sut.run({}); - expect(actualResult.coverage).eq(expectedCoverageReport); + const actualResult = await sut.dryRun(factory.dryRunOptions()); + assertions.expectCompleted(actualResult); + expect(actualResult.mutantCoverage).eq(expectedCoverageReport); }); it('should add error when the reporter raises the "browser_error" event', async () => { const expectedError = 'Global variable undefined'; reporterMock.emit('browser_error', expectedError); - const actualResult = await sut.run({}); - expect(actualResult.errorMessages).deep.eq([expectedError]); + const actualResult = await sut.dryRun(factory.dryRunOptions()); + assertions.expectErrored(actualResult); + expect(actualResult.errorMessage).deep.eq(expectedError); }); it('should add error when the reporter raises the "compile_error" event', async () => { const expectedErrors = ['foo', 'bar']; reporterMock.emit('compile_error', expectedErrors); - const actualResult = await sut.run({}); - expect(actualResult.errorMessages).deep.eq(expectedErrors); - }); - - it('should set result status when the reporter raises the "run_complete" event', async () => { - reporterMock.emit('run_complete', RunStatus.Timeout); - const actualResult = await sut.run({}); - expect(actualResult.status).eq(RunStatus.Timeout); - }); - - it('should convert run state Error to a Complete when no tests where ran or no error messages where reported', async () => { - reporterMock.emit('run_complete', RunStatus.Error); - const actualResult = await sut.run({}); - expect(actualResult.status).eq(RunStatus.Complete); + const actualResult = await sut.dryRun(factory.dryRunOptions()); + assertions.expectErrored(actualResult); + expect(actualResult.errorMessage).deep.eq('foo, bar'); }); it('should report state Error when tests where ran and run completed in an error', async () => { - reporterMock.emit('test_result', testResult()); - reporterMock.emit('run_complete', RunStatus.Error); - const actualResult = await sut.run({}); - expect(actualResult.status).eq(RunStatus.Error); + reporterMock.emit('test_result', factory.testResult()); + reporterMock.emit('browser_error', 'some error'); + const actualResult = await sut.dryRun(factory.dryRunOptions()); + assertions.expectErrored(actualResult); }); it('should report state Error when error messages were reported', async () => { reporterMock.emit('browser_error', 'Undefined var'); - reporterMock.emit('run_complete', RunStatus.Complete); - const actualResult = await sut.run({}); - expect(actualResult.status).eq(RunStatus.Error); + reporterMock.emit('run_complete', DryRunStatus.Complete); + const actualResult = await sut.dryRun(factory.dryRunOptions()); + assertions.expectErrored(actualResult); }); }); - function testResult(overrides?: Partial): TestResult { - return Object.assign( - { - name: 'foobar', - status: TestStatus.Success, - timeSpentMs: 0, - }, - overrides - ); - } + describe('mutantRun', () => { + // it('should set testHooks middleware when testHooks are provided', async () => { + // await sut.run({ testHooks: 'foobar' }); + // expect(TestHooksMiddleware.instance.currentTestHooks).eq('foobar'); + // }); + }); }); diff --git a/packages/karma-runner/test/unit/StrykerReporter.spec.ts b/packages/karma-runner/test/unit/karma-plugins/StrykerReporter.spec.ts similarity index 88% rename from packages/karma-runner/test/unit/StrykerReporter.spec.ts rename to packages/karma-runner/test/unit/karma-plugins/StrykerReporter.spec.ts index 9bf03b9312..e1c3f4ce0e 100644 --- a/packages/karma-runner/test/unit/StrykerReporter.spec.ts +++ b/packages/karma-runner/test/unit/karma-plugins/StrykerReporter.spec.ts @@ -1,8 +1,9 @@ -import { RunStatus, TestResult, TestStatus } from '@stryker-mutator/api/test_runner'; +import { DryRunStatus, TestResult, TestStatus } from '@stryker-mutator/api/test_runner'; import { expect } from 'chai'; import { TestResults } from 'karma'; +import { MutantCoverage } from '@stryker-mutator/api/core'; -import StrykerReporter, { KarmaSpec } from '../../src/StrykerReporter'; +import StrykerReporter, { KarmaSpec } from '../../../src/karma-plugins/StrykerReporter'; describe('StrykerReporter', () => { let sut: StrykerReporter; @@ -30,6 +31,7 @@ describe('StrykerReporter', () => { sut.onSpecComplete( undefined, karmaSpec({ + id: '23', description: '3', success: true, suite: ['1', '2'], @@ -37,7 +39,7 @@ describe('StrykerReporter', () => { }) ); const expectedTestResult: TestResult = { - failureMessages: [], + id: '23', name: '1 2 3', status: TestStatus.Success, timeSpentMs: 64, @@ -67,7 +69,7 @@ describe('StrykerReporter', () => { }); describe('onRunComplete', () => { - let events: () => RunStatus[]; + let events: () => DryRunStatus[]; beforeEach(() => { events = listenTo('run_complete'); @@ -84,7 +86,7 @@ describe('StrykerReporter', () => { error: true, }) ); - expect(events()[0]).eq(RunStatus.Error); + expect(events()[0]).eq(DryRunStatus.Error); }); it('should convert disconnected to RunState.Timeout', () => { @@ -93,7 +95,7 @@ describe('StrykerReporter', () => { disconnected: true, }) ); - expect(events()[0]).eq(RunStatus.Timeout); + expect(events()[0]).eq(DryRunStatus.Timeout); }); }); @@ -118,8 +120,8 @@ describe('StrykerReporter', () => { describe('onBrowserComplete', () => { it('should emit "coverage_report"', () => { const events = listenTo('coverage_report'); - const expectedCoverage = { ['foobar.js']: { s: [] } }; - sut.onBrowserComplete(undefined, { coverage: expectedCoverage }); + const expectedCoverage: MutantCoverage = { static: { [1]: 4 }, perTest: {} }; + sut.onBrowserComplete(undefined, { mutantCoverage: expectedCoverage }); expect(events()).lengthOf(1); expect(events()[0]).eq(expectedCoverage); }); diff --git a/packages/karma-runner/test/unit/karma-plugins/TestHooksMiddleware.spec.ts b/packages/karma-runner/test/unit/karma-plugins/TestHooksMiddleware.spec.ts new file mode 100644 index 0000000000..33f18ff56a --- /dev/null +++ b/packages/karma-runner/test/unit/karma-plugins/TestHooksMiddleware.spec.ts @@ -0,0 +1,140 @@ +import { expect } from 'chai'; +import { factory } from '@stryker-mutator/test-helpers'; +import { Request, NextFunction, Response } from 'express'; + +import sinon = require('sinon'); + +import TestHooksMiddleware, { TEST_HOOKS_FILE_NAME } from '../../../src/karma-plugins/TestHooksMiddleware'; + +describe(TestHooksMiddleware.name, () => { + let sut: TestHooksMiddleware; + + beforeEach(() => { + sut = new TestHooksMiddleware(); + }); + + describe('configureCoverageAnalysis', () => { + it('should set __strykerShouldReportCoverage__ to false if coverage analysis is "off"', () => { + sut.configureCoverageAnalysis('off'); + expect(sut.currentTestHooks).contains('window.__strykerShouldReportCoverage__ = false'); + }); + it('should set __strykerShouldReportCoverage__ to true if coverage analysis is not "off"', () => { + sut.configureCoverageAnalysis('all'); + expect(sut.currentTestHooks).contains('window.__strykerShouldReportCoverage__ = true'); + }); + + describe('perTest', () => { + it('should throw if the current test framework is not supported', () => { + sut.configureTestFramework(['chai', 'requirejs', 'tap']); // "tap" is not yet supported + expect(() => sut.configureCoverageAnalysis('perTest')).throws( + 'Could not configure coverageAnalysis "perTest". Your test framework is not supported by the `@stryker-mutator/karma-runner`. Supported test frameworks: mocha, jasmine' + ); + }); + + it('should should set a jasmine reporter if current testFramework is "jasmine"', () => { + sut.configureTestFramework(['chai', 'jasmine', 'requirejs']); + sut.configureCoverageAnalysis('perTest'); + expect(sut.currentTestHooks) + .contains('window.__strykerShouldReportCoverage__ = true') + .contains('window.__stryker__.currentTestId = spec.id') + .and.contains('jasmine.getEnv().addReporter(') + .and.not.contains('beforeEach(function() {'); + }); + + it('should should set a beforeEach hook if current testFramework is "mocha"', () => { + sut.configureTestFramework(['chai', 'mocha', 'requirejs']); + sut.configureCoverageAnalysis('perTest'); + expect(sut.currentTestHooks) + .contains('window.__strykerShouldReportCoverage__ = true') + .contains('window.__stryker__.currentTestId = this.currentTest && this.currentTest.fullTitle()') + .and.contains('beforeEach(function() {') + .and.not.contains('jasmine.getEnv().addReporter('); + }); + }); + }); + + describe('configureActiveMutant', () => { + it('should set __strykerShouldReportCoverage__ to false', () => { + sut.configureActiveMutant(factory.mutantRunOptions()); + expect(sut.currentTestHooks).contains('window.__strykerShouldReportCoverage__ = false'); + }); + + it('should declare the __stryker__ namespace', () => { + sut.configureActiveMutant(factory.mutantRunOptions({ activeMutant: factory.mutant({ id: 42 }) })); + expect(sut.currentTestHooks).contains('window.__stryker__ = window.__stryker__ || {}'); + }); + + it('should set the "activeMutant" id', () => { + sut.configureActiveMutant(factory.mutantRunOptions({ activeMutant: factory.mutant({ id: 42 }) })); + expect(sut.currentTestHooks).contains('window.__stryker__.activeMutant = 42'); + }); + + it("should ignore the test filter if the current test framework doesn't support it", () => { + sut.configureActiveMutant(factory.mutantRunOptions({ testFilter: ['fooSpec'] })); + expect(sut.currentTestHooks).not.contains('fooSpec'); + }); + + it('should set the jasmine specFilter if the current testFramework is "jasmine"', () => { + sut.configureTestFramework(['jasmine']); + sut.configureActiveMutant(factory.mutantRunOptions({ testFilter: ['fooSpec', 'barSpec'] })); + expect(sut.currentTestHooks) + .contains('jasmine.getEnv().configure({ specFilter: function(spec) {') + .contains('return ["fooSpec","barSpec"].indexOf(spec.id) !== -1'); + }); + it('should use mocha\'s `grep` to filter tests if the current testFramework is "mocha"', () => { + sut.configureTestFramework(['mocha']); + sut.configureActiveMutant(factory.mutantRunOptions({ testFilter: ['fooSpec', 'barSpec'] })); + expect(sut.currentTestHooks).contains('mocha.grep(/(fooSpec)|(barSpec)/)'); + }); + it("should escape RegExp special characters while while configuring mocha's grep", () => { + sut.configureTestFramework(['mocha']); + sut.configureActiveMutant(factory.mutantRunOptions({ testFilter: ['foo.spec', 'bar?spec'] })); + expect(sut.currentTestHooks).contains('mocha.grep(/(foo\\.spec)|(bar\\?spec)/)'); + }); + it('should escape `/` in the regex literal', () => { + sut.configureTestFramework(['mocha']); + sut.configureActiveMutant( + factory.mutantRunOptions({ testFilter: ['MutationTestReportTotalsComponent should show N/A when no mutation score is available'] }) + ); + expect(sut.currentTestHooks).contains( + 'mocha.grep(/(MutationTestReportTotalsComponent should show N\\/A when no mutation score is available)/)' + ); + }); + }); + + describe('handler', () => { + let request: Request; + let response: Response; + let next: NextFunction; + + beforeEach(() => { + request = { + url: '', + } as Request; + response = ({ + writeHead: sinon.stub(), + end: sinon.stub(), + } as unknown) as Response; + next = sinon.stub(); + }); + + it('should pass through normal requests', () => { + request.url = '/karma/base.js'; + sut.handler(request, response, next); + expect(next).called; + expect(response.writeHead).not.called; + }); + + it('should pass serve "currentTestHooks" when called with the correct url', () => { + sut.currentTestHooks = 'foo test hooks'; + request.url = `/absolute${TEST_HOOKS_FILE_NAME}?foo=bar`; + sut.handler(request, response, next); + expect(next).not.called; + expect(response.writeHead).calledWith(200, { + 'Cache-Control': 'no-cache', + 'Content-Type': 'application/javascript', + }); + expect(response.end).calledWith('foo test hooks'); + }); + }); +}); diff --git a/packages/karma-runner/test/unit/starters/stryker-karma.conf.spec.ts b/packages/karma-runner/test/unit/starters/stryker-karma.conf.spec.ts index 238c988659..3adaece0b5 100644 --- a/packages/karma-runner/test/unit/starters/stryker-karma.conf.spec.ts +++ b/packages/karma-runner/test/unit/starters/stryker-karma.conf.spec.ts @@ -2,12 +2,12 @@ import * as path from 'path'; import { testInjector } from '@stryker-mutator/test-helpers'; import { expect } from 'chai'; -import { Config, ConfigOptions } from 'karma'; +import { Config, ConfigOptions, ClientOptions } from 'karma'; import * as sinon from 'sinon'; import sut = require('../../../src/starters/stryker-karma.conf'); -import StrykerReporter from '../../../src/StrykerReporter'; -import TestHooksMiddleware, { TEST_HOOKS_FILE_NAME } from '../../../src/TestHooksMiddleware'; +import StrykerReporter from '../../../src/karma-plugins/StrykerReporter'; +import TestHooksMiddleware, { TEST_HOOKS_FILE_NAME } from '../../../src/karma-plugins/TestHooksMiddleware'; import * as utils from '../../../src/utils'; describe('stryker-karma.conf.js', () => { @@ -48,6 +48,7 @@ describe('stryker-karma.conf.js', () => { requireModuleStub.returns((conf: Config) => conf.set({ basePath: 'foobar', + frameworks: ['mocha'], }) ); sut.setGlobals({ karmaConfigFile: 'foobar.conf.js' }); @@ -57,6 +58,7 @@ describe('stryker-karma.conf.js', () => { // Assert expect(config).deep.include({ basePath: 'foobar' }); + expect(config).deep.include({ frameworks: ['mocha'] }); expect(requireModuleStub).calledWith(path.resolve('foobar.conf.js')); }); @@ -98,22 +100,58 @@ describe('stryker-karma.conf.js', () => { // See https://github.com/stryker-mutator/stryker/issues/2049 it('should force clearContext to false', () => { // Arrange - requireModuleStub.returns((conf: Config) => conf.set({ client: { clearContext: true } })); + sut.setGlobals({ getLogger, karmaConfigFile: 'karma.conf.js' }); + requireModuleStub.returns((conf: Config) => conf.set({ client: { clearContext: true }, frameworks: ['mocha'] })); // Act sut(config); // Assert - expect(config).deep.include({ client: { clearContext: false } }); + expect(config.client?.clearContext).false; + }); + + it('should force non-random and failFast options when dealing with jasmine', () => { + // Arrange + sut.setGlobals({ getLogger, karmaConfigFile: 'karma.conf.js' }); + requireModuleStub.returns((conf: Config) => conf.set({ client: { jasmine: { random: true } } as ClientOptions, frameworks: ['jasmine'] })); + + // Act + sut(config); + + // Assert + expect((config.client as any).jasmine).deep.eq({ random: false, failFast: true }); + }); + + it('should force bail options when dealing with mocha', () => { + // Arrange + sut.setGlobals({ getLogger, karmaConfigFile: 'karma.conf.js' }); + requireModuleStub.returns((conf: Config) => conf.set({ client: { mocha: { bail: false } } as ClientOptions, frameworks: ['mocha'] })); + + // Act + sut(config); + + // Assert + expect((config.client as any).mocha).deep.include({ bail: true }); }); it('should configure the tests hooks middleware', () => { + // Arrange + sinon.stub(TestHooksMiddleware.instance, 'configureTestFramework'); + requireModuleStub.returns((conf: Config) => + conf.set({ + frameworks: ['my', 'framework'], + }) + ); + sut.setGlobals({ karmaConfigFile: 'foobar.conf.js' }); + + // Act sut(config); - expect(config).deep.include({ - files: [{ pattern: TEST_HOOKS_FILE_NAME, included: true, watched: false, served: false, nocache: true }], - }); + + // Assert + expect(config.files).deep.include({ pattern: TEST_HOOKS_FILE_NAME, included: true, watched: false, served: false, nocache: true }); expect(config.plugins).include('karma-*'); expect(config.plugins).deep.include({ ['middleware:TestHooksMiddleware']: ['value', TestHooksMiddleware.instance.handler] }); + expect(TestHooksMiddleware.instance.configureTestFramework).calledWith(['my', 'framework']); }); it('should configure the stryker reporter', () => { diff --git a/packages/karma-runner/testResources/configs/example-karma.conf.js b/packages/karma-runner/testResources/configs/example-karma.conf.js deleted file mode 100644 index ee82de6f53..0000000000 --- a/packages/karma-runner/testResources/configs/example-karma.conf.js +++ /dev/null @@ -1,64 +0,0 @@ -// Karma configuration -// Generated on Thu Dec 15 2016 17:14:16 GMT+0100 (W. Europe Standard Time) - -module.exports = function(config) { - config.set({ - - // base path that will be used to resolve all patterns (eg. files, exclude) - basePath: '', - - - // frameworks to use - // available frameworks: https://npmjs.org/browse/keyword/karma-adapter - frameworks: ['jasmine', 'requirejs'], - - - // list of files / patterns to load in the browser - files: [ - ], - - - // list of files to exclude - exclude: [ - ], - - - // preprocess matching files before serving them to the browser - // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor - preprocessors: { - }, - - - // test results reporter to use - // possible values: 'dots', 'progress' - // available reporters: https://npmjs.org/browse/keyword/karma-reporter - reporters: ['progress'], - - - // enable / disable colors in the output (reporters and logs) - colors: true, - - - // level of logging - // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG - logLevel: config.LOG_INFO, - - - // enable / disable watching file and executing tests whenever any file changes - autoWatch: true, - - - // start these browsers - // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher - browsers: ['Chrome'], - - - // Continuous Integration mode - // if true, Karma captures browsers, runs the tests and exits - singleRun: false, - - // Concurrency level - // how many browser should be started simultaneous - concurrency: Infinity, - }); -} diff --git a/packages/karma-runner/testResources/configs/files-karma.conf.js b/packages/karma-runner/testResources/configs/files-karma.conf.js deleted file mode 100644 index 52b87791f0..0000000000 --- a/packages/karma-runner/testResources/configs/files-karma.conf.js +++ /dev/null @@ -1,12 +0,0 @@ -module.exports = function (config) { - config.set({ - files: [ - 'src/**/*.js', - { pattern: 'resources/**/*.js', included: false } - ], - exclude: [ - '**/index.js', - '+(Error|InfiniteAdd).js' - ] - }); -}; diff --git a/packages/karma-runner/testResources/configs/jasmine-client-options-echo-ui.spec.js b/packages/karma-runner/testResources/configs/jasmine-client-options-echo-ui.spec.js new file mode 100644 index 0000000000..5d636f27ba --- /dev/null +++ b/packages/karma-runner/testResources/configs/jasmine-client-options-echo-ui.spec.js @@ -0,0 +1,11 @@ +describe('jasmine client options', () => { + it('should not override client options', function() { + expect(jasmine.getEnv().configuration().oneFailurePerSpec).toBe(true); + }); + it('should override "random" options', function() { + expect(jasmine.getEnv().configuration().random).toBe(false); + }); + it('should override "failFast" options', function() { + expect(jasmine.getEnv().configuration().failFast).toBe(true); + }); +}) diff --git a/packages/karma-runner/testResources/configs/jasmine-client-options-karma.conf.js b/packages/karma-runner/testResources/configs/jasmine-client-options-karma.conf.js new file mode 100644 index 0000000000..18c35014b0 --- /dev/null +++ b/packages/karma-runner/testResources/configs/jasmine-client-options-karma.conf.js @@ -0,0 +1,18 @@ +module.exports = function (config) { + config.set({ + frameworks: ['jasmine'], + browsers: ['ChromeHeadless'], + files: [ + require.resolve('./jasmine-client-options-echo-ui.spec.js') + ], + client: { + jasmine: { + random: true, + oneFailurePerSpec: true, + failFast: false, + timeoutInterval: 1000 + } + }, + singleRun: true + }); +}; diff --git a/packages/karma-runner/testResources/configs/mocha-client-options-echo-ui.spec.js b/packages/karma-runner/testResources/configs/mocha-client-options-echo-ui.spec.js new file mode 100644 index 0000000000..cf0d90b32f --- /dev/null +++ b/packages/karma-runner/testResources/configs/mocha-client-options-echo-ui.spec.js @@ -0,0 +1,10 @@ +suite('mocha client options', () => { + test('should not override client options', async function() { + expect(mocha.options.global).include('jQuery'); + }); + test('should override bail', async () => { + throw new Error('Expected exception'); + }); + test('should not execute this test', async () => { + }); +}) diff --git a/packages/karma-runner/testResources/configs/mocha-client-options-karma.conf.js b/packages/karma-runner/testResources/configs/mocha-client-options-karma.conf.js new file mode 100644 index 0000000000..ff680de5b4 --- /dev/null +++ b/packages/karma-runner/testResources/configs/mocha-client-options-karma.conf.js @@ -0,0 +1,17 @@ +module.exports = function (config) { + config.set({ + frameworks: ['mocha', 'chai'], + browsers: ['ChromeHeadless'], + files: [ + require.resolve('./mocha-client-options-echo-ui.spec.js') + ], + client: { + mocha: { + global: ['jQuery'], + ui: 'tdd', + bail: false // should be overridden by Stryker + } + }, + singleRun: true + }); +}; diff --git a/packages/karma-runner/testResources/instrumented/karma-jasmine.conf.js b/packages/karma-runner/testResources/instrumented/karma-jasmine.conf.js new file mode 100644 index 0000000000..472826d72e --- /dev/null +++ b/packages/karma-runner/testResources/instrumented/karma-jasmine.conf.js @@ -0,0 +1,16 @@ + + +module.exports = function (config) { + config.set({ + files: [ + __dirname + '/src/*.js', + __dirname + '/test/jasmine/*.js' + ], + frameworks: [ + 'jasmine' + ], + browsers: [ + 'ChromeHeadless' + ] + }); +} diff --git a/packages/karma-runner/testResources/instrumented/karma-mocha.conf.js b/packages/karma-runner/testResources/instrumented/karma-mocha.conf.js new file mode 100644 index 0000000000..5f0546dfce --- /dev/null +++ b/packages/karma-runner/testResources/instrumented/karma-mocha.conf.js @@ -0,0 +1,17 @@ + + +module.exports = function (config) { + config.set({ + files: [ + __dirname + '/src/*.js', + __dirname + '/test/mocha/*.js' + ], + frameworks: [ + 'chai', + 'mocha' + ], + browsers: [ + 'ChromeHeadless' + ] + }); +} diff --git a/packages/karma-runner/testResources/instrumented/src/Add.js b/packages/karma-runner/testResources/instrumented/src/Add.js new file mode 100644 index 0000000000..d9d9f1b450 --- /dev/null +++ b/packages/karma-runner/testResources/instrumented/src/Add.js @@ -0,0 +1,102 @@ +// This file is generated with tasks/instrument-test-resources.js + function stryNS_9fa48() { + var g = new Function("return this")(); + var ns = g.__stryker__ || (g.__stryker__ = {}); + + if (ns.activeMutant === undefined && g.process && g.process.env && g.process.env.__STRYKER_ACTIVE_MUTANT__) { + ns.activeMutant = Number(g.process.env.__STRYKER_ACTIVE_MUTANT__); + } + + function retrieveNS() { + return ns; + } + + stryNS_9fa48 = retrieveNS; + return retrieveNS(); +} + +stryNS_9fa48(); + +function stryCov_9fa48() { + var ns = stryNS_9fa48(); + var cov = ns.mutantCoverage || (ns.mutantCoverage = { + static: {}, + perTest: {} + }); + + function cover() { + var c = cov.static; + + if (ns.currentTestId) { + c = cov.perTest[ns.currentTestId] = cov.perTest[ns.currentTestId] || {}; + } + + var a = arguments; + + for (var i = 0; i < a.length; i++) { + c[a[i]] = (c[a[i]] || 0) + 1; + } + } + + stryCov_9fa48 = cover; + cover.apply(null, arguments); +} + +function stryMutAct_9fa48(id) { + var ns = stryNS_9fa48(); + + function isActive(id) { + return ns.activeMutant === id; + } + + stryMutAct_9fa48 = isActive; + return isActive(id); +} + +var add = function (num1, num2) { + if (stryMutAct_9fa48(0)) { + {} + } else { + stryCov_9fa48(0); + return stryMutAct_9fa48(1) ? num1 - num2 : (stryCov_9fa48(1), num1 + num2); + } +}; + +var addOne = function (number) { + if (stryMutAct_9fa48(2)) { + {} + } else { + stryCov_9fa48(2); + stryMutAct_9fa48(3) ? number-- : (stryCov_9fa48(3), number++); + return number; + } +}; + +var negate = function (number) { + if (stryMutAct_9fa48(4)) { + {} + } else { + stryCov_9fa48(4); + return stryMutAct_9fa48(5) ? +number : (stryCov_9fa48(5), -number); + } +}; + +var isNegativeNumber = function (number) { + if (stryMutAct_9fa48(6)) { + {} + } else { + stryCov_9fa48(6); + var isNegative = stryMutAct_9fa48(7) ? true : (stryCov_9fa48(7), false); + + if (stryMutAct_9fa48(11) ? number >= 0 : stryMutAct_9fa48(10) ? number <= 0 : stryMutAct_9fa48(9) ? false : stryMutAct_9fa48(8) ? true : (stryCov_9fa48(8, 9, 10, 11), number < 0)) { + if (stryMutAct_9fa48(12)) { + {} + } else { + stryCov_9fa48(12); + isNegative = stryMutAct_9fa48(13) ? false : (stryCov_9fa48(13), true); + } + } + + return isNegative; + } +}; \ No newline at end of file diff --git a/packages/karma-runner/testResources/instrumented/src/Circle.js b/packages/karma-runner/testResources/instrumented/src/Circle.js new file mode 100644 index 0000000000..5f5f5b0490 --- /dev/null +++ b/packages/karma-runner/testResources/instrumented/src/Circle.js @@ -0,0 +1,73 @@ +// This file is generated with tasks/instrument-test-resources.js + function stryNS_9fa48() { + var g = new Function("return this")(); + var ns = g.__stryker__ || (g.__stryker__ = {}); + + if (ns.activeMutant === undefined && g.process && g.process.env && g.process.env.__STRYKER_ACTIVE_MUTANT__) { + ns.activeMutant = Number(g.process.env.__STRYKER_ACTIVE_MUTANT__); + } + + function retrieveNS() { + return ns; + } + + stryNS_9fa48 = retrieveNS; + return retrieveNS(); +} + +stryNS_9fa48(); + +function stryCov_9fa48() { + var ns = stryNS_9fa48(); + var cov = ns.mutantCoverage || (ns.mutantCoverage = { + static: {}, + perTest: {} + }); + + function cover() { + var c = cov.static; + + if (ns.currentTestId) { + c = cov.perTest[ns.currentTestId] = cov.perTest[ns.currentTestId] || {}; + } + + var a = arguments; + + for (var i = 0; i < a.length; i++) { + c[a[i]] = (c[a[i]] || 0) + 1; + } + } + + stryCov_9fa48 = cover; + cover.apply(null, arguments); +} + +function stryMutAct_9fa48(id) { + var ns = stryNS_9fa48(); + + function isActive(id) { + return ns.activeMutant === id; + } + + stryMutAct_9fa48 = isActive; + return isActive(id); +} + +var getCircumference = function (radius) { + if (stryMutAct_9fa48(14)) { + {} + } else { + stryCov_9fa48(14); + //Function to test multiple math mutations in a single function. + return stryMutAct_9fa48(15) ? 2 * Math.PI / radius : (stryCov_9fa48(15), (stryMutAct_9fa48(16) ? 2 / Math.PI : (stryCov_9fa48(16), 2 * Math.PI)) * radius); + } +}; + +var untestedFunction = function () { + if (stryMutAct_9fa48(17)) { + {} + } else { + stryCov_9fa48(17); + var i = stryMutAct_9fa48(18) ? 5 / 2 / 3 : (stryCov_9fa48(18), (stryMutAct_9fa48(19) ? 5 * 2 : (stryCov_9fa48(19), 5 / 2)) * 3); + } +}; \ No newline at end of file diff --git a/packages/karma-runner/testResources/instrumented/test/jasmine/AddSpec.js b/packages/karma-runner/testResources/instrumented/test/jasmine/AddSpec.js new file mode 100644 index 0000000000..33fcf4c5b9 --- /dev/null +++ b/packages/karma-runner/testResources/instrumented/test/jasmine/AddSpec.js @@ -0,0 +1,48 @@ +describe('Add', function () { + it('should be able to add two numbers', function (done) { + var num1 = 2; + var num2 = 5; + var expected = num1 + num2; + + var actual = add(num1, num2); + + expect(actual).toBe(expected); + window.setTimeout(function () { + done(); + }, 20); + }); + + it('should be able 1 to a number', function () { + var number = 2; + var expected = 3; + + var actual = addOne(number); + + expect(actual).toBe(expected); + }); + + it('should be able negate a number', function () { + var number = 2; + var expected = -2; + + var actual = negate(number); + + expect(actual).toBe(expected); + }); + + it('should be able to recognize a negative number', function () { + var number = -2; + + var isNegative = isNegativeNumber(number); + + expect(isNegative).toBe(true); + }); + + it('should be able to recognize that 0 is not a negative number', function () { + var number = 0; + + var isNegative = isNegativeNumber(number); + + expect(isNegative).toBe(false); + }); +}); diff --git a/packages/karma-runner/testResources/instrumented/test/jasmine/CircleSpec.js b/packages/karma-runner/testResources/instrumented/test/jasmine/CircleSpec.js new file mode 100644 index 0000000000..6bcc7e3e7b --- /dev/null +++ b/packages/karma-runner/testResources/instrumented/test/jasmine/CircleSpec.js @@ -0,0 +1,10 @@ +describe('Circle', function() { + it('should have a circumference of 2PI when the radius is 1', function() { + var radius = 1; + var expectedCircumference = 2 * Math.PI; + + var circumference = getCircumference(radius); + + expect(circumference).toBe(expectedCircumference); + }); +}); diff --git a/packages/karma-runner/testResources/instrumented/test/mocha/AddSpec.js b/packages/karma-runner/testResources/instrumented/test/mocha/AddSpec.js new file mode 100644 index 0000000000..ea5140a4e4 --- /dev/null +++ b/packages/karma-runner/testResources/instrumented/test/mocha/AddSpec.js @@ -0,0 +1,48 @@ +describe('Add', function () { + it('should be able to add two numbers', function (done) { + var num1 = 2; + var num2 = 5; + var expected = num1 + num2; + + var actual = add(num1, num2); + + expect(actual).eq(expected); + window.setTimeout(function () { + done(); + }, 20); + }); + + it('should be able 1 to a number', function () { + var number = 2; + var expected = 3; + + var actual = addOne(number); + + expect(actual).eq(expected); + }); + + it('should be able negate a number', function () { + var number = 2; + var expected = -2; + + var actual = negate(number); + + expect(actual).eq(expected); + }); + + it('should be able to recognize a negative number', function () { + var number = -2; + + var isNegative = isNegativeNumber(number); + + expect(isNegative).eq(true); + }); + + it('should be able to recognize that 0 is not a negative number', function () { + var number = 0; + + var isNegative = isNegativeNumber(number); + + expect(isNegative).eq(false); + }); +}); diff --git a/packages/karma-runner/testResources/instrumented/test/mocha/CircleSpec.js b/packages/karma-runner/testResources/instrumented/test/mocha/CircleSpec.js new file mode 100644 index 0000000000..789d302815 --- /dev/null +++ b/packages/karma-runner/testResources/instrumented/test/mocha/CircleSpec.js @@ -0,0 +1,10 @@ +describe('Circle', function() { + it('should have a circumference of 2PI when the radius is 1', function() { + var radius = 1; + var expectedCircumference = 2 * Math.PI; + + var circumference = getCircumference(radius); + + expect(circumference).eq(expectedCircumference); + }); +}); diff --git a/packages/karma-runner/testResources/sampleProject/karma-jasmine.conf.js b/packages/karma-runner/testResources/sampleProject/karma-jasmine.conf.js new file mode 100644 index 0000000000..c484073cad --- /dev/null +++ b/packages/karma-runner/testResources/sampleProject/karma-jasmine.conf.js @@ -0,0 +1,23 @@ + + +module.exports = function (config) { + config.set({ + files: [ + __dirname + '/src/*.js', + __dirname + '/test-jasmine/*.js' + ], + exclude: [ + __dirname + '/src/Error.js', + __dirname + '/src/InfiniteAdd.js', + __dirname + '/test-jasmine/AddFailedSpec.js' + ], + singleRun: false, + watch: true, + frameworks: [ + 'jasmine' + ], + browsers: [ + 'ChromeHeadless' + ] + }); +} diff --git a/packages/karma-runner/testResources/sampleProject/karma-mocha.conf.js b/packages/karma-runner/testResources/sampleProject/karma-mocha.conf.js new file mode 100644 index 0000000000..d9ad2d92ba --- /dev/null +++ b/packages/karma-runner/testResources/sampleProject/karma-mocha.conf.js @@ -0,0 +1,23 @@ + + +module.exports = function (config) { + config.set({ + files: [ + __dirname + '/src/*.js', + __dirname + '/test-mocha/*.js' + ], + exclude: [ + __dirname + '/src/Error.js', + __dirname + '/src/InfiniteAdd.js' + ], + singleRun: false, + watch: true, + frameworks: [ + 'mocha', + 'chai' + ], + browsers: [ + 'ChromeHeadless' + ] + }); +} diff --git a/packages/karma-runner/testResources/sampleProject/karma.conf.js b/packages/karma-runner/testResources/sampleProject/karma.conf.js deleted file mode 100644 index 0bbac48919..0000000000 --- a/packages/karma-runner/testResources/sampleProject/karma.conf.js +++ /dev/null @@ -1,22 +0,0 @@ - - -module.exports = function (config) { - config.set({ - files: [ - __dirname + '/src/*.js', - __dirname + '/test-jasmine/*.js' - ], - exclude: [ - __dirname + '/src/Error.js', - __dirname + '/src/InfiniteAdd.js' - ], - singleRun: false, - watch: true, - frameworks: [ - 'jasmine' - ], - browsers: [ - 'ChromeHeadless' - ] - }); -} diff --git a/packages/karma-runner/testResources/sampleProject/src-instrumented/Add.js b/packages/karma-runner/testResources/sampleProject/src-instrumented/Add.js deleted file mode 100644 index c43612fd26..0000000000 --- a/packages/karma-runner/testResources/sampleProject/src-instrumented/Add.js +++ /dev/null @@ -1,9 +0,0 @@ - -var __cov_SOMzr_s4Ei_s$AxxqyedTQ = (Function('return this'))(); -if (!__cov_SOMzr_s4Ei_s$AxxqyedTQ.__coverage__) { __cov_SOMzr_s4Ei_s$AxxqyedTQ.__coverage__ = {}; } -__cov_SOMzr_s4Ei_s$AxxqyedTQ = __cov_SOMzr_s4Ei_s$AxxqyedTQ.__coverage__; -if (!(__cov_SOMzr_s4Ei_s$AxxqyedTQ['src/Add.js'])) { - __cov_SOMzr_s4Ei_s$AxxqyedTQ['src/Add.js'] = {"path":"src/Add.js","s":{"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0},"b":{"1":[0,0]},"f":{"1":0,"2":0,"3":0,"4":0},"fnMap":{"1":{"name":"(anonymous_1)","line":1,"loc":{"start":{"line":1,"column":10},"end":{"line":1,"column":31}}},"2":{"name":"(anonymous_2)","line":5,"loc":{"start":{"line":5,"column":13},"end":{"line":5,"column":30}}},"3":{"name":"(anonymous_3)","line":10,"loc":{"start":{"line":10,"column":13},"end":{"line":10,"column":30}}},"4":{"name":"(anonymous_4)","line":14,"loc":{"start":{"line":14,"column":23},"end":{"line":14,"column":40}}}},"statementMap":{"1":{"start":{"line":1,"column":0},"end":{"line":3,"column":2}},"2":{"start":{"line":2,"column":2},"end":{"line":2,"column":21}},"3":{"start":{"line":5,"column":0},"end":{"line":8,"column":2}},"4":{"start":{"line":6,"column":2},"end":{"line":6,"column":11}},"5":{"start":{"line":7,"column":2},"end":{"line":7,"column":16}},"6":{"start":{"line":10,"column":0},"end":{"line":12,"column":2}},"7":{"start":{"line":11,"column":2},"end":{"line":11,"column":17}},"8":{"start":{"line":14,"column":0},"end":{"line":20,"column":2}},"9":{"start":{"line":15,"column":2},"end":{"line":15,"column":25}},"10":{"start":{"line":16,"column":2},"end":{"line":18,"column":3}},"11":{"start":{"line":17,"column":4},"end":{"line":17,"column":22}},"12":{"start":{"line":19,"column":2},"end":{"line":19,"column":20}}},"branchMap":{"1":{"line":16,"type":"if","locations":[{"start":{"line":16,"column":2},"end":{"line":16,"column":2}},{"start":{"line":16,"column":2},"end":{"line":16,"column":2}}]}}}; -} -__cov_SOMzr_s4Ei_s$AxxqyedTQ = __cov_SOMzr_s4Ei_s$AxxqyedTQ['src/Add.js']; -__cov_SOMzr_s4Ei_s$AxxqyedTQ.s['1']++;var add=function(num1,num2){__cov_SOMzr_s4Ei_s$AxxqyedTQ.f['1']++;__cov_SOMzr_s4Ei_s$AxxqyedTQ.s['2']++;return num1+num2;};__cov_SOMzr_s4Ei_s$AxxqyedTQ.s['3']++;var addOne=function(number){__cov_SOMzr_s4Ei_s$AxxqyedTQ.f['2']++;__cov_SOMzr_s4Ei_s$AxxqyedTQ.s['4']++;number++;__cov_SOMzr_s4Ei_s$AxxqyedTQ.s['5']++;return number;};__cov_SOMzr_s4Ei_s$AxxqyedTQ.s['6']++;var negate=function(number){__cov_SOMzr_s4Ei_s$AxxqyedTQ.f['3']++;__cov_SOMzr_s4Ei_s$AxxqyedTQ.s['7']++;return-number;};__cov_SOMzr_s4Ei_s$AxxqyedTQ.s['8']++;var isNegativeNumber=function(number){__cov_SOMzr_s4Ei_s$AxxqyedTQ.f['4']++;__cov_SOMzr_s4Ei_s$AxxqyedTQ.s['9']++;var isNegative=false;__cov_SOMzr_s4Ei_s$AxxqyedTQ.s['10']++;if(number<0){__cov_SOMzr_s4Ei_s$AxxqyedTQ.b['1'][0]++;__cov_SOMzr_s4Ei_s$AxxqyedTQ.s['11']++;isNegative=true;}else{__cov_SOMzr_s4Ei_s$AxxqyedTQ.b['1'][1]++;}__cov_SOMzr_s4Ei_s$AxxqyedTQ.s['12']++;return isNegative;}; diff --git a/packages/karma-runner/testResources/sampleProject/src-instrumented/Circle.js b/packages/karma-runner/testResources/sampleProject/src-instrumented/Circle.js deleted file mode 100644 index 16cc0e7694..0000000000 --- a/packages/karma-runner/testResources/sampleProject/src-instrumented/Circle.js +++ /dev/null @@ -1,9 +0,0 @@ - -var __cov_TQWF1rJhMWGk$5mUo9CPjw = (Function('return this'))(); -if (!__cov_TQWF1rJhMWGk$5mUo9CPjw.__coverage__) { __cov_TQWF1rJhMWGk$5mUo9CPjw.__coverage__ = {}; } -__cov_TQWF1rJhMWGk$5mUo9CPjw = __cov_TQWF1rJhMWGk$5mUo9CPjw.__coverage__; -if (!(__cov_TQWF1rJhMWGk$5mUo9CPjw['src/Circle.js'])) { - __cov_TQWF1rJhMWGk$5mUo9CPjw['src/Circle.js'] = {"path":"src/Circle.js","s":{"1":0,"2":0,"3":0,"4":0},"b":{},"f":{"1":0,"2":0},"fnMap":{"1":{"name":"(anonymous_1)","line":1,"loc":{"start":{"line":1,"column":23},"end":{"line":1,"column":40}}},"2":{"name":"(anonymous_2)","line":6,"loc":{"start":{"line":6,"column":23},"end":{"line":6,"column":34}}}},"statementMap":{"1":{"start":{"line":1,"column":0},"end":{"line":4,"column":2}},"2":{"start":{"line":3,"column":2},"end":{"line":3,"column":30}},"3":{"start":{"line":6,"column":0},"end":{"line":8,"column":2}},"4":{"start":{"line":7,"column":2},"end":{"line":7,"column":20}}},"branchMap":{}}; -} -__cov_TQWF1rJhMWGk$5mUo9CPjw = __cov_TQWF1rJhMWGk$5mUo9CPjw['src/Circle.js']; -__cov_TQWF1rJhMWGk$5mUo9CPjw.s['1']++;var getCircumference=function(radius){__cov_TQWF1rJhMWGk$5mUo9CPjw.f['1']++;__cov_TQWF1rJhMWGk$5mUo9CPjw.s['2']++;return 2*Math.PI*radius;};__cov_TQWF1rJhMWGk$5mUo9CPjw.s['3']++;var untestedFunction=function(){__cov_TQWF1rJhMWGk$5mUo9CPjw.f['2']++;__cov_TQWF1rJhMWGk$5mUo9CPjw.s['4']++;var i=5/2*3;}; diff --git a/packages/karma-runner/tsconfig.src.json b/packages/karma-runner/tsconfig.src.json index 1b0ffa229c..d43ba622eb 100644 --- a/packages/karma-runner/tsconfig.src.json +++ b/packages/karma-runner/tsconfig.src.json @@ -18,9 +18,6 @@ { "path": "../api/tsconfig.src.json" }, - { - "path": "../jasmine-framework/tsconfig.src.json" - }, { "path": "../util/tsconfig.src.json" } diff --git a/packages/karma-runner/tsconfig.stryker.json b/packages/karma-runner/tsconfig.stryker.json deleted file mode 100644 index ae424d3c8f..0000000000 --- a/packages/karma-runner/tsconfig.stryker.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "./tsconfig.test.json", - "include": [ - "src", - "src-generated", - "schema/*.json", - "test", - "typings" - ], -} diff --git a/packages/karma-runner/tsconfig.test.json b/packages/karma-runner/tsconfig.test.json index ae773b007d..9382313549 100644 --- a/packages/karma-runner/tsconfig.test.json +++ b/packages/karma-runner/tsconfig.test.json @@ -18,9 +18,6 @@ }, { "path": "../test-helpers/tsconfig.src.json" - }, - { - "path": "../mocha-framework/tsconfig.src.json" } ] } diff --git a/packages/mocha-framework/CHANGELOG.md b/packages/mocha-framework/CHANGELOG.md index e40031e458..9636b571f2 100644 --- a/packages/mocha-framework/CHANGELOG.md +++ b/packages/mocha-framework/CHANGELOG.md @@ -3,6 +3,97 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [4.0.0-beta.10](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.9...v4.0.0-beta.10) (2020-10-05) + +**Note:** Version bump only for package @stryker-mutator/mocha-framework + + + + + +# [4.0.0-beta.9](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.8...v4.0.0-beta.9) (2020-09-30) + +**Note:** Version bump only for package @stryker-mutator/mocha-framework + + + + + +# [4.0.0-beta.8](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.7...v4.0.0-beta.8) (2020-09-22) + +**Note:** Version bump only for package @stryker-mutator/mocha-framework + + + + + +# [4.0.0-beta.7](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.6...v4.0.0-beta.7) (2020-09-17) + +**Note:** Version bump only for package @stryker-mutator/mocha-framework + + + + + +# [4.0.0-beta.6](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.5...v4.0.0-beta.6) (2020-09-10) + +**Note:** Version bump only for package @stryker-mutator/mocha-framework + + + + + +# [4.0.0-beta.5](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.4...v4.0.0-beta.5) (2020-09-09) + +**Note:** Version bump only for package @stryker-mutator/mocha-framework + + + + + +# [4.0.0-beta.4](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.3...v4.0.0-beta.4) (2020-08-29) + +**Note:** Version bump only for package @stryker-mutator/mocha-framework + + + + + +# [4.0.0-beta.3](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.2...v4.0.0-beta.3) (2020-08-19) + +**Note:** Version bump only for package @stryker-mutator/mocha-framework + + + + + +# [4.0.0-beta.2](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.1...v4.0.0-beta.2) (2020-08-07) + +**Note:** Version bump only for package @stryker-mutator/mocha-framework + + + + + +# [4.0.0-beta.1](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.0...v4.0.0-beta.1) (2020-07-17) + +**Note:** Version bump only for package @stryker-mutator/mocha-framework + + + + + +# [4.0.0-beta.0](https://github.com/stryker-mutator/stryker/compare/v3.3.1...v4.0.0-beta.0) (2020-07-10) + + +### Features + +* **test-framework:** remove `TestFramework` API ([fe5e200](https://github.com/stryker-mutator/stryker/commit/fe5e200e1f7ad7a24ebceacb2a62c2be58ce6a4f)) + + + + + ## [3.3.1](https://github.com/stryker-mutator/stryker/compare/v3.3.0...v3.3.1) (2020-07-04) **Note:** Version bump only for package @stryker-mutator/mocha-framework diff --git a/packages/mocha-framework/package.json b/packages/mocha-framework/package.json index 0d33b89ac9..561759ac0f 100644 --- a/packages/mocha-framework/package.json +++ b/packages/mocha-framework/package.json @@ -1,13 +1,9 @@ { "name": "@stryker-mutator/mocha-framework", - "version": "3.3.1", + "version": "4.0.0-beta.10", "description": "A plugin to use the mocha test framework in Stryker, the JavaScript mutation testing framework", "main": "src/index.js", - "scripts": { - "test": "nyc --exclude-after-remap=false --check-coverage --include src/**/*.js --reporter=html --report-dir=reports/coverage --lines 100 --functions 100 --branches 100 npm run mocha", - "mocha": "mocha \"test/helpers/**/*.js\" \"test/unit/**/*.js\" && mocha --timeout 10000 \"test/helpers/**/*.js\" \"test/integration/**/*.js\"", - "stryker": "node ../core/bin/stryker run" - }, + "scripts": {}, "repository": { "type": "git", "url": "https://github.com/stryker-mutator/stryker" @@ -40,11 +36,11 @@ "tslib": "~2.0.0" }, "peerDependencies": { - "@stryker-mutator/core": "^3.0.0", + "@stryker-mutator/core": "4.0.0-beta.4", "mocha": ">= 2.3.3 < 8" }, "dependencies": { - "@stryker-mutator/api": "^3.3.1", - "@stryker-mutator/util": "^3.3.1" + "@stryker-mutator/api": "4.0.0-beta.10", + "@stryker-mutator/util": "4.0.0-beta.10" } } diff --git a/packages/mocha-framework/src/MochaTestFramework.ts b/packages/mocha-framework/src/MochaTestFramework.ts deleted file mode 100644 index 43e31c8eab..0000000000 --- a/packages/mocha-framework/src/MochaTestFramework.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { TestFramework, TestSelection } from '@stryker-mutator/api/test_framework'; - -const FILTER_HEADER_FRAGMENT = ` - var Mocha = window.Mocha || require('mocha'); - var describe = Mocha.describe;`; -const FILTER_RESET = `${FILTER_HEADER_FRAGMENT} - if (window.____mochaAddTest) { - Mocha.Suite.prototype.addTest = window.____mochaAddTest; - } -`; - -export default class MochaTestFramework implements TestFramework { - public beforeEach(codeFragment: string): string { - return `beforeEach(function() { - ${codeFragment} - });`; - } - - public afterEach(codeFragment: string): string { - return `afterEach(function() { - ${codeFragment} - });`; - } - - public filter(testSelections: TestSelection[]) { - if (testSelections.length) { - const selectedTestNames = testSelections.map((selection) => selection.name); - return `${FILTER_HEADER_FRAGMENT} - var selectedTestNames = ${JSON.stringify(selectedTestNames)}; - if (window.____mochaAddTest) { - Mocha.Suite.prototype.addTest = window.____mochaAddTest; - } else { - window.____mochaAddTest = Mocha.Suite.prototype.addTest - } - var realAddTest = Mocha.Suite.prototype.addTest; - - Mocha.Suite.prototype.addTest = function (test) { - // Only actually add the tests with the expected names - var name = this.fullTitle() + ' ' + test.title; - if(!selectedTestNames.length || selectedTestNames.indexOf(name) !== -1) { - realAddTest.apply(this, arguments); - } - };`; - } else { - return FILTER_RESET; - } - } -} diff --git a/packages/mocha-framework/src/index.ts b/packages/mocha-framework/src/index.ts index cb7e44417f..aa36b43d7e 100644 --- a/packages/mocha-framework/src/index.ts +++ b/packages/mocha-framework/src/index.ts @@ -1,5 +1 @@ -import { declareClassPlugin, PluginKind } from '@stryker-mutator/api/plugin'; - -import MochaTestFramework from './MochaTestFramework'; - -export const strykerPlugins = [declareClassPlugin(PluginKind.TestFramework, 'mocha', MochaTestFramework)]; +console.warn('Framework plugins are no longer needed in Stryker 4.0. Please remove "@stryker-mutator/mocha-framework" from your devDependencies.'); diff --git a/packages/mocha-framework/test/helpers/initChai.ts b/packages/mocha-framework/test/helpers/initChai.ts deleted file mode 100644 index 514154da42..0000000000 --- a/packages/mocha-framework/test/helpers/initChai.ts +++ /dev/null @@ -1,6 +0,0 @@ -import * as chai from 'chai'; -import * as chaiAsPromised from 'chai-as-promised'; -import * as sinonChai from 'sinon-chai'; - -chai.use(sinonChai); -chai.use(chaiAsPromised); diff --git a/packages/mocha-framework/test/helpers/initSourceMaps.ts b/packages/mocha-framework/test/helpers/initSourceMaps.ts deleted file mode 100644 index fcfbfda16c..0000000000 --- a/packages/mocha-framework/test/helpers/initSourceMaps.ts +++ /dev/null @@ -1 +0,0 @@ -import 'source-map-support/register'; diff --git a/packages/mocha-framework/test/integration/nestedSuite.it.spec.ts b/packages/mocha-framework/test/integration/nestedSuite.it.spec.ts deleted file mode 100644 index e3cf89dc8e..0000000000 --- a/packages/mocha-framework/test/integration/nestedSuite.it.spec.ts +++ /dev/null @@ -1,90 +0,0 @@ -import * as fs from 'fs'; -import * as path from 'path'; - -import { TestSelection } from '@stryker-mutator/api/test_framework'; -import { expect } from 'chai'; -import * as execa from 'execa'; -import * as rimraf from 'rimraf'; - -import MochaTestFramework from '../../src/MochaTestFramework'; - -interface MochaTestRunResult { - tests: MochaTest[]; - pending: MochaTest[]; - failure: MochaTest[]; - passes: MochaTest[]; -} - -interface MochaTest { - title: string; - fullTitle: string; -} - -// See https://github.com/stryker-mutator/stryker/issues/249 -describe('Selecting tests with nested suites', () => { - let sut: MochaTestFramework; - const nestedSuiteFile = path.resolve(__dirname, '..', '..', 'testResources', 'nested-suite.js'); - const selectTestFile = path.join(__dirname, '..', '..', 'testResources', '__filterSpecs.js'); - const testSelections: ReadonlyArray> = [ - { id: 0, name: 'outer test 1' }, - { id: 1, name: 'outer test 2' }, - { id: 2, name: 'outer inner test 3' }, - ]; - - beforeEach(() => { - sut = new MochaTestFramework(); - }); - - afterEach(() => { - rimraf.sync(selectTestFile); - }); - - it('should run all tests in expected order when running all tests', () => { - const result = execMocha(nestedSuiteFile); - expect(result.tests.map((test) => test.fullTitle)).deep.eq(['outer test 1', 'outer test 2', 'outer inner test 3']); - }); - - it('should only run test 1 if filtered on index 0', () => { - filter([0]); - const result = execMocha(selectTestFile, nestedSuiteFile); - expect(result.tests).lengthOf(1); - expect(result.passes).lengthOf(1); - expect(result.passes[0].fullTitle).eq('outer test 1'); - }); - - it('should only run test 2 if filtered on index 1', () => { - filter([1]); - const result = execMocha(selectTestFile, nestedSuiteFile); - expect(result.tests).lengthOf(1); - expect(result.passes).lengthOf(1); - expect(result.passes[0].fullTitle).eq('outer test 2'); - }); - - it('should only run test 3 if filtered on index 2', () => { - filter([2]); - const result = execMocha(selectTestFile, nestedSuiteFile); - expect(result.tests).lengthOf(1); - expect(result.passes).lengthOf(1); - expect(result.passes[0].fullTitle).eq('outer inner test 3'); - }); - - it('should run tests 1 and 3 if filtered on indices 0 and 2', () => { - filter([0, 2]); - const result = execMocha(selectTestFile, nestedSuiteFile); - expect(result.tests).lengthOf(2); - expect(result.passes).lengthOf(2); - expect(result.passes[0].fullTitle).eq('outer test 1'); - expect(result.passes[1].fullTitle).eq('outer inner test 3'); - }); - - function filter(testIds: number[]) { - const selections = testIds.map((id) => testSelections[id]); - const filterFn = `(function (window) {${sut.filter(selections)}})(global);`; - fs.writeFileSync(selectTestFile, filterFn, 'utf8'); - } - - function execMocha(...files: string[]) { - const execResult = execa.sync('mocha', ['--reporter', 'json', ...files]); - return JSON.parse(execResult.stdout) as MochaTestRunResult; - } -}); diff --git a/packages/mocha-framework/test/unit/MochaTestFramework.spec.ts b/packages/mocha-framework/test/unit/MochaTestFramework.spec.ts deleted file mode 100644 index b09468d740..0000000000 --- a/packages/mocha-framework/test/unit/MochaTestFramework.spec.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { expect } from 'chai'; -import { normalizeWhitespaces } from '@stryker-mutator/util'; - -import MochaTestFramework from '../../src/MochaTestFramework'; - -describe('MochaTestFramework', () => { - let sut: MochaTestFramework; - beforeEach(() => (sut = new MochaTestFramework())); - - describe('beforeEach()', () => { - it('should result in a beforeEach mocha hook', () => expect(sut.beforeEach('fragment')).to.contain('fragment').and.to.contain('beforeEach')); - }); - - describe('afterEach()', () => { - it('should result in an afterEach mocha hook', () => expect(sut.afterEach('fragment')).to.contain('fragment').and.to.contain('afterEach')); - }); - - describe('filter()', () => { - it("should result in a filtering of mocha it's", () => { - expect( - sut.filter([ - { id: 5, name: 'test five' }, - { id: 8, name: 'test eight' }, - ]) - ) - .to.contain('var realAddTest = Mocha.Suite.prototype.addTest;') - .to.contain("var Mocha = window.Mocha || require('mocha');") - .and.to.contain('selectedTestNames = ["test five","test eight"];') - .and.to.contain('if(!selectedTestNames.length || selectedTestNames.indexOf(name) !== -1)') - .and.to.contain('realAddTest.apply(this, arguments);'); - }); - it('should result in a filter reset when selecting no tests', () => { - const actualFilter = normalizeWhitespaces(sut.filter([])); - const expectedFilter = normalizeWhitespaces(` - var Mocha = window.Mocha || require('mocha'); - var describe = Mocha.describe; - if (window.____mochaAddTest) { - Mocha.Suite.prototype.addTest = window.____mochaAddTest; - } - `); - expect(actualFilter).eq(expectedFilter); - }); - }); -}); diff --git a/packages/mocha-framework/testResources/nested-suite.js b/packages/mocha-framework/testResources/nested-suite.js deleted file mode 100644 index 791e07920c..0000000000 --- a/packages/mocha-framework/testResources/nested-suite.js +++ /dev/null @@ -1,16 +0,0 @@ -describe('outer', () => { - - it('test 1', () => { - - }); - - describe('inner', () => { - it('test 3', () => { - - }); - }); - - it('test 2', () => { - - }); -}); \ No newline at end of file diff --git a/packages/mocha-framework/tsconfig.stryker.json b/packages/mocha-framework/tsconfig.stryker.json deleted file mode 100644 index 0f7ed99680..0000000000 --- a/packages/mocha-framework/tsconfig.stryker.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": "./tsconfig.test.json", - "include": [ - "src", - "test" - ], -} diff --git a/packages/mocha-runner/.mocharc.jsonc b/packages/mocha-runner/.mocharc.jsonc new file mode 100644 index 0000000000..dc3280aa96 --- /dev/null +++ b/packages/mocha-runner/.mocharc.jsonc @@ -0,0 +1,3 @@ +{ + "require": "test/setup.js" +} diff --git a/packages/mocha-runner/.nycrc.json b/packages/mocha-runner/.nycrc.json new file mode 100644 index 0000000000..57ff700bda --- /dev/null +++ b/packages/mocha-runner/.nycrc.json @@ -0,0 +1,11 @@ +{ + "exclude-after-remap": false, + "check-coverage": true, + "reporter": ["text", "html"], + "report-dir": "reports/coverage", + "lines": 80, + "functions": 80, + "statements": 80, + "branches": 75, + "include": "src/**/*.js" +} diff --git a/packages/mocha-runner/CHANGELOG.md b/packages/mocha-runner/CHANGELOG.md index 4225c1684d..c0cd1a27c7 100644 --- a/packages/mocha-runner/CHANGELOG.md +++ b/packages/mocha-runner/CHANGELOG.md @@ -3,6 +3,121 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [4.0.0-beta.10](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.9...v4.0.0-beta.10) (2020-10-05) + +**Note:** Version bump only for package @stryker-mutator/mocha-runner + + + + + +# [4.0.0-beta.9](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.8...v4.0.0-beta.9) (2020-09-30) + +**Note:** Version bump only for package @stryker-mutator/mocha-runner + + + + + +# [4.0.0-beta.8](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.7...v4.0.0-beta.8) (2020-09-22) + +**Note:** Version bump only for package @stryker-mutator/mocha-runner + + + + + +# [4.0.0-beta.7](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.6...v4.0.0-beta.7) (2020-09-17) + +**Note:** Version bump only for package @stryker-mutator/mocha-runner + + + + + +# [4.0.0-beta.6](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.5...v4.0.0-beta.6) (2020-09-10) + +**Note:** Version bump only for package @stryker-mutator/mocha-runner + + + + + +# [4.0.0-beta.5](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.4...v4.0.0-beta.5) (2020-09-09) + + +### Bug Fixes + +* **mocha-runner:** don't allow custom timeout ([#2463](https://github.com/stryker-mutator/stryker/issues/2463)) ([e90b563](https://github.com/stryker-mutator/stryker/commit/e90b5635907dfcd36de98d73fa6c2da31f69fbed)) +* **mocha-runner:** fix memory leaks ([23eede2](https://github.com/stryker-mutator/stryker/commit/23eede22036c9efa502af8016e530af780a7cebb)) + + +### Features + +* **typescript:** Disable type checking ([#2446](https://github.com/stryker-mutator/stryker/issues/2446)) ([3ff996b](https://github.com/stryker-mutator/stryker/commit/3ff996b7516b7782434d86aa9aecbee334978a7f)), closes [#2438](https://github.com/stryker-mutator/stryker/issues/2438) + + + + + +# [4.0.0-beta.4](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.3...v4.0.0-beta.4) (2020-08-29) + + +### Features + +* **api:** rename test_runner2 -> test_runner ([#2442](https://github.com/stryker-mutator/stryker/issues/2442)) ([4d3ae97](https://github.com/stryker-mutator/stryker/commit/4d3ae9764dbd689c895b76e44f2eea76c82fabc8)) +* **test-runner:** add `nrOfTests` metric ([0eea448](https://github.com/stryker-mutator/stryker/commit/0eea44892e2383e8b0a34c6267e2f455d604f55a)) + + +### BREAKING CHANGES + +* **api:** Plugin creators should now use `'test_runner'` instead of `'test_runner2'`. + + + + + +# [4.0.0-beta.3](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.2...v4.0.0-beta.3) (2020-08-19) + + +### Features + +* **mocha:** deprecate mocha < v6 ([#2379](https://github.com/stryker-mutator/stryker/issues/2379)) ([fee0754](https://github.com/stryker-mutator/stryker/commit/fee0754c395ade4ee92d434963034e59ea5d180d)) +* **test runner api:** remove `sandboxFileNames` injectable values ([#2369](https://github.com/stryker-mutator/stryker/issues/2369)) ([92f3bf5](https://github.com/stryker-mutator/stryker/commit/92f3bf528d0b01be1f6c219b37a5f90da0431686)), closes [#2351](https://github.com/stryker-mutator/stryker/issues/2351) + + +### BREAKING CHANGES + +* **mocha:** Mocha@<6 is deprecated and support for it will be removed in Stryker v5 + + + + + +# [4.0.0-beta.2](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.1...v4.0.0-beta.2) (2020-08-07) + +**Note:** Version bump only for package @stryker-mutator/mocha-runner + + + + + +# [4.0.0-beta.1](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.0...v4.0.0-beta.1) (2020-07-17) + +**Note:** Version bump only for package @stryker-mutator/mocha-runner + + + + + +# [4.0.0-beta.0](https://github.com/stryker-mutator/stryker/compare/v3.3.1...v4.0.0-beta.0) (2020-07-10) + +**Note:** Version bump only for package @stryker-mutator/mocha-runner + + + + + ## [3.3.1](https://github.com/stryker-mutator/stryker/compare/v3.3.0...v3.3.1) (2020-07-04) **Note:** Version bump only for package @stryker-mutator/mocha-runner diff --git a/packages/mocha-runner/package.json b/packages/mocha-runner/package.json index a9b8c70bed..0a5071e031 100644 --- a/packages/mocha-runner/package.json +++ b/packages/mocha-runner/package.json @@ -1,13 +1,13 @@ { "name": "@stryker-mutator/mocha-runner", - "version": "3.3.1", + "version": "4.0.0-beta.10", "description": "A plugin to use the mocha test runner in Stryker, the JavaScript mutation testing framework", "main": "src/index.js", "scripts": { - "test": "nyc --exclude-after-remap=false --check-coverage --reporter=html --report-dir=reports/coverage --lines 80 --functions 80 --branches 75 npm run mocha", - "mocha": "npm run test:unit && npm run test:integration", - "test:unit": "mocha \"test/helpers/**/*.js\" \"test/unit/**/*.js\"", - "test:integration": "mocha --no-timeout \"test/helpers/**/*.js\" \"test/integration/**/*.js\"", + "test": "nyc npm run test:all", + "test:all": "npm run test:unit && npm run test:integration", + "test:unit": "mocha 'test/unit/**/*.js'", + "test:integration": "mocha --no-timeout 'test/integration/**/*.js'", "stryker": "node ../core/bin/stryker run" }, "repository": { @@ -36,20 +36,20 @@ }, "homepage": "https://github.com/stryker-mutator/stryker/tree/master/packages/mocha-runner#readme", "dependencies": { - "@stryker-mutator/api": "^3.3.1", - "@stryker-mutator/util": "^3.3.1", - "multimatch": "~4.0.0", + "@stryker-mutator/api": "4.0.0-beta.10", + "@stryker-mutator/util": "4.0.0-beta.10", + "glob": "~7.1.6", "tslib": "~2.0.0" }, "devDependencies": { - "@stryker-mutator/core": "^3.3.1", - "@stryker-mutator/mocha-framework": "^3.3.1", - "@stryker-mutator/test-helpers": "^3.3.1", - "@types/multimatch": "~4.0.0", + "@stryker-mutator/core": "4.0.0-beta.10", + "@stryker-mutator/mocha-framework": "4.0.0-beta.10", + "@stryker-mutator/test-helpers": "4.0.0-beta.10", + "@types/glob": "~7.1.3", "@types/node": "^14.0.1" }, "peerDependencies": { - "@stryker-mutator/core": "^3.0.0", + "@stryker-mutator/core": "~4.0.0", "mocha": ">= 2.3.3 < 9" } } diff --git a/packages/mocha-runner/schema/mocha-runner-options.json b/packages/mocha-runner/schema/mocha-runner-options.json index 4d68ae17d7..d0d749b5d6 100644 --- a/packages/mocha-runner/schema/mocha-runner-options.json +++ b/packages/mocha-runner/schema/mocha-runner-options.json @@ -56,17 +56,14 @@ "type": "boolean", "description": "Explicit turn off [mocha config file](https://mochajs.org/#-config-path)" }, - "timeout": { - "description": "Set mocha's [`timeout` option](https://mochajs.org/#-t---timeout-ms)", - "type": "number" - }, "async-only": { "description": "Set mocha's [`async-only` option](https://mochajs.org/#-async-only-a)", "type": "boolean" }, "ui": { "description": "Set the name of your [mocha ui](https://mochajs.org/#-u---ui-name)", - "type": "string" + "type": "string", + "enum": ["bdd", "tdd", "qunit", "exports"] }, "files": { "description": "DEPRECATED, use `spec` instead.", diff --git a/packages/mocha-runner/src/LibWrapper.ts b/packages/mocha-runner/src/LibWrapper.ts index 6ea0ef1b87..aa9596575d 100644 --- a/packages/mocha-runner/src/LibWrapper.ts +++ b/packages/mocha-runner/src/LibWrapper.ts @@ -1,10 +1,14 @@ +import path = require('path'); + import * as Mocha from 'mocha'; -import * as multimatch from 'multimatch'; +import glob = require('glob'); import { MochaOptions } from '../src-generated/mocha-runner-options'; +const mochaRoot = path.dirname(require.resolve('mocha/package.json')); + let loadOptions: undefined | ((argv?: string[] | string) => { [key: string]: any } | undefined); -let handleFiles: undefined | ((options: MochaOptions) => string[]); +let collectFiles: undefined | ((options: MochaOptions) => string[]); let handleRequires: undefined | ((requires?: string[]) => Promise); let loadRootHooks: undefined | ((rootHooks: any) => Promise); @@ -14,21 +18,21 @@ try { * @since 6.0.0' * @see https://mochajs.org/api/module-lib_cli_options.html#.loadOptions */ - loadOptions = require('mocha/lib/cli/options').loadOptions; + loadOptions = require(`${mochaRoot}/lib/cli/options`).loadOptions; } catch { // Mocha < 6 doesn't support `loadOptions` } try { // https://github.com/mochajs/mocha/blob/master/lib/cli/run-helpers.js#L132 - const runHelpers = require('mocha/lib/cli/run-helpers'); - handleFiles = runHelpers.handleFiles; + const runHelpers = require(`${mochaRoot}/lib/cli/run-helpers`); + collectFiles = runHelpers.handleFiles; handleRequires = runHelpers.handleRequires; // handleRequires is available since mocha v7.2 loadRootHooks = runHelpers.loadRootHooks; // loadRootHooks is available since mocha v7.2 - if (!handleFiles) { + if (!collectFiles) { // Might be moved: https://github.com/mochajs/mocha/commit/15b96afccaf508312445770e3af1c145d90b28c6#diff-39b692a81eb0c9f3614247af744ab4a8 - handleFiles = require('mocha/lib/cli/collect-files'); + collectFiles = require(`${mochaRoot}/lib/cli/collect-files`); } } catch { // Mocha < 6 doesn't support `handleFiles` @@ -40,9 +44,9 @@ try { export default class LibWrapper { public static Mocha = Mocha; public static require = require; - public static multimatch = multimatch; + public static glob = glob.sync; public static loadOptions = loadOptions; - public static handleFiles = handleFiles; + public static collectFiles = collectFiles; public static handleRequires = handleRequires; public static loadRootHooks = loadRootHooks; } diff --git a/packages/mocha-runner/src/MochaAdapter.ts b/packages/mocha-runner/src/MochaAdapter.ts new file mode 100644 index 0000000000..856d1a7f61 --- /dev/null +++ b/packages/mocha-runner/src/MochaAdapter.ts @@ -0,0 +1,110 @@ +import path = require('path'); +import fs = require('fs'); + +import { tokens, commonTokens } from '@stryker-mutator/api/plugin'; +import { Logger } from '@stryker-mutator/api/logging'; +import { PropertyPathBuilder } from '@stryker-mutator/util'; + +import { MochaOptions, MochaRunnerOptions } from '../src-generated/mocha-runner-options'; + +import LibWrapper from './LibWrapper'; +import { MochaTestRunner } from './MochaTestRunner'; + +const DEFAULT_TEST_PATTERN = 'test/**/*.js'; + +/** + * A class that contains polyfills for different versions of mocha. + * Tries to mimic the functionality of mocha's latest api. + * + * Currently supports mocha < 6 + */ +export class MochaAdapter { + public static readonly inject = tokens(commonTokens.logger); + + constructor(private readonly log: Logger) {} + + public create(options: Mocha.MochaOptions) { + return new LibWrapper.Mocha(options); + } + + public collectFiles(options: MochaOptions): string[] { + if (LibWrapper.collectFiles) { + this.log.debug("Mocha >= 6 detected. Using mocha's `collectFiles` to load files"); + return this.mocha6DiscoverFiles(options); + } else { + this.log.debug('Mocha < 6 detected. Using custom logic to discover files'); + return this.legacyDiscoverFiles(options); + } + } + + public async handleRequires(requires: string[]): Promise { + if (LibWrapper.handleRequires) { + const rawRootHooks = await LibWrapper.handleRequires(requires); + if (rawRootHooks) { + return await LibWrapper.loadRootHooks!(rawRootHooks); + } + } else { + const modulesToRequire = requires.map((moduleName) => { + const maybeSetupFileName = path.resolve(moduleName); + if (fs.existsSync(maybeSetupFileName)) { + return maybeSetupFileName; + } else { + return moduleName; + } + }); + modulesToRequire.forEach(LibWrapper.require); + } + } + + private mocha6DiscoverFiles(options: MochaOptions): string[] { + const originalProcessExit = process.exit; + try { + // process.exit unfortunate side effect: https://github.com/mochajs/mocha/blob/07ea8763c663bdd3fe1f8446cdb62dae233f4916/lib/cli/run-helpers.js#L174 + (process as any).exit = () => {}; + const files = LibWrapper.collectFiles!(options); + return files; + } finally { + process.exit = originalProcessExit; + } + } + + private legacyDiscoverFiles(options: MochaOptions): string[] { + const globPatterns = this.mochaFileGlobPatterns(options); + const fileNames = new Set(); + globPatterns.forEach((patten) => LibWrapper.glob(patten).forEach((fileName) => fileNames.add(fileName))); + if (fileNames.size) { + this.log.debug(`Using files: ${JSON.stringify(fileNames, null, 2)}`); + } else { + this.log.debug(`Tried ${JSON.stringify(globPatterns, null, 2)} but did not result in any files.`); + throw new Error( + `[${MochaTestRunner.name}] No files discovered (tried pattern(s) ${JSON.stringify( + globPatterns, + null, + 2 + )}). Please specify the files (glob patterns) containing your tests in ${PropertyPathBuilder.create() + .prop('mochaOptions') + .prop('spec')} in your config file.` + ); + } + return [...fileNames]; + } + + private mochaFileGlobPatterns(mochaOptions: MochaOptions): string[] { + // Use both `spec` as `files` + const globPatterns: string[] = []; + if (mochaOptions.spec) { + globPatterns.push(...mochaOptions.spec); + } + + if (typeof mochaOptions.files === 'string') { + // `files` if for backward compat + globPatterns.push(mochaOptions.files); + } else if (mochaOptions.files) { + globPatterns.push(...mochaOptions.files); + } + if (!globPatterns.length) { + globPatterns.push(DEFAULT_TEST_PATTERN); + } + return globPatterns; + } +} diff --git a/packages/mocha-runner/src/MochaOptionsEditor.ts b/packages/mocha-runner/src/MochaOptionsEditor.ts deleted file mode 100644 index fb281f76fb..0000000000 --- a/packages/mocha-runner/src/MochaOptionsEditor.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { tokens } from '@stryker-mutator/api/plugin'; -import { StrykerOptions, OptionsEditor } from '@stryker-mutator/api/core'; - -import MochaOptionsLoader from './MochaOptionsLoader'; -import { MochaRunnerWithStrykerOptions } from './MochaRunnerWithStrykerOptions'; - -export default class MochaOptionsEditor implements OptionsEditor { - public static inject = tokens('loader'); - constructor(private readonly loader: MochaOptionsLoader) {} - - public edit(options: StrykerOptions): void { - const optionsWithMocha = options as MochaRunnerWithStrykerOptions; - optionsWithMocha.mochaOptions = this.loader.load(optionsWithMocha); - } -} diff --git a/packages/mocha-runner/src/MochaOptionsLoader.ts b/packages/mocha-runner/src/MochaOptionsLoader.ts index 90c8d331af..9360cde69b 100644 --- a/packages/mocha-runner/src/MochaOptionsLoader.ts +++ b/packages/mocha-runner/src/MochaOptionsLoader.ts @@ -3,7 +3,7 @@ import * as path from 'path'; import { Logger } from '@stryker-mutator/api/logging'; import { commonTokens, tokens } from '@stryker-mutator/api/plugin'; -import { propertyPath } from '@stryker-mutator/util'; +import { PropertyPathBuilder } from '@stryker-mutator/util'; import { MochaOptions, MochaRunnerOptions } from '../src-generated/mocha-runner-options'; @@ -22,7 +22,6 @@ export const DEFAULT_MOCHA_OPTIONS: Readonly = Object.freeze({ ignore: [], opts: './test/mocha.opts', spec: ['test'], - timeout: 2000, ui: 'bdd', 'no-package': false, 'no-opts': false, @@ -34,7 +33,7 @@ export default class MochaOptionsLoader { public static inject = tokens(commonTokens.logger); constructor(private readonly log: Logger) {} - public load(strykerOptions: MochaRunnerWithStrykerOptions): MochaOptions { + public load(strykerOptions: MochaRunnerWithStrykerOptions) { const mochaOptions = { ...strykerOptions.mochaOptions } as MochaOptions; return { ...DEFAULT_MOCHA_OPTIONS, ...this.loadMochaOptions(mochaOptions), ...mochaOptions }; } @@ -44,7 +43,7 @@ export default class MochaOptionsLoader { this.log.debug("Mocha >= 6 detected. Using mocha's `%s` to load mocha options", LibWrapper.loadOptions.name); return this.loadMocha6Options(overrides); } else { - this.log.warn('DEPRECATED: Mocha < 6 detected. Please upgrade to at least Mocha version 6.'); + this.log.warn('DEPRECATED: Mocha < 6 detected. Please upgrade to at least Mocha version 6. Stryker will drop support for Mocha < 6 in V5.'); this.log.debug('Mocha < 6 detected. Using custom logic to parse mocha options'); return this.loadLegacyMochaOptsFile(overrides); } @@ -52,10 +51,9 @@ export default class MochaOptionsLoader { private loadMocha6Options(overrides: MochaOptions) { const args = serializeMochaLoadOptionsArguments(overrides); - const loadOptions = LibWrapper.loadOptions || (() => ({})); - const rawConfig = loadOptions(args) || {}; + const rawConfig = LibWrapper.loadOptions!(args) || {}; if (this.log.isTraceEnabled()) { - this.log.trace(`Mocha: ${loadOptions.name}([${args.map((arg) => `'${arg}'`).join(',')}]) => ${JSON.stringify(rawConfig)}`); + this.log.trace(`Mocha: ${LibWrapper.loadOptions!.name}([${args.map((arg) => `'${arg}'`).join(',')}]) => ${JSON.stringify(rawConfig)}`); } const options = filterConfig(rawConfig); if (this.log.isDebugEnabled()) { @@ -77,7 +75,7 @@ export default class MochaOptionsLoader { } else { this.log.debug( 'No mocha opts file found, not loading additional mocha options (%s was not defined).', - propertyPath('mochaOptions', 'opts') + PropertyPathBuilder.create().prop('mochaOptions').prop('opts').build() ); return {}; } @@ -112,17 +110,13 @@ export default class MochaOptionsLoader { } mochaRunnerOptions.require.push(...args); break; - case '--timeout': - case '-t': - mochaRunnerOptions.timeout = this.parseNextInt(args, DEFAULT_MOCHA_OPTIONS.timeout!); - break; case '--async-only': case '-A': mochaRunnerOptions['async-only'] = true; break; case '--ui': case '-u': - mochaRunnerOptions.ui = this.parseNextString(args) ?? DEFAULT_MOCHA_OPTIONS.ui!; + mochaRunnerOptions.ui = (this.parseNextString(args) as 'bdd' | 'tdd' | 'qunit' | 'exports') ?? DEFAULT_MOCHA_OPTIONS.ui!; break; case '--grep': case '-g': @@ -141,14 +135,6 @@ export default class MochaOptionsLoader { return mochaRunnerOptions; } - private parseNextInt(args: string[], otherwise: number): number { - if (args.length > 1) { - return parseInt(args[1], 10); - } else { - return otherwise; - } - } - private parseNextString(args: string[]): string | undefined { if (args.length > 1) { return args[1]; diff --git a/packages/mocha-runner/src/MochaTestRunner.ts b/packages/mocha-runner/src/MochaTestRunner.ts index b61b2eecb3..401ecab967 100644 --- a/packages/mocha-runner/src/MochaTestRunner.ts +++ b/packages/mocha-runner/src/MochaTestRunner.ts @@ -1,134 +1,137 @@ -import * as path from 'path'; - -import { StrykerOptions } from '@stryker-mutator/api/core'; +import { InstrumenterContext, INSTRUMENTER_CONSTANTS, StrykerOptions } from '@stryker-mutator/api/core'; import { Logger } from '@stryker-mutator/api/logging'; import { commonTokens, tokens } from '@stryker-mutator/api/plugin'; -import { RunResult, RunStatus, TestRunner } from '@stryker-mutator/api/test_runner'; -import { propertyPath } from '@stryker-mutator/util'; +import { I, escapeRegExp, DirectoryRequireCache } from '@stryker-mutator/util'; + +import { + TestRunner, + DryRunResult, + DryRunOptions, + MutantRunOptions, + MutantRunResult, + DryRunStatus, + toMutantRunResult, + CompleteDryRunResult, +} from '@stryker-mutator/api/test_runner'; -import { MochaOptions, MochaRunnerOptions } from '../src-generated/mocha-runner-options'; +import { MochaOptions } from '../src-generated/mocha-runner-options'; -import LibWrapper from './LibWrapper'; import { StrykerMochaReporter } from './StrykerMochaReporter'; -import { evalGlobal } from './utils'; import { MochaRunnerWithStrykerOptions } from './MochaRunnerWithStrykerOptions'; - -const DEFAULT_TEST_PATTERN = 'test/**/*.js'; +import * as pluginTokens from './plugin-tokens'; +import MochaOptionsLoader from './MochaOptionsLoader'; +import { MochaAdapter } from './MochaAdapter'; export class MochaTestRunner implements TestRunner { - private testFileNames: string[]; - private readonly mochaOptions: MochaOptions; - private rootHooks: any; - - public static inject = tokens(commonTokens.logger, commonTokens.sandboxFileNames, commonTokens.options); - constructor(private readonly log: Logger, private readonly allFileNames: readonly string[], options: StrykerOptions) { - this.mochaOptions = (options as MochaRunnerWithStrykerOptions).mochaOptions; + public testFileNames: string[]; + public rootHooks: any; + public mochaOptions!: MochaOptions; + private readonly instrumenterContext: InstrumenterContext; + + public static inject = tokens( + commonTokens.logger, + commonTokens.options, + pluginTokens.loader, + pluginTokens.mochaAdapter, + pluginTokens.directoryRequireCache, + pluginTokens.globalNamespace + ); + constructor( + private readonly log: Logger, + private readonly options: StrykerOptions, + private readonly loader: I, + private readonly mochaAdapter: I, + private readonly requireCache: I, + globalNamespace: typeof INSTRUMENTER_CONSTANTS.NAMESPACE | '__stryker2__' + ) { StrykerMochaReporter.log = log; + this.instrumenterContext = global[globalNamespace] || (global[globalNamespace] = {}); } - public async init(): Promise { - if (LibWrapper.handleFiles) { - this.log.debug("Mocha >= 6 detected. Using mocha's `handleFiles` to load files"); - this.testFileNames = this.mocha6DiscoverFiles(LibWrapper.handleFiles); - } else { - this.log.debug('Mocha < 6 detected. Using custom logic to discover files'); - this.testFileNames = this.legacyDiscoverFiles(); + this.mochaOptions = this.loader.load(this.options as MochaRunnerWithStrykerOptions); + this.testFileNames = this.mochaAdapter.collectFiles(this.mochaOptions); + this.requireCache.init({ initFiles: this.testFileNames, rootModuleId: require.resolve('mocha/lib/mocha') }); + if (this.mochaOptions.require) { + this.rootHooks = await this.mochaAdapter.handleRequires(this.mochaOptions.require); } - await this.additionalRequires(); } - private mocha6DiscoverFiles(handleFiles: (options: MochaOptions) => string[]): string[] { - const originalProcessExit = process.exit; - try { - // process.exit unfortunate side effect: https://github.com/mochajs/mocha/blob/07ea8763c663bdd3fe1f8446cdb62dae233f4916/lib/cli/run-helpers.js#L174 - (process as any).exit = () => {}; - const files = handleFiles(this.mochaOptions); - return files; - } finally { - process.exit = originalProcessExit; + public async dryRun(options: DryRunOptions): Promise { + let interceptor: (mocha: Mocha) => void = () => {}; + if (options.coverageAnalysis === 'perTest') { + interceptor = (mocha) => { + const self = this; + mocha.suite.beforeEach('StrykerIntercept', function () { + self.instrumenterContext.currentTestId = this.currentTest?.fullTitle(); + }); + }; } - } - - private legacyDiscoverFiles(): string[] { - const globPatterns = this.mochaFileGlobPatterns(); - const globPatternsAbsolute = globPatterns.map((glob) => path.resolve(glob)); - const fileNames = LibWrapper.multimatch(this.allFileNames.slice(), globPatternsAbsolute); - if (fileNames.length) { - this.log.debug(`Using files: ${JSON.stringify(fileNames, null, 2)}`); - } else { - this.log.debug(`Tried ${JSON.stringify(globPatternsAbsolute, null, 2)} on files: ${JSON.stringify(this.allFileNames, null, 2)}.`); - throw new Error( - `[${MochaTestRunner.name}] No files discovered (tried pattern(s) ${JSON.stringify( - globPatterns, - null, - 2 - )}). Please specify the files (glob patterns) containing your tests in ${propertyPath( - 'mochaOptions', - 'spec' - )} in your config file.` - ); + const runResult = await this.run(interceptor); + if (runResult.status === DryRunStatus.Complete && options.coverageAnalysis !== 'off') { + runResult.mutantCoverage = this.instrumenterContext.mutantCoverage; } - return fileNames; + return runResult; } - private mochaFileGlobPatterns(): string[] { - // Use both `spec` as `files` - const globPatterns: string[] = []; - if (this.mochaOptions.spec) { - globPatterns.push(...this.mochaOptions.spec); - } - if (typeof this.mochaOptions.files === 'string') { - // `files` if for backward compat - globPatterns.push(this.mochaOptions.files); - } else if (this.mochaOptions.files) { - globPatterns.push(...this.mochaOptions.files); - } - if (!globPatterns.length) { - globPatterns.push(DEFAULT_TEST_PATTERN); + public async mutantRun({ activeMutant, testFilter }: MutantRunOptions): Promise { + this.instrumenterContext.activeMutant = activeMutant.id; + let intercept: (mocha: Mocha) => void = () => {}; + if (testFilter) { + const metaRegExp = testFilter.map((testId) => `(${escapeRegExp(testId)})`).join('|'); + const regex = new RegExp(metaRegExp); + intercept = (mocha) => { + mocha.grep(regex); + }; } - return globPatterns; + const dryRunResult = await this.run(intercept); + return toMutantRunResult(dryRunResult); } - public run({ testHooks }: { testHooks?: string }): Promise { - return new Promise((resolve, reject) => { - try { - this.purgeFiles(); - const mocha = new LibWrapper.Mocha({ reporter: StrykerMochaReporter as any, bail: true, rootHooks: this.rootHooks } as Mocha.MochaOptions); - this.configure(mocha); - this.addTestHooks(mocha, testHooks); - this.addFiles(mocha); - try { - mocha.run(() => { - const reporter = StrykerMochaReporter.currentInstance; - if (reporter) { - const result: RunResult = reporter.runResult; - resolve(result); - } else { - const errorMsg = 'The StrykerMochaReporter was not instantiated properly. Could not retrieve the RunResult.'; - this.log.error(errorMsg); - resolve({ - errorMessages: [errorMsg], - status: RunStatus.Error, - tests: [], - }); - } - }); - } catch (error) { - resolve({ - errorMessages: [error], - status: RunStatus.Error, - tests: [], - }); - } - } catch (error) { - this.log.error(error); - reject(error); + public async run(intercept: (mocha: Mocha) => void): Promise { + this.requireCache.clear(); + const mocha = this.mochaAdapter.create({ + reporter: StrykerMochaReporter as any, + bail: true, + timeout: false as any, // Mocha 5 doesn't support `0` + rootHooks: this.rootHooks, + } as Mocha.MochaOptions); + this.configure(mocha); + intercept(mocha); + this.addFiles(mocha); + try { + await this.runMocha(mocha); + if ((mocha as any).dispose) { + // Since mocha 7.2 + (mocha as any).dispose(); } - }); + this.requireCache.record(); + const reporter = StrykerMochaReporter.currentInstance; + if (reporter) { + const result: CompleteDryRunResult = { + status: DryRunStatus.Complete, + tests: reporter.tests, + }; + return result; + } else { + const errorMessage = `Mocha didn't instantiate the ${StrykerMochaReporter.name} correctly. Test result cannot be reported.`; + this.log.error(errorMessage); + return { + status: DryRunStatus.Error, + errorMessage, + }; + } + } catch (errorMessage) { + return { + errorMessage, + status: DryRunStatus.Error, + }; + } } - private purgeFiles() { - this.allFileNames.forEach((fileName) => delete require.cache[fileName]); + private runMocha(mocha: Mocha): Promise { + return new Promise((res) => { + mocha.run(() => res()); + }); } private addFiles(mocha: Mocha) { @@ -137,15 +140,6 @@ export class MochaTestRunner implements TestRunner { }); } - private addTestHooks(mocha: Mocha, testHooks: string | undefined): void { - if (testHooks) { - const suite = (mocha as any).suite; - suite.emit('pre-require', global, '', mocha); - suite.emit('require', evalGlobal(testHooks), '', mocha); - suite.emit('post-require', global, '', mocha); - } - } - private configure(mocha: Mocha) { const options = this.mochaOptions; @@ -155,25 +149,8 @@ export class MochaTestRunner implements TestRunner { } } - if (options) { - setIfDefined(options['async-only'], (asyncOnly) => asyncOnly && mocha.asyncOnly()); - setIfDefined(options.timeout, mocha.timeout); - setIfDefined(options.ui, mocha.ui); - setIfDefined(options.grep, mocha.grep); - } - } - - private async additionalRequires() { - if (this.mochaOptions.require) { - if (LibWrapper.handleRequires) { - const rawRootHooks = await LibWrapper.handleRequires(this.mochaOptions.require); - if (rawRootHooks) { - this.rootHooks = await LibWrapper.loadRootHooks!(rawRootHooks); - } - } else { - const modulesToRequire = this.mochaOptions.require.map((moduleName) => (moduleName.startsWith('.') ? path.resolve(moduleName) : moduleName)); - modulesToRequire.forEach(LibWrapper.require); - } - } + setIfDefined(options['async-only'], (asyncOnly) => asyncOnly && mocha.asyncOnly()); + setIfDefined(options.ui, mocha.ui); + setIfDefined(options.grep, mocha.grep); } } diff --git a/packages/mocha-runner/src/StrykerMochaReporter.ts b/packages/mocha-runner/src/StrykerMochaReporter.ts index bd1e5c5375..117c741b6f 100644 --- a/packages/mocha-runner/src/StrykerMochaReporter.ts +++ b/packages/mocha-runner/src/StrykerMochaReporter.ts @@ -1,5 +1,6 @@ import { Logger } from '@stryker-mutator/api/logging'; -import { RunResult, RunStatus, TestStatus } from '@stryker-mutator/api/test_runner'; +import { FailedTestResult, TestResult, SuccessTestResult, TestStatus } from '@stryker-mutator/api/test_runner'; +import { I } from '@stryker-mutator/util'; import Timer from './Timer'; @@ -9,12 +10,12 @@ export class StrykerMochaReporter { * Needs to be set from 'the outside' because mocha doesn't really have a nice way of providing * data to reporters... */ - public static log: Logger; - public runResult: RunResult; + public static log: Logger | undefined; private readonly timer = new Timer(); private passedCount = 0; + public tests: TestResult[]; - public static currentInstance: StrykerMochaReporter | undefined; + public static currentInstance: I | undefined; constructor(private readonly runner: NodeJS.EventEmitter) { this.registerEvents(); @@ -25,43 +26,40 @@ export class StrykerMochaReporter { this.runner.on('start', () => { this.passedCount = 0; this.timer.reset(); - this.runResult = { - errorMessages: [], - status: RunStatus.Error, - tests: [], - }; - StrykerMochaReporter.log.debug('Starting Mocha test run'); + this.tests = []; + StrykerMochaReporter.log?.debug('Starting Mocha test run'); }); - this.runner.on('pass', (test: any) => { - this.runResult.tests.push({ - name: test.fullTitle(), + this.runner.on('pass', (test: Mocha.Test) => { + const title: string = test.fullTitle(); + const result: SuccessTestResult = { + id: title, + name: title, status: TestStatus.Success, timeSpentMs: this.timer.elapsedMs(), - }); + }; + this.tests.push(result); this.passedCount++; this.timer.reset(); }); - this.runner.on('fail', (test: any, err: any) => { - this.runResult.tests.push({ - failureMessages: [err.message], - name: test.fullTitle(), + this.runner.on('fail', (test: Mocha.Test, err: Error) => { + const title = test.fullTitle(); + const result: FailedTestResult = { + id: title, + failureMessage: err.message, + name: title, status: TestStatus.Failed, timeSpentMs: this.timer.elapsedMs(), - }); - if (!this.runResult.errorMessages) { - this.runResult.errorMessages = []; - } - this.runResult.errorMessages.push(err.message); - if (StrykerMochaReporter.log.isTraceEnabled()) { - StrykerMochaReporter.log.trace(`Test failed: ${test.fullTitle()}. Error: ${err.message}`); + }; + this.tests.push(result); + if (StrykerMochaReporter.log?.isTraceEnabled()) { + StrykerMochaReporter.log?.trace(`Test failed: ${test.fullTitle()}. Error: ${err.message}`); } }); this.runner.on('end', () => { - this.runResult.status = RunStatus.Complete; - StrykerMochaReporter.log.debug('Mocha test run completed: %s/%s passed', this.passedCount, this.runResult.tests.length); + StrykerMochaReporter.log?.debug('Mocha test run completed: %s/%s passed', this.passedCount, this.tests.length); }); } } diff --git a/packages/mocha-runner/src/index.ts b/packages/mocha-runner/src/index.ts index b247b46113..1a2013b4a4 100644 --- a/packages/mocha-runner/src/index.ts +++ b/packages/mocha-runner/src/index.ts @@ -1,19 +1,10 @@ -import { BaseContext, commonTokens, declareClassPlugin, declareFactoryPlugin, Injector, PluginKind, tokens } from '@stryker-mutator/api/plugin'; +import { declareFactoryPlugin, PluginKind } from '@stryker-mutator/api/plugin'; import * as strykerValidationSchema from '../schema/mocha-runner-options.json'; -import MochaOptionsEditor from './MochaOptionsEditor'; -import MochaOptionsLoader from './MochaOptionsLoader'; +import { createMochaTestRunner, createMochaTestRunnerFactory } from './mochaRunnerFactories'; import { MochaTestRunner } from './MochaTestRunner'; -export const strykerPlugins = [ - declareFactoryPlugin(PluginKind.OptionsEditor, 'mocha-runner', mochaOptionsEditorFactory), - declareClassPlugin(PluginKind.TestRunner, 'mocha', MochaTestRunner), -]; +export const strykerPlugins = [declareFactoryPlugin(PluginKind.TestRunner, 'mocha', createMochaTestRunner)]; -mochaOptionsEditorFactory.inject = tokens(commonTokens.injector); -function mochaOptionsEditorFactory(injector: Injector): MochaOptionsEditor { - return injector.provideClass('loader', MochaOptionsLoader).injectClass(MochaOptionsEditor); -} - -export { strykerValidationSchema }; +export { strykerValidationSchema, MochaTestRunner, createMochaTestRunnerFactory }; diff --git a/packages/mocha-runner/src/mochaRunnerFactories.ts b/packages/mocha-runner/src/mochaRunnerFactories.ts new file mode 100644 index 0000000000..c92ba94567 --- /dev/null +++ b/packages/mocha-runner/src/mochaRunnerFactories.ts @@ -0,0 +1,23 @@ +import { INSTRUMENTER_CONSTANTS } from '@stryker-mutator/api/core'; +import { commonTokens, Injector, PluginContext, tokens } from '@stryker-mutator/api/plugin'; +import { DirectoryRequireCache } from '@stryker-mutator/util'; + +import { MochaAdapter } from './MochaAdapter'; +import MochaOptionsLoader from './MochaOptionsLoader'; +import { MochaTestRunner } from './MochaTestRunner'; +import * as pluginTokens from './plugin-tokens'; + +export const createMochaTestRunner = createMochaTestRunnerFactory(); + +export function createMochaTestRunnerFactory(namespace: typeof INSTRUMENTER_CONSTANTS.NAMESPACE | '__stryker2__' = INSTRUMENTER_CONSTANTS.NAMESPACE) { + createMochaTestRunner.inject = tokens(commonTokens.injector); + function createMochaTestRunner(injector: Injector): MochaTestRunner { + return injector + .provideClass(pluginTokens.loader, MochaOptionsLoader) + .provideClass(pluginTokens.mochaAdapter, MochaAdapter) + .provideClass(pluginTokens.directoryRequireCache, DirectoryRequireCache) + .provideValue(pluginTokens.globalNamespace, namespace) + .injectClass(MochaTestRunner); + } + return createMochaTestRunner; +} diff --git a/packages/mocha-runner/src/plugin-tokens.ts b/packages/mocha-runner/src/plugin-tokens.ts new file mode 100644 index 0000000000..5cf014275b --- /dev/null +++ b/packages/mocha-runner/src/plugin-tokens.ts @@ -0,0 +1,4 @@ +export const loader = 'loader'; +export const mochaAdapter = 'mochaAdapter'; +export const directoryRequireCache = 'directoryRequireCache'; +export const globalNamespace = 'globalNamespace'; diff --git a/packages/mocha-runner/src/utils.ts b/packages/mocha-runner/src/utils.ts index 5e55ea0caf..a4946cf6d9 100644 --- a/packages/mocha-runner/src/utils.ts +++ b/packages/mocha-runner/src/utils.ts @@ -2,15 +2,6 @@ import { MochaOptions } from '../src-generated/mocha-runner-options'; import mochaSchema = require('../schema/mocha-runner-options.json'); -/** - * Executes a piece of javascript code in global scope while passing the `require` function - * @param body The JavaScript to execute - */ -export function evalGlobal(body: string) { - const fn = new Function('require', body); - fn(require); -} - export function serializeMochaLoadOptionsArguments(mochaOptions: MochaOptions): string[] { const args: string[] = []; if (mochaOptions['no-config']) { diff --git a/packages/mocha-runner/stryker.conf.js b/packages/mocha-runner/stryker.conf.js index 05c6be512c..f9625942a3 100644 --- a/packages/mocha-runner/stryker.conf.js +++ b/packages/mocha-runner/stryker.conf.js @@ -4,6 +4,9 @@ const path = require('path'); */ const settings = require('../../stryker.parent.conf'); const moduleName = __dirname.split(path.sep).pop(); +settings.plugins = settings.plugins.map(p => path.resolve(p)); settings.dashboard.module = moduleName; +settings.files = ['{src-generated,src,test,schema}/**/*.{ts,json}', '*.{ts,json}', '!src/**/*.d.ts'] +delete settings.checkers; module.exports = settings; diff --git a/packages/mocha-runner/test/helpers/factories.ts b/packages/mocha-runner/test/helpers/factories.ts index 7f3c8e3097..05b6ca555f 100644 --- a/packages/mocha-runner/test/helpers/factories.ts +++ b/packages/mocha-runner/test/helpers/factories.ts @@ -1,6 +1,6 @@ import { MochaOptions } from '../../src-generated/mocha-runner-options'; import { DEFAULT_MOCHA_OPTIONS } from '../../src/MochaOptionsLoader'; -export function createMochaOptions(overrides: Partial): MochaOptions { +export function createMochaOptions(overrides?: Partial): MochaOptions { return { ...DEFAULT_MOCHA_OPTIONS, ...overrides }; } diff --git a/packages/mocha-runner/test/helpers/initChai.ts b/packages/mocha-runner/test/helpers/initChai.ts deleted file mode 100644 index 514154da42..0000000000 --- a/packages/mocha-runner/test/helpers/initChai.ts +++ /dev/null @@ -1,6 +0,0 @@ -import * as chai from 'chai'; -import * as chaiAsPromised from 'chai-as-promised'; -import * as sinonChai from 'sinon-chai'; - -chai.use(sinonChai); -chai.use(chaiAsPromised); diff --git a/packages/mocha-runner/test/helpers/initSinon.ts b/packages/mocha-runner/test/helpers/initSinon.ts deleted file mode 100644 index 96cb3f7e59..0000000000 --- a/packages/mocha-runner/test/helpers/initSinon.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { testInjector } from '@stryker-mutator/test-helpers'; -import * as sinon from 'sinon'; - -afterEach(() => { - sinon.restore(); - testInjector.reset(); -}); diff --git a/packages/mocha-runner/test/helpers/initSourceMaps.ts b/packages/mocha-runner/test/helpers/initSourceMaps.ts deleted file mode 100644 index fcfbfda16c..0000000000 --- a/packages/mocha-runner/test/helpers/initSourceMaps.ts +++ /dev/null @@ -1 +0,0 @@ -import 'source-map-support/register'; diff --git a/packages/mocha-runner/test/integration/MemoryLeak.it.spec.ts b/packages/mocha-runner/test/integration/MemoryLeak.it.spec.ts new file mode 100644 index 0000000000..5e3d80a87e --- /dev/null +++ b/packages/mocha-runner/test/integration/MemoryLeak.it.spec.ts @@ -0,0 +1,18 @@ +import path = require('path'); + +import execa = require('execa'); + +import { expect } from 'chai'; + +import { MochaTestRunner } from '../../src'; + +describe(MochaTestRunner.name, () => { + it('should not leak memory when running multiple times (#2461)', async () => { + const childProcess = await execa.node(path.resolve(__dirname, 'MemoryLeak.worker.js'), [], { + stdio: 'pipe', + nodeOptions: ['--max-old-space-size=32', '--max-semi-space-size=1'], + }); + expect(childProcess.exitCode).eq(0); + expect(childProcess.stdout).contains('Iterator count 1'); + }); +}); diff --git a/packages/mocha-runner/test/integration/MemoryLeak.worker.ts b/packages/mocha-runner/test/integration/MemoryLeak.worker.ts new file mode 100644 index 0000000000..ef15e14a8b --- /dev/null +++ b/packages/mocha-runner/test/integration/MemoryLeak.worker.ts @@ -0,0 +1,46 @@ +import path = require('path'); + +import { testInjector } from '@stryker-mutator/test-helpers'; + +import { expect } from 'chai'; +import { DryRunStatus, TestStatus } from '@stryker-mutator/api/test_runner'; + +import { createMochaTestRunnerFactory } from '../../src'; + +/** + * This file will run the mocha runner a number of times in a test suite that is designed + * to result in an OutOfMemory error when the mocha test runner does not clean it's memory + * Start this process with `--max-old-space-size=32 --max-semi-space-size=1` to get a fast OutOfMemory error (if there is a memory leak) + * + * @see https://github.com/stryker-mutator/stryker/issues/2461 + * @see https://nodejs.org/api/modules.html#modules_accessing_the_main_module + * @see https://stackoverflow.com/questions/30252905/nodejs-decrease-v8-garbage-collector-memory-usage + */ + +if (require.main === module) { + main().catch((err) => { + console.error(err); + process.exitCode = 1; + }); +} + +async function main() { + process.chdir(path.resolve(__dirname, '..', '..', 'testResources', 'big-project')); + testInjector.options.mochaOptions = { 'no-config': true }; + const mochaRunner = testInjector.injector.injectFunction(createMochaTestRunnerFactory('__stryker2__')); + + await mochaRunner.init(); + await doDryRun(); + + async function doDryRun(n = 20) { + if (n > 0) { + console.log(`Iterator count ${n}`); + const result = await mochaRunner.dryRun({ coverageAnalysis: 'off', timeout: 3000 }); + if (result.status === DryRunStatus.Complete) { + expect(result.tests).lengthOf(1); + expect(result.tests[0].status).eq(TestStatus.Success); + } + await doDryRun(n - 1); + } + } +} diff --git a/packages/mocha-runner/test/integration/MochaFileResolving.it.spec.ts b/packages/mocha-runner/test/integration/MochaFileResolving.it.spec.ts new file mode 100644 index 0000000000..d5d04acaf6 --- /dev/null +++ b/packages/mocha-runner/test/integration/MochaFileResolving.it.spec.ts @@ -0,0 +1,48 @@ +import * as path from 'path'; + +import { expect } from 'chai'; +import { testInjector } from '@stryker-mutator/test-helpers'; + +import MochaOptionsLoader from '../../src/MochaOptionsLoader'; +import { MochaRunnerWithStrykerOptions } from '../../src/MochaRunnerWithStrykerOptions'; +import { createMochaTestRunnerFactory } from '../../src'; + +describe('Mocha 6 file resolving integration', () => { + const cwd = process.cwd(); + let options: MochaRunnerWithStrykerOptions; + + beforeEach(() => { + options = testInjector.options as MochaRunnerWithStrykerOptions; + options.mochaOptions = {}; + }); + + afterEach(() => { + process.chdir(cwd); + }); + + it('should resolve test files while respecting "files", "spec", "extension" and "exclude" properties', () => { + const configLoader = createConfigLoader(); + process.chdir(resolveTestDir()); + options.mochaOptions = configLoader.load(options); + const testRunner = createTestRunner(); + testRunner.init(); + expect((testRunner as any).testFileNames).deep.eq([ + resolveTestDir('helpers/1.ts'), + resolveTestDir('helpers/2.js'), + resolveTestDir('specs/3.js'), + resolveTestDir('specs/4.ts'), + ]); + }); + + function createConfigLoader() { + return testInjector.injector.injectClass(MochaOptionsLoader); + } + + function createTestRunner() { + return testInjector.injector.injectFunction(createMochaTestRunnerFactory('__stryker2__')); + } + + function resolveTestDir(fileName = '.') { + return path.resolve(__dirname, '..', '..', 'testResources', 'file-resolving', fileName); + } +}); diff --git a/packages/mocha-runner/test/integration/MochaFileResolving.spec.ts b/packages/mocha-runner/test/integration/MochaFileResolving.spec.ts deleted file mode 100644 index 7a2fed1bdb..0000000000 --- a/packages/mocha-runner/test/integration/MochaFileResolving.spec.ts +++ /dev/null @@ -1,49 +0,0 @@ -import * as path from 'path'; - -import { commonTokens } from '@stryker-mutator/api/plugin'; -import { expect } from 'chai'; -import { testInjector } from '@stryker-mutator/test-helpers'; - -import MochaOptionsLoader from '../../src/MochaOptionsLoader'; -import { MochaTestRunner } from '../../src/MochaTestRunner'; -import { MochaRunnerWithStrykerOptions } from '../../src/MochaRunnerWithStrykerOptions'; - -describe('Mocha 6 file resolving integration', () => { - const cwd = process.cwd(); - let options: MochaRunnerWithStrykerOptions; - - beforeEach(() => { - options = testInjector.options as MochaRunnerWithStrykerOptions; - options.mochaOptions = {}; - }); - - afterEach(() => { - process.chdir(cwd); - }); - - it('should resolve test files while respecting "files", "spec", "extension" and "exclude" properties', () => { - const configLoader = createConfigLoader(); - process.chdir(resolveTestDir()); - options.mochaOptions = configLoader.load(options); - const testRunner = createTestRunner(); - testRunner.init(); - expect((testRunner as any).testFileNames).deep.eq([ - resolveTestDir('helpers/1.ts'), - resolveTestDir('helpers/2.js'), - resolveTestDir('specs/3.js'), - resolveTestDir('specs/4.ts'), - ]); - }); - - function createConfigLoader() { - return testInjector.injector.injectClass(MochaOptionsLoader); - } - - function createTestRunner() { - return testInjector.injector.provideValue(commonTokens.sandboxFileNames, []).injectClass(MochaTestRunner); - } - - function resolveTestDir(fileName = '.') { - return path.resolve(__dirname, '..', '..', 'testResources', 'file-resolving', fileName); - } -}); diff --git a/packages/mocha-runner/test/integration/MochaFramework.it.spec.ts b/packages/mocha-runner/test/integration/MochaFramework.it.spec.ts index c729fed1ab..521dce8cf7 100644 --- a/packages/mocha-runner/test/integration/MochaFramework.it.spec.ts +++ b/packages/mocha-runner/test/integration/MochaFramework.it.spec.ts @@ -1,95 +1,95 @@ -import * as path from 'path'; +// import * as path from 'path'; -import { expect } from 'chai'; -import { TestSelection } from '@stryker-mutator/api/test_framework'; -import { TestStatus, RunStatus } from '@stryker-mutator/api/test_runner'; -import { LoggingServer, testInjector } from '@stryker-mutator/test-helpers'; -import MochaTestFramework from '@stryker-mutator/mocha-framework/src/MochaTestFramework'; -import ChildProcessProxy from '@stryker-mutator/core/src/child-proxy/ChildProcessProxy'; -import { LogLevel } from '@stryker-mutator/api/core'; -import { commonTokens } from '@stryker-mutator/api/plugin'; +// import { expect } from 'chai'; +// import { TestSelection } from '@stryker-mutator/api/test_framework'; +// import { TestStatus, RunStatus } from '@stryker-mutator/api/test_runner'; +// import { LoggingServer, testInjector } from '@stryker-mutator/test-helpers'; +// import MochaTestFramework from '@stryker-mutator/mocha-framework/src/MochaTestFramework'; +// import ChildProcessProxy from '@stryker-mutator/core/src/child-proxy/ChildProcessProxy'; +// import { LogLevel } from '@stryker-mutator/api/core'; +// import { commonTokens } from '@stryker-mutator/api/plugin'; -import { MochaTestRunner } from '../../src/MochaTestRunner'; +// import { MochaTestRunner } from '../../src/MochaTestRunner'; -const test0: Readonly = Object.freeze({ - id: 0, - name: 'MyMath should be able to add two numbers', -}); -const test3: Readonly = Object.freeze({ - id: 3, - name: 'MyMath should be able to recognize a negative number', -}); +// const test0: Readonly = Object.freeze({ +// id: 0, +// name: 'MyMath should be able to add two numbers', +// }); +// const test3: Readonly = Object.freeze({ +// id: 3, +// name: 'MyMath should be able to recognize a negative number', +// }); -export function wrapInClosure(codeFragment: string) { - return ` - (function (window) { - ${codeFragment} - })((Function('return this'))());`; -} +// export function wrapInClosure(codeFragment: string) { +// return ` +// (function (window) { +// ${codeFragment} +// })((Function('return this'))());`; +// } -describe('Integration with @stryker-mutator/mocha-framework', () => { - let testFramework: MochaTestFramework; - let loggingServer: LoggingServer; - let sut: ChildProcessProxy; +// describe('Integration with @stryker-mutator/mocha-framework', () => { +// let testFramework: MochaTestFramework; +// let loggingServer: LoggingServer; +// let sut: ChildProcessProxy; - beforeEach(async () => { - testFramework = new MochaTestFramework(); - loggingServer = new LoggingServer(); - const resolveSampleProject: typeof path.resolve = path.resolve.bind(path, __dirname, '../../testResources/sampleProject'); - const port = await loggingServer.listen(); - testInjector.options.mochaOptions = { - file: [], - ignore: [], - spec: [resolveSampleProject('MyMathSpec.js')], - }; - testInjector.options.plugins = []; +// beforeEach(async () => { +// testFramework = new MochaTestFramework(); +// loggingServer = new LoggingServer(); +// const resolveSampleProject: typeof path.resolve = path.resolve.bind(path, __dirname, '../../testResources/sampleProject'); +// const port = await loggingServer.listen(); +// testInjector.options.mochaOptions = { +// file: [], +// ignore: [], +// spec: [resolveSampleProject('MyMathSpec.js')], +// }; +// testInjector.options.plugins = []; - sut = ChildProcessProxy.create( - require.resolve('../../src/MochaTestRunner'), - { level: LogLevel.Trace, port }, - testInjector.options, - { - [commonTokens.sandboxFileNames]: [resolveSampleProject('MyMath.js'), resolveSampleProject('MyMathSpec.js')], - }, - __dirname, - MochaTestRunner - ); - await sut.proxy.init(); - }); +// sut = ChildProcessProxy.create( +// require.resolve('../../src/MochaTestRunner'), +// { level: LogLevel.Trace, port }, +// testInjector.options, +// { +// [commonTokens.sandboxFileNames]: [resolveSampleProject('MyMath.js'), resolveSampleProject('MyMathSpec.js')], +// }, +// __dirname, +// MochaTestRunner +// ); +// await sut.proxy.init(); +// }); - afterEach(async () => { - await sut.dispose(); - await loggingServer.dispose(); - }); +// afterEach(async () => { +// await sut.dispose(); +// await loggingServer.dispose(); +// }); - it('should be able to filter tests', async () => { - const testHooks = wrapInClosure(testFramework.filter([test0, test3])); - const actualResult = await sut.proxy.run({ testHooks }); - expect(actualResult.tests.map((test) => ({ name: test.name, status: test.status }))).deep.eq([ - { - name: 'MyMath should be able to add two numbers', - status: TestStatus.Success, - }, - { - name: 'MyMath should be able to recognize a negative number', - status: TestStatus.Success, - }, - ]); - }); +// it('should be able to filter tests', async () => { +// const testHooks = wrapInClosure(testFramework.filter([test0, test3])); +// const actualResult = await sut.proxy.run({ testHooks }); +// expect(actualResult.tests.map((test) => ({ name: test.name, status: test.status }))).deep.eq([ +// { +// name: 'MyMath should be able to add two numbers', +// status: TestStatus.Success, +// }, +// { +// name: 'MyMath should be able to recognize a negative number', +// status: TestStatus.Success, +// }, +// ]); +// }); - it('should be able to clear the filter after a filtered run', async () => { - await sut.proxy.run({ testHooks: wrapInClosure(testFramework.filter([test0, test3])) }); - const actualResult = await sut.proxy.run({ testHooks: wrapInClosure(testFramework.filter([])) }); - expect(actualResult.tests).lengthOf(5); - }); +// it('should be able to clear the filter after a filtered run', async () => { +// await sut.proxy.run({ testHooks: wrapInClosure(testFramework.filter([test0, test3])) }); +// const actualResult = await sut.proxy.run({ testHooks: wrapInClosure(testFramework.filter([])) }); +// expect(actualResult.tests).lengthOf(5); +// }); - it('should be able to run beforeEach and afterEach', async () => { - const testHooks = wrapInClosure( - testFramework.beforeEach('console.log("beforeEach from hook");') + testFramework.afterEach('console.log("afterEach from hook");') - ); - const actualProcessOutput = await sut.proxy.run({ testHooks }); - expect(actualProcessOutput.status).eq(RunStatus.Complete); - expect(sut.stdout).includes('beforeEach from hook'); - expect(sut.stdout).includes('afterEach from hook'); - }); -}); +// it('should be able to run beforeEach and afterEach', async () => { +// const testHooks = wrapInClosure( +// testFramework.beforeEach('console.log("beforeEach from hook");') + testFramework.afterEach('console.log("afterEach from hook");') +// ); +// const actualProcessOutput = await sut.proxy.run({ testHooks }); +// expect(actualProcessOutput.status).eq(RunStatus.Complete); +// expect(sut.stdout).includes('beforeEach from hook'); +// expect(sut.stdout).includes('afterEach from hook'); +// }); +// }); diff --git a/packages/mocha-runner/test/integration/MochaOptionsLoader.it.spec.ts b/packages/mocha-runner/test/integration/MochaOptionsLoader.it.spec.ts index 8f9a9d00ea..6b62072d7f 100644 --- a/packages/mocha-runner/test/integration/MochaOptionsLoader.it.spec.ts +++ b/packages/mocha-runner/test/integration/MochaOptionsLoader.it.spec.ts @@ -28,7 +28,6 @@ describe(`${MochaOptionsLoader.name} integration`, () => { opts: './test/mocha.opts', package: false, // mocha sets package: false after loading it... extension: ['js'], - timeout: 2000, ui: 'bdd', }); }); @@ -42,7 +41,6 @@ describe(`${MochaOptionsLoader.name} integration`, () => { package: false, // mocha sets package: false after loading it... config: configFile, extension: ['json', 'js'], - timeout: 2000, ui: 'bdd', }); }); @@ -56,7 +54,6 @@ describe(`${MochaOptionsLoader.name} integration`, () => { opts: './test/mocha.opts', package: false, // mocha sets package: false after loading it... extension: ['jsonc', 'js'], - timeout: 2000, ui: 'bdd', }); }); @@ -75,7 +72,6 @@ describe(`${MochaOptionsLoader.name} integration`, () => { ignore: ['/path/to/some/excluded/file'], require: ['@babel/register'], spec: ['test/**/*.spec.js'], - timeout: false, ui: 'bdd', }); }); @@ -86,7 +82,6 @@ describe(`${MochaOptionsLoader.name} integration`, () => { expect(actualConfig).deep.include({ ['async-only']: true, extension: ['json'], - timeout: 20, ui: 'tdd', }); }); @@ -97,7 +92,6 @@ describe(`${MochaOptionsLoader.name} integration`, () => { expect(actualConfig).deep.include({ ['async-only']: true, extension: ['js', 'json'], - timeout: 2000, ui: 'bdd', }); }); @@ -109,12 +103,11 @@ describe(`${MochaOptionsLoader.name} integration`, () => { 'no-package': true, 'no-opts': true, }); - const expectedOptions = { + const expectedOptions: MochaOptions = { extension: ['js', 'cjs', 'mjs'], ['no-config']: true, ['no-opts']: true, ['no-package']: true, - timeout: 2000, ui: 'bdd', }; expect(actualConfig).deep.include(expectedOptions); diff --git a/packages/mocha-runner/test/integration/ProjectWithRootHooks.it.spec.ts b/packages/mocha-runner/test/integration/ProjectWithRootHooks.it.spec.ts index e4e3a293fb..8ed80a96fc 100644 --- a/packages/mocha-runner/test/integration/ProjectWithRootHooks.it.spec.ts +++ b/packages/mocha-runner/test/integration/ProjectWithRootHooks.it.spec.ts @@ -1,13 +1,11 @@ import * as path from 'path'; -import { commonTokens } from '@stryker-mutator/api/plugin'; -import { testInjector } from '@stryker-mutator/test-helpers'; +import { testInjector, factory } from '@stryker-mutator/test-helpers'; import { expect } from 'chai'; -import { RunStatus } from '@stryker-mutator/api/test_runner'; -import { MochaTestRunner } from '../../src/MochaTestRunner'; -import MochaOptionsEditor from '../../src/MochaOptionsEditor'; -import MochaOptionsLoader from '../../src/MochaOptionsLoader'; +import { expectCompleted } from '@stryker-mutator/test-helpers/src/assertions'; + +import { createMochaTestRunnerFactory, MochaTestRunner } from '../../src'; describe('Running a project with root hooks', () => { const cwd = process.cwd(); @@ -16,8 +14,7 @@ describe('Running a project with root hooks', () => { beforeEach(async () => { process.chdir(path.resolve(__dirname, '..', '..', 'testResources', 'parallel-with-root-hooks-sample')); - testInjector.injector.provideClass('loader', MochaOptionsLoader).injectClass(MochaOptionsEditor).edit(testInjector.options); - sut = testInjector.injector.provideValue(commonTokens.sandboxFileNames, []).injectClass(MochaTestRunner); + sut = testInjector.injector.injectFunction(createMochaTestRunnerFactory('__stryker2__')); await sut.init(); }); @@ -26,9 +23,8 @@ describe('Running a project with root hooks', () => { }); it('should have run the root hooks', async () => { - const result = await sut.run({}); - expect(result.status).eq(RunStatus.Complete); + const result = await sut.dryRun(factory.dryRunOptions({})); + expectCompleted(result); expect(result.tests).has.lengthOf(2); - expect(result.errorMessages).lengthOf(0); }); }); diff --git a/packages/mocha-runner/test/integration/QUnitSample.it.spec.ts b/packages/mocha-runner/test/integration/QUnitSample.it.spec.ts index d24d5fc53b..46deca5e85 100644 --- a/packages/mocha-runner/test/integration/QUnitSample.it.spec.ts +++ b/packages/mocha-runner/test/integration/QUnitSample.it.spec.ts @@ -1,22 +1,14 @@ import * as path from 'path'; -import { commonTokens } from '@stryker-mutator/api/plugin'; -import { RunStatus } from '@stryker-mutator/api/test_runner'; -import { testInjector } from '@stryker-mutator/test-helpers'; +import { testInjector, factory, assertions } from '@stryker-mutator/test-helpers'; import { expect } from 'chai'; -import { MochaTestRunner } from '../../src/MochaTestRunner'; import { createMochaOptions } from '../helpers/factories'; +import { createMochaTestRunnerFactory } from '../../src'; describe('QUnit sample', () => { - let files: string[]; - - beforeEach(() => { - files = []; - }); - function createSut() { - return testInjector.injector.provideValue(commonTokens.sandboxFileNames, files).injectClass(MochaTestRunner); + return testInjector.injector.injectFunction(createMochaTestRunnerFactory('__stryker2__')); } it('should work when configured with "qunit" ui', async () => { @@ -26,11 +18,10 @@ describe('QUnit sample', () => { ui: 'qunit', }); testInjector.options.mochaOptions = mochaOptions; - files = mochaOptions.spec!; const sut = createSut(); await sut.init(); - const actualResult = await sut.run({}); - expect(actualResult.status).eq(RunStatus.Complete); + const actualResult = await sut.dryRun(factory.dryRunOptions()); + assertions.expectCompleted(actualResult); expect(actualResult.tests.map((t) => t.name)).deep.eq([ 'Math should be able to add two numbers', 'Math should be able 1 to a number', @@ -41,14 +32,13 @@ describe('QUnit sample', () => { }); it('should not run tests when not configured with "qunit" ui', async () => { - files = [resolve('./testResources/qunit-sample/MyMathSpec.js'), resolve('./testResources/qunit-sample/MyMath.js')]; testInjector.options.mochaOptions = createMochaOptions({ files: [resolve('./testResources/qunit-sample/MyMathSpec.js')], }); const sut = createSut(); await sut.init(); - const actualResult = await sut.run({}); - expect(actualResult.status).eq(RunStatus.Complete); + const actualResult = await sut.dryRun(factory.dryRunOptions()); + assertions.expectCompleted(actualResult); expect(actualResult.tests).lengthOf(0); }); }); diff --git a/packages/mocha-runner/test/integration/SampleProject.it.spec.ts b/packages/mocha-runner/test/integration/SampleProject.it.spec.ts index e45b6bb982..da1386278c 100644 --- a/packages/mocha-runner/test/integration/SampleProject.it.spec.ts +++ b/packages/mocha-runner/test/integration/SampleProject.it.spec.ts @@ -1,21 +1,16 @@ import * as path from 'path'; -import { commonTokens } from '@stryker-mutator/api/plugin'; -import { RunResult, RunStatus, TestResult, TestStatus } from '@stryker-mutator/api/test_runner'; -import { testInjector } from '@stryker-mutator/test-helpers'; -import * as chai from 'chai'; -import * as chaiAsPromised from 'chai-as-promised'; +import { testInjector, factory, assertions } from '@stryker-mutator/test-helpers'; +import { TestResult, CompleteDryRunResult, TestStatus } from '@stryker-mutator/api/test_runner'; +import { expect } from 'chai'; -import { MochaTestRunner } from '../../src/MochaTestRunner'; import { createMochaOptions } from '../helpers/factories'; +import { createMochaTestRunnerFactory, MochaTestRunner } from '../../src'; -chai.use(chaiAsPromised); -const expect = chai.expect; +const countTests = (runResult: CompleteDryRunResult, predicate: (result: TestResult) => boolean) => runResult.tests.filter(predicate).length; -const countTests = (runResult: RunResult, predicate: (result: TestResult) => boolean) => runResult.tests.filter(predicate).length; - -const countSucceeded = (runResult: RunResult) => countTests(runResult, (t) => t.status === TestStatus.Success); -const countFailed = (runResult: RunResult) => countTests(runResult, (t) => t.status === TestStatus.Failed); +const countSucceeded = (runResult: CompleteDryRunResult) => countTests(runResult, (t) => t.status === TestStatus.Success); +const countFailed = (runResult: CompleteDryRunResult) => countTests(runResult, (t) => t.status === TestStatus.Failed); function resolve(fileName: string) { return path.resolve(__dirname, '..', '..', fileName); @@ -26,36 +21,36 @@ describe('Running a sample project', () => { let spec: string[]; function createSut() { - return testInjector.injector.provideValue(commonTokens.sandboxFileNames, spec).injectClass(MochaTestRunner); + return testInjector.injector.injectFunction(createMochaTestRunnerFactory('__stryker2__')); } describe('when tests pass', () => { beforeEach(() => { - spec = [resolve('./testResources/sampleProject/MyMath.js'), resolve('./testResources/sampleProject/MyMathSpec.js')]; + spec = [resolve('./testResources/sample-project/MyMath.js'), resolve('./testResources/sample-project/MyMathSpec.js')]; testInjector.options.mochaOptions = createMochaOptions({ spec }); sut = createSut(); return sut.init(); }); it('should report completed tests', async () => { - const runResult = await sut.run({}); + const runResult = await sut.dryRun(factory.dryRunOptions()); + assertions.expectCompleted(runResult); expect(countSucceeded(runResult)).to.be.eq(5, 'Succeeded tests did not match'); expect(countFailed(runResult)).to.be.eq(0, 'Failed tests did not match'); runResult.tests.forEach((t) => expect(t.timeSpentMs).to.be.greaterThan(-1).and.to.be.lessThan(1000)); - expect(runResult.status).to.be.eq(RunStatus.Complete, 'Test result did not match'); - expect(runResult.coverage).to.not.be.ok; }); it('should be able to run 2 times in a row', async () => { - await sut.run({}); - const runResult = await sut.run({}); + await sut.dryRun(factory.dryRunOptions()); + const runResult = await sut.dryRun(factory.dryRunOptions()); + assertions.expectCompleted(runResult); expect(countSucceeded(runResult)).to.be.eq(5); }); }); describe('with an error in an un-included input file', () => { beforeEach(() => { - spec = [resolve('testResources/sampleProject/MyMath.js'), resolve('testResources/sampleProject/MyMathSpec.js')]; + spec = [resolve('testResources/sample-project/MyMath.js'), resolve('testResources/sample-project/MyMathSpec.js')]; testInjector.options.mochaOptions = createMochaOptions({ files: spec, }); @@ -64,40 +59,40 @@ describe('Running a sample project', () => { }); it('should report completed tests without errors', async () => { - const runResult = await sut.run({}); - expect(runResult.status).to.be.eq(RunStatus.Complete, 'Test result did not match'); + const runResult = await sut.dryRun(factory.dryRunOptions()); + assertions.expectCompleted(runResult); }); }); describe('with multiple failed tests', () => { before(() => { - spec = [resolve('testResources/sampleProject/MyMath.js'), resolve('testResources/sampleProject/MyMathFailedSpec.js')]; + spec = [resolve('testResources/sample-project/MyMath.js'), resolve('testResources/sample-project/MyMathFailedSpec.js')]; testInjector.options.mochaOptions = createMochaOptions({ spec }); sut = createSut(); return sut.init(); }); it('should only report the first failure', async () => { - const runResult = await sut.run({}); + const runResult = await sut.dryRun(factory.dryRunOptions()); + assertions.expectCompleted(runResult); expect(countFailed(runResult)).to.be.eq(1); }); }); describe('when no tests are executed', () => { beforeEach(() => { - spec = [resolve('./testResources/sampleProject/MyMath.js')]; + spec = [resolve('./testResources/sample-project/MyMath.js')]; testInjector.options.mochaOptions = createMochaOptions({ spec }); sut = createSut(); return sut.init(); }); it('should report no completed tests', async () => { - const runResult = await sut.run({}); + const runResult = await sut.dryRun(factory.dryRunOptions()); + assertions.expectCompleted(runResult); expect(countSucceeded(runResult)).to.be.eq(0, 'Succeeded tests did not match'); expect(countFailed(runResult)).to.be.eq(0, 'Failed tests did not match'); runResult.tests.forEach((t) => expect(t.timeSpentMs).to.be.greaterThan(-1).and.to.be.lessThan(1000)); - expect(runResult.status).to.be.eq(RunStatus.Complete, 'Test result did not match'); - expect(runResult.coverage).to.not.be.ok; }); }); }); diff --git a/packages/mocha-runner/test/integration/SampleProjectInstrumented.it.spec.ts b/packages/mocha-runner/test/integration/SampleProjectInstrumented.it.spec.ts new file mode 100644 index 0000000000..d9faf12a2b --- /dev/null +++ b/packages/mocha-runner/test/integration/SampleProjectInstrumented.it.spec.ts @@ -0,0 +1,148 @@ +import path = require('path'); + +import { testInjector, factory, assertions } from '@stryker-mutator/test-helpers'; +import { expect } from 'chai'; +import { MutantCoverage } from '@stryker-mutator/api/core'; + +import { MochaTestRunner, createMochaTestRunnerFactory } from '../../src'; +import { createMochaOptions } from '../helpers/factories'; + +function resolve(fileName: string) { + return path.resolve(__dirname, '..', '..', fileName); +} + +describe('Running an instrumented project', () => { + let sut: MochaTestRunner; + + beforeEach(async () => { + const spec = [ + resolve('./testResources/sample-project-instrumented/MyMath.js'), + resolve('./testResources/sample-project-instrumented/MyMathSpec.js'), + ]; + testInjector.options.mochaOptions = createMochaOptions({ spec }); + sut = testInjector.injector.injectFunction(createMochaTestRunnerFactory('__stryker2__')); + await sut.init(); + }); + + describe('dryRun', () => { + it('should report perTest mutantCoverage when coverage analysis is "perTest"', async () => { + const result = await sut.dryRun(factory.dryRunOptions({ coverageAnalysis: 'perTest' })); + assertions.expectCompleted(result); + const expectedMutantCoverage: MutantCoverage = { + perTest: { + 'MyMath should be able 1 to a number': { + '1': 1, + '4': 1, + '5': 1, + }, + 'MyMath should be able negate a number': { + '1': 1, + '6': 1, + '7': 1, + }, + 'MyMath should be able to add two numbers': { + '1': 1, + '2': 1, + '3': 1, + }, + 'MyMath should be able to recognize a negative number': { + '1': 1, + '8': 1, + '9': 1, + '10': 1, + '11': 1, + '12': 1, + '13': 1, + '14': 1, + '15': 1, + }, + 'MyMath should be able to recognize that 0 is not a negative number': { + '1': 1, + '8': 1, + '9': 1, + '10': 1, + '11': 1, + '12': 1, + '13': 1, + }, + }, + static: { + '0': 1, + }, + }; + expect(result.mutantCoverage).deep.eq(expectedMutantCoverage); + }); + + it('should report static mutantCoverage when coverage analysis is "all"', async () => { + const result = await sut.dryRun(factory.dryRunOptions({ coverageAnalysis: 'all' })); + assertions.expectCompleted(result); + const expectedMutantCoverage: MutantCoverage = { + perTest: {}, + static: { + '0': 1, + '1': 5, + '2': 1, + '3': 1, + '4': 1, + '5': 1, + '6': 1, + '7': 1, + '8': 2, + '9': 2, + '10': 2, + '11': 2, + '12': 2, + '13': 2, + '14': 1, + '15': 1, + }, + }; + expect(result.mutantCoverage).deep.eq(expectedMutantCoverage); + }); + + it('should not report mutantCoverage when coverage analysis is "off"', async () => { + const result = await sut.dryRun(factory.dryRunOptions({ coverageAnalysis: 'off' })); + assertions.expectCompleted(result); + expect(result.mutantCoverage).undefined; + }); + }); + + describe('mutantRun', () => { + it('should be able to survive a mutant', async () => { + const result = await sut.mutantRun(factory.mutantRunOptions({ activeMutant: factory.mutant({ id: 0 }) })); + assertions.expectSurvived(result); + }); + + it('should be able to kill a mutant', async () => { + const result = await sut.mutantRun(factory.mutantRunOptions({ activeMutant: factory.mutant({ id: 3 }) })); + assertions.expectKilled(result); + expect(result.killedBy).eq('MyMath should be able to add two numbers'); + expect(result.failureMessage).eq('expected -3 to equal 7'); + }); + + it('should bail after the first failed test', async () => { + const result = await sut.mutantRun(factory.mutantRunOptions({ activeMutant: factory.mutant({ id: 3 }) })); + assertions.expectKilled(result); + expect(result.nrOfTests).eq(1); + }); + + it('should be able to kill a mutant with filtered test', async () => { + const result = await sut.mutantRun( + factory.mutantRunOptions({ activeMutant: factory.mutant({ id: 3 }), testFilter: ['MyMath should be able to add two numbers'] }) + ); + assertions.expectKilled(result); + expect(result.killedBy).eq('MyMath should be able to add two numbers'); + expect(result.failureMessage).eq('expected -3 to equal 7'); + }); + + it('should be able to survive if killer test is not filtered', async () => { + const result = await sut.mutantRun( + factory.mutantRunOptions({ + activeMutant: factory.mutant({ id: 3 }), + testFilter: ['MyMath should be able negate a number', 'MyMath should be able to recognize a negative number'], + }) + ); + assertions.expectSurvived(result); + }); + }); +}); diff --git a/packages/mocha-runner/test/setup.ts b/packages/mocha-runner/test/setup.ts new file mode 100644 index 0000000000..17b2337b58 --- /dev/null +++ b/packages/mocha-runner/test/setup.ts @@ -0,0 +1,25 @@ +import 'source-map-support/register'; +import * as chai from 'chai'; +import * as chaiAsPromised from 'chai-as-promised'; +import * as sinon from 'sinon'; +import * as sinonChai from 'sinon-chai'; +import { testInjector } from '@stryker-mutator/test-helpers'; + +import { StrykerMochaReporter } from '../src/StrykerMochaReporter'; + +chai.use(sinonChai); +chai.use(chaiAsPromised); + +const cwd = process.cwd(); + +export const mochaHooks = { + afterEach() { + if (process.cwd() !== cwd) { + process.chdir(cwd); + } + sinon.restore(); + testInjector.reset(); + StrykerMochaReporter.currentInstance = undefined; + delete global.__stryker2__; + }, +}; diff --git a/packages/mocha-runner/test/unit/MochaAdapter.spec.ts b/packages/mocha-runner/test/unit/MochaAdapter.spec.ts new file mode 100644 index 0000000000..c23f11801f --- /dev/null +++ b/packages/mocha-runner/test/unit/MochaAdapter.spec.ts @@ -0,0 +1,159 @@ +import path = require('path'); +import fs = require('fs'); + +import sinon = require('sinon'); +import { expect } from 'chai'; +import { testInjector } from '@stryker-mutator/test-helpers'; + +import { MochaAdapter } from '../../src/MochaAdapter'; +import LibWrapper from '../../src/LibWrapper'; + +describe(MochaAdapter.name, () => { + let requireStub: sinon.SinonStub; + let collectFilesStub: sinon.SinonStub; + let handleRequiresStub: sinon.SinonStub; + let loadRootHooks: sinon.SinonStub; + let sut: MochaAdapter; + let mochaConstructorStub: sinon.SinonStub; + let existsSyncStub: sinon.SinonStub; + + beforeEach(() => { + requireStub = sinon.stub(LibWrapper, 'require'); + mochaConstructorStub = sinon.stub(LibWrapper, 'Mocha'); + collectFilesStub = sinon.stub(LibWrapper, 'collectFiles'); + handleRequiresStub = sinon.stub(LibWrapper, 'handleRequires'); + loadRootHooks = sinon.stub(LibWrapper, 'loadRootHooks'); + existsSyncStub = sinon.stub(fs, 'existsSync'); + sut = testInjector.injector.injectClass(MochaAdapter); + }); + + describe(MochaAdapter.prototype.create.name, () => { + it('should create a new mocha instance with provided options', () => { + const mochaInstance = { isMochaInstance: true }; + const mochaOptions: Mocha.MochaOptions = { timeout: 2356 }; + mochaConstructorStub.returns(mochaInstance); + const actual = sut.create(mochaOptions); + expect(actual).eq(mochaInstance); + expect(mochaConstructorStub).calledWithNew; + expect(mochaConstructorStub).calledWithExactly(mochaOptions); + }); + }); + + describe(MochaAdapter.prototype.collectFiles.name, () => { + let globStub: sinon.SinonStub; + + describe('when mocha version < 6', () => { + beforeEach(() => { + collectFilesStub.value(undefined); + globStub = sinon.stub(LibWrapper, 'glob'); + }); + + it('should log about mocha < 6 detection', async () => { + globStub.returns(['foo.js']); + sut.collectFiles({}); + expect(testInjector.logger.debug).calledWith('Mocha < 6 detected. Using custom logic to discover files'); + }); + + it('should support both `files` as `spec`', async () => { + globStub.returns(['foo.js']); + sut.collectFiles({ + files: ['bar'], + spec: ['foo'], + }); + expect(globStub).calledWith('foo'); + expect(globStub).calledWith('bar'); + }); + + it('should match given file names with configured mocha files as `string`', () => { + // Arrange + const relativeGlobPattern = '*.js'; + const expectedFiles = ['foo.js', 'bar.js']; + globStub.returns(expectedFiles); + + // Act + const actualFiles = sut.collectFiles({ files: relativeGlobPattern }); + + // Assert + expect(globStub).calledWith(relativeGlobPattern); + expect(actualFiles).deep.eq(expectedFiles); + }); + + it('should match given file names with default mocha pattern "test/**/*.js"', () => { + globStub.returns(['foo.js']); + sut.collectFiles({}); + expect(globStub).calledWith('test/**/*.js'); + }); + + it('should reject if no files could be discovered', async () => { + // Arrange + globStub.returns([]); + const relativeGlobbing = JSON.stringify(['test/**/*.js'], null, 2); + + // Act & assert + expect(() => sut.collectFiles({})).throws( + `[MochaTestRunner] No files discovered (tried pattern(s) ${relativeGlobbing}). Please specify the files (glob patterns) containing your tests in mochaOptions.spec in your config file.` + ); + expect(testInjector.logger.debug).calledWith(`Tried ${relativeGlobbing} but did not result in any files.`); + }); + }); + + describe('when mocha version >= 6', () => { + let discoveredFiles: string[]; + + beforeEach(() => { + discoveredFiles = []; + collectFilesStub.returns(discoveredFiles); + }); + + it('should log about mocha >= 6 detection', async () => { + sut.collectFiles({}); + expect(testInjector.logger.debug).calledWith("Mocha >= 6 detected. Using mocha's `collectFiles` to load files"); + }); + + it('should mock away the `process.exit` method when calling the mocha function (unfortunate side effect)', async () => { + const originalProcessExit = process.exit; + let stubbedProcessExit = process.exit; + collectFilesStub.callsFake(() => (stubbedProcessExit = process.exit)); + sut.collectFiles({}); + expect(originalProcessExit, "Process.exit doesn't seem to be stubbed away").not.eq(stubbedProcessExit); + expect(originalProcessExit, "Process.exit doesn't seem to be reset").eq(process.exit); + }); + }); + }); + + describe(MochaAdapter.prototype.handleRequires.name, () => { + describe('when mocha version < 7.2', () => { + beforeEach(() => { + handleRequiresStub.value(undefined); + }); + it('should pass require additional options when constructed', async () => { + await sut.handleRequires(['ts-node', 'babel-register']); + expect(requireStub).calledTwice; + expect(requireStub).calledWith('ts-node'); + expect(requireStub).calledWith('babel-register'); + }); + it('should resolve local files', async () => { + const setupFileName = path.resolve('test/setup.js'); + existsSyncStub.returns(false).withArgs(setupFileName).returns(true); + await sut.handleRequires(['ts-node', 'test/setup.js']); + expect(requireStub).calledWith('ts-node'); + expect(requireStub).calledWith(setupFileName); + }); + }); + + describe('when mocha version >= 7.2', () => { + it("should use mocha's `handleRequires`", async () => { + await sut.handleRequires(['ts-node']); + expect(handleRequiresStub).calledWithExactly(['ts-node']); + }); + + it('should also load the root hooks', async () => { + handleRequiresStub.resolves('raw root hooks'); + loadRootHooks.resolves('root hooks'); + const result = await sut.handleRequires(['./test/setup.js']); + expect(loadRootHooks).calledWith('raw root hooks'); + expect(result).eq('root hooks'); + }); + }); + }); +}); diff --git a/packages/mocha-runner/test/unit/MochaOptionsLoader.spec.ts b/packages/mocha-runner/test/unit/MochaOptionsLoader.spec.ts index 937ac6f8fe..d833d61143 100644 --- a/packages/mocha-runner/test/unit/MochaOptionsLoader.spec.ts +++ b/packages/mocha-runner/test/unit/MochaOptionsLoader.spec.ts @@ -66,9 +66,8 @@ describe(MochaOptionsLoader.name, () => { // Following are valid options rawOptions.extension = ['foo']; rawOptions.require = ['bar']; - rawOptions.timeout = 4200; rawOptions['async-only'] = true; - rawOptions.ui = 'quux'; + rawOptions.ui = 'qunit'; rawOptions.grep = 'quuz'; rawOptions.ignore = ['garply']; rawOptions.file = ['grault']; @@ -76,7 +75,7 @@ describe(MochaOptionsLoader.name, () => { rawOptions.garply = 'waldo'; // this should be filtered out const result = sut.load(options); - const expected: MochaOptions = createMochaOptions({ + const expected = createMochaOptions({ extension: ['foo'], file: ['grault'], grep: 'quuz', @@ -84,11 +83,10 @@ describe(MochaOptionsLoader.name, () => { opts: './test/mocha.opts', require: ['bar'], spec: ['test/**/*.js'], - timeout: 4200, 'async-only': true, - ui: 'quux', + ui: 'qunit', }); - expect(result).deep.eq({ ...expected }); + expect(result).deep.contains(expected); }); it('should trace log the mocha call', () => { @@ -104,7 +102,7 @@ describe(MochaOptionsLoader.name, () => { it("should respect mocha's defaults", () => { const actualOptions = sut.load(options); - expect(actualOptions).deep.eq(createMochaOptions()); + expect(actualOptions).deep.contains(createMochaOptions()); }); it('should not allow to set parallel', () => { @@ -130,7 +128,9 @@ describe(MochaOptionsLoader.name, () => { it('should log deprecated mocha version warning', async () => { existsFileStub.returns(false); sut.load(options); - expect(testInjector.logger.warn).calledWith('DEPRECATED: Mocha < 6 detected. Please upgrade to at least Mocha version 6.'); + expect(testInjector.logger.warn).calledWith( + 'DEPRECATED: Mocha < 6 detected. Please upgrade to at least Mocha version 6. Stryker will drop support for Mocha < 6 in V5.' + ); }); it('should load a mocha.opts file if specified', () => { @@ -175,7 +175,7 @@ describe(MochaOptionsLoader.name, () => { it('should not load default mocha.opts file if not found', () => { existsFileStub.returns(false); const mochaOptions = sut.load(options); - expect(mochaOptions).deep.eq(createMochaOptions()); + expect(mochaOptions).deep.contains(createMochaOptions()); expect(testInjector.logger.debug).calledWith( 'No mocha opts file found, not loading additional mocha options (%s was not defined).', 'mochaOptions.opts' @@ -202,8 +202,6 @@ describe(MochaOptionsLoader.name, () => { }); } - itShouldLoadProperty('--timeout', '2000', { timeout: 2000 }); - itShouldLoadProperty('-t', '2000', { timeout: 2000 }); itShouldLoadProperty('-A', '', { 'async-only': true }); itShouldLoadProperty('--async-only', '', { 'async-only': true }); itShouldLoadProperty('--ui', 'qunit', { ui: 'qunit' }); @@ -223,18 +221,16 @@ describe(MochaOptionsLoader.name, () => { 'async-only': false, opts: 'path/to/opts/file', require: ['ts-node/register'], - timeout: 4000, ui: 'exports', }; const mochaOptions = sut.load(options); - expect(mochaOptions).deep.equal( + expect(mochaOptions).deep.contains( createMochaOptions({ 'async-only': false, extension: ['js'], opts: 'path/to/opts/file', require: ['ts-node/register'], spec: ['test'], - timeout: 4000, ui: 'exports', }) ); @@ -264,12 +260,11 @@ describe(MochaOptionsLoader.name, () => { opts: 'some/mocha.opts/file', }; const mochaOptions = sut.load(options); - expect(mochaOptions).deep.eq( + expect(mochaOptions).deep.contain( createMochaOptions({ extension: ['js'], opts: 'some/mocha.opts/file', spec: ['test'], - timeout: 2000, ui: 'bdd', }) ); @@ -288,7 +283,6 @@ describe(MochaOptionsLoader.name, () => { ignore: [], opts: './test/mocha.opts', spec: ['test'], - timeout: 2000, ui: 'bdd', ...overrides, }; diff --git a/packages/mocha-runner/test/unit/MochaTestRunner.spec.ts b/packages/mocha-runner/test/unit/MochaTestRunner.spec.ts index f5c54e92fe..19468a3ca0 100644 --- a/packages/mocha-runner/test/unit/MochaTestRunner.spec.ts +++ b/packages/mocha-runner/test/unit/MochaTestRunner.spec.ts @@ -1,287 +1,292 @@ -import { EventEmitter } from 'events'; -import * as path from 'path'; - -import { commonTokens } from '@stryker-mutator/api/plugin'; -import { RunOptions } from '@stryker-mutator/api/test_runner'; -import { testInjector } from '@stryker-mutator/test-helpers'; import { expect } from 'chai'; import * as Mocha from 'mocha'; - +import { testInjector, factory, assertions } from '@stryker-mutator/test-helpers'; import sinon = require('sinon'); -import LibWrapper from '../../src/LibWrapper'; -import { MochaOptions } from '../../src-generated/mocha-runner-options'; +import { KilledMutantRunResult, MutantRunStatus } from '@stryker-mutator/api/test_runner'; +import { DirectoryRequireCache } from '@stryker-mutator/util'; + import { MochaTestRunner } from '../../src/MochaTestRunner'; import { StrykerMochaReporter } from '../../src/StrykerMochaReporter'; -import * as utils from '../../src/utils'; +import { MochaAdapter } from '../../src/MochaAdapter'; +import * as pluginTokens from '../../src/plugin-tokens'; +import MochaOptionsLoader from '../../src/MochaOptionsLoader'; +import { createMochaOptions } from '../helpers/factories'; describe(MochaTestRunner.name, () => { - let MochaStub: sinon.SinonStub; - let mocha: sinon.SinonStubbedInstance & { suite: sinon.SinonStubbedInstance }; - let sut: MochaTestRunner; - let requireStub: sinon.SinonStub; - let handleFilesStub: sinon.SinonStub; - let handleRequiresStub: sinon.SinonStub; - let loadRootHooks: sinon.SinonStub; + let directoryRequireCacheMock: sinon.SinonStubbedInstance; + let mocha: sinon.SinonStubbedInstance & { suite: sinon.SinonStubbedInstance; dispose?: sinon.SinonStub }; + let mochaAdapterMock: sinon.SinonStubbedInstance; + let mochaOptionsLoaderMock: sinon.SinonStubbedInstance; + let reporterMock: sinon.SinonStubbedInstance; beforeEach(() => { - MochaStub = sinon.stub(LibWrapper, 'Mocha'); - requireStub = sinon.stub(LibWrapper, 'require'); - handleFilesStub = sinon.stub(LibWrapper, 'handleFiles'); - handleRequiresStub = sinon.stub(LibWrapper, 'handleRequires'); - loadRootHooks = sinon.stub(LibWrapper, 'loadRootHooks'); - sinon.stub(utils, 'evalGlobal'); + reporterMock = sinon.createStubInstance(StrykerMochaReporter); + directoryRequireCacheMock = sinon.createStubInstance(DirectoryRequireCache); + reporterMock.tests = []; + mochaAdapterMock = sinon.createStubInstance(MochaAdapter); + mochaOptionsLoaderMock = sinon.createStubInstance(MochaOptionsLoader); mocha = sinon.createStubInstance(Mocha) as any; - mocha.suite = sinon.createStubInstance(EventEmitter) as Mocha.Suite & sinon.SinonStubbedInstance; - MochaStub.returns(mocha); + mocha.suite = sinon.createStubInstance(Mocha.Suite) as any; + mochaAdapterMock.create.returns(mocha); }); afterEach(() => { // These keys can be used to test the nodejs cache - delete require.cache['foo.js']; - delete require.cache['bar.js']; - delete require.cache['baz.js']; delete StrykerMochaReporter.log; }); - function createSut(mochaSettings: Partial<{ fileNames: readonly string[]; mochaOptions: Partial }>) { - testInjector.options.mochaOptions = mochaSettings.mochaOptions || {}; + function createSut(): MochaTestRunner { return testInjector.injector - .provideValue(commonTokens.sandboxFileNames, mochaSettings.fileNames || ['src/math.js', 'test/mathSpec.js']) + .provideValue(pluginTokens.mochaAdapter, mochaAdapterMock) + .provideValue(pluginTokens.loader, mochaOptionsLoaderMock) + .provideValue(pluginTokens.directoryRequireCache, directoryRequireCacheMock) + .provideValue(pluginTokens.globalNamespace, '__stryker2__' as const) .injectClass(MochaTestRunner); } - it('should set the static `log` property on StrykerMochaReporter', () => { - createSut({}); - expect(StrykerMochaReporter.log).eq(testInjector.logger); + describe('constructor', () => { + it('should set the static `log` property on StrykerMochaReporter', () => { + createSut(); + expect(StrykerMochaReporter.log).eq(testInjector.logger); + }); }); - describe('when mocha version < 6', () => { - let multimatchStub: sinon.SinonStub; - + describe(MochaTestRunner.prototype.init.name, () => { + let sut: MochaTestRunner; beforeEach(() => { - handleFilesStub.value(undefined); - multimatchStub = sinon.stub(LibWrapper, 'multimatch'); + sut = createSut(); }); - it('should log about mocha < 6 detection', async () => { - sut = createSut({}); - multimatchStub.returns(['foo.js']); + it('should load mocha options', async () => { + mochaOptionsLoaderMock.load.returns({}); await sut.init(); - expect(testInjector.logger.debug).calledWith('Mocha < 6 detected. Using custom logic to discover files'); + expect(mochaOptionsLoaderMock.load).calledWithExactly(testInjector.options); }); - it('should add discovered test files on run() ', async () => { - multimatchStub.returns(['foo.js', 'bar.js', 'foo2.js']); - sut = createSut({}); - await sut.init(); - await actRun(); - expect(mocha.addFile).calledThrice; - expect(mocha.addFile).calledWith('foo.js'); - expect(mocha.addFile).calledWith('foo2.js'); - expect(mocha.addFile).calledWith('bar.js'); - }); + it('should collect the files', async () => { + const expectedTestFileNames = ['foo.js', 'foo.spec.js']; + const mochaOptions = Object.freeze(createMochaOptions()); + mochaOptionsLoaderMock.load.returns(mochaOptions); + mochaAdapterMock.collectFiles.returns(expectedTestFileNames); - it('should support both `files` as `spec`', async () => { - multimatchStub.returns(['foo.js']); - sut = createSut({ - fileNames: ['foo'], - mochaOptions: { - files: ['bar'], - spec: ['foo'], - }, - }); await sut.init(); - await actRun(); - expect(multimatchStub).calledWith(['foo'], [path.resolve('foo'), path.resolve('bar')]); - }); - it('should match given file names with configured mocha files as `array`', () => { - const relativeGlobPatterns = ['*.js', 'baz.js']; - const expectedGlobPatterns = relativeGlobPatterns.map((glob) => path.resolve(glob)); - actAssertMatchedPatterns(relativeGlobPatterns, expectedGlobPatterns); + expect(mochaAdapterMock.collectFiles).calledWithExactly(mochaOptions); + expect(sut.testFileNames).eq(expectedTestFileNames); }); - it('should match given file names with configured mocha files as `string`', () => { - const relativeGlobPattern = '*.js'; - const expectedGlobPatterns = [path.resolve(relativeGlobPattern)]; - actAssertMatchedPatterns(relativeGlobPattern, expectedGlobPatterns); + it('should init the directory require cache', async () => { + const expectedTestFileNames = ['foo.js', 'foo.spec.js']; + mochaAdapterMock.collectFiles.returns(expectedTestFileNames); + mochaOptionsLoaderMock.load.returns({}); + + await sut.init(); + + expect(directoryRequireCacheMock.init).calledWithExactly({ + initFiles: expectedTestFileNames, + rootModuleId: require.resolve('mocha/lib/mocha'), + }); }); - it('should match given file names with default mocha pattern "test/**/*.js"', () => { - const expectedGlobPatterns = [path.resolve('test/**/*.js')]; - actAssertMatchedPatterns(undefined, expectedGlobPatterns); + it('should not handle requires when there are no `requires`', async () => { + mochaOptionsLoaderMock.load.returns({}); + await sut.init(); + expect(mochaAdapterMock.handleRequires).not.called; }); - it('should reject if no files could be discovered', async () => { - // Arrange - multimatchStub.returns([]); - const files = ['foo.js', 'bar.js']; - const relativeGlobbing = JSON.stringify(['test/**/*.js'], null, 2); - const absoluteGlobbing = JSON.stringify([path.resolve('test/**/*.js')], null, 2); - const filesStringified = JSON.stringify(files, null, 2); + it('should handle requires and collect root hooks', async () => { + const requires = ['test/setup.js']; + const expectedRootHooks = { beforeEach() {} }; + mochaOptionsLoaderMock.load.returns(createMochaOptions({ require: requires })); + mochaAdapterMock.handleRequires.returns(expectedRootHooks); - // Act - sut = createSut({ fileNames: files }); - const onGoingWork = sut.init(); + await sut.init(); - // Assert - await expect(onGoingWork).rejectedWith( - `[MochaTestRunner] No files discovered (tried pattern(s) ${relativeGlobbing}). Please specify the files (glob patterns) containing your tests in mochaOptions.spec in your config file.` - ); - expect(testInjector.logger.debug).calledWith(`Tried ${absoluteGlobbing} on files: ${filesStringified}.`); + expect(sut.rootHooks).eq(expectedRootHooks); }); - - function actAssertMatchedPatterns(relativeGlobPatterns: string | string[] | undefined, expectedGlobPatterns: string[]) { - const expectedFiles = ['foo.js', 'bar.js']; - multimatchStub.returns(['foo.js']); - sut = createSut({ fileNames: expectedFiles, mochaOptions: { files: relativeGlobPatterns } }); - sut.init(); - expect(multimatchStub).calledWith(expectedFiles, expectedGlobPatterns); - } }); - describe('when mocha version >= 6', () => { - let discoveredFiles: string[]; - + describe(MochaTestRunner.prototype.dryRun.name, () => { + let sut: MochaTestRunner; + let testFileNames: string[]; beforeEach(() => { - discoveredFiles = []; - handleFilesStub.returns(discoveredFiles); - }); - - it('should log about mocha >= 6 detection', async () => { - sut = createSut({}); - await sut.init(); - expect(testInjector.logger.debug).calledWith("Mocha >= 6 detected. Using mocha's `handleFiles` to load files"); - }); - - it('should mock away the `process.exit` method when calling the mocha function (unfortunate side effect)', async () => { - sut = createSut({}); - const originalProcessExit = process.exit; - let stubbedProcessExit = process.exit; - handleFilesStub.callsFake(() => (stubbedProcessExit = process.exit)); - await sut.init(); - expect(originalProcessExit, "Process.exit doesn't seem to be stubbed away").not.eq(stubbedProcessExit); - expect(originalProcessExit, "Process.exit doesn't seem to be reset").eq(process.exit); + testFileNames = []; + sut = createSut(); + sut.testFileNames = testFileNames; + sut.mochaOptions = {}; }); it('should pass along supported options to mocha', async () => { // Arrange - discoveredFiles.push('foo.js', 'bar.js', 'foo2.js'); - const mochaOptions: Partial = { - ['async-only']: true, - grep: 'grepme', - opts: 'opts', - require: [], - timeout: 2000, - ui: 'assert', - }; - sut = createSut({ mochaOptions }); - await sut.init(); + testFileNames.push('foo.js', 'bar.js', 'foo2.js'); + sut.mochaOptions['async-only'] = true; + sut.mochaOptions.grep = 'grepme'; + sut.mochaOptions.opts = 'opts'; + sut.mochaOptions.require = []; + sut.mochaOptions.ui = 'exports'; // Act - await actRun(); + await actDryRun(); // Assert expect(mocha.asyncOnly).called; - expect(mocha.timeout).calledWith(2000); - expect(mocha.ui).calledWith('assert'); + expect(mocha.ui).calledWith('exports'); expect(mocha.grep).calledWith('grepme'); }); - it("should don't set asyncOnly if asyncOnly is false", async () => { - // Arrange - const mochaOptions: Partial = { - ['async-only']: false, - }; - sut = createSut({ mochaOptions }); - await sut.init(); + it('should force timeout off', async () => { + await actDryRun(); + expect(mochaAdapterMock.create).calledWithMatch({ timeout: false }); + }); - // Act - await actRun(); + it('should force bail', async () => { + await actDryRun(); + expect(mochaAdapterMock.create).calledWithMatch({ bail: true }); + }); - // Assert + it("should don't set asyncOnly if asyncOnly is false", async () => { + sut.mochaOptions['async-only'] = false; + await actDryRun(); expect(mocha.asyncOnly).not.called; }); - it('should pass require additional require options when constructed', async () => { - handleRequiresStub.value(undefined); - const mochaOptions: Partial = { require: ['ts-node', 'babel-register'] }; - sut = createSut({ mochaOptions }); - await sut.init(); - expect(requireStub).calledTwice; - expect(requireStub).calledWith('ts-node'); - expect(requireStub).calledWith('babel-register'); + it('should pass rootHooks to the mocha instance', async () => { + const rootHooks = { beforeEach() {} }; + sut.rootHooks = rootHooks; + await actDryRun(); + expect(mochaAdapterMock.create).calledWithMatch({ rootHooks }); }); - it('should pass and resolve relative require options when constructed', async () => { - handleRequiresStub.value(undefined); - const mochaOptions: Partial = { require: ['./setup.js', 'babel-register'] }; - sut = createSut({ mochaOptions }); - await sut.init(); - const resolvedRequire = path.resolve('./setup.js'); - expect(requireStub).calledTwice; - expect(requireStub).calledWith(resolvedRequire); - expect(requireStub).calledWith('babel-register'); + it('should add collected files ', async () => { + sut.testFileNames.push('foo.js', 'bar.js', 'foo2.js'); + await actDryRun(); + expect(mocha.addFile).calledThrice; + expect(mocha.addFile).calledWith('foo.js'); + expect(mocha.addFile).calledWith('foo2.js'); + expect(mocha.addFile).calledWith('bar.js'); }); - it('should evaluate additional testHooks if required (in global mocha context)', async () => { - discoveredFiles.push(''); - sut = createSut({}); - await sut.init(); - await actRun({ timeout: 0, testHooks: 'foobar();' }); - expect(utils.evalGlobal).calledWith('foobar();'); - expect(mocha.suite.emit).calledWith('pre-require', global, '', mocha); - expect(mocha.suite.emit).calledWith('require', undefined, '', mocha); - expect(mocha.suite.emit).calledWith('post-require', global, '', mocha); + it('should add a beforeEach hook if coverage analysis is "perTest"', async () => { + testFileNames.push(''); + await actDryRun(factory.dryRunOptions({ coverageAnalysis: 'perTest' })); + expect(mocha.suite.beforeEach).calledWithMatch('StrykerIntercept', sinon.match.func); + mocha.suite.beforeEach.callArgOnWith(1, { currentTest: { fullTitle: () => 'foo should be bar' } }); + expect(global.__stryker2__?.currentTestId).eq('foo should be bar'); + }); + + it('should not add a beforeEach hook if coverage analysis isn\'t "perTest"', async () => { + testFileNames.push(''); + await actDryRun(factory.dryRunOptions({ coverageAnalysis: 'all' })); + expect(mocha.suite.beforeEach).not.called; + }); + + it('should collect mutant coverage', async () => { + testFileNames.push(''); + StrykerMochaReporter.currentInstance = reporterMock; + reporterMock.tests = []; + global.__stryker2__!.mutantCoverage = factory.mutantCoverage({ static: { 1: 2 } }); + const result = await actDryRun(factory.dryRunOptions({ coverageAnalysis: 'all' })); + assertions.expectCompleted(result); + expect(result.mutantCoverage).deep.eq(factory.mutantCoverage({ static: { 1: 2 } })); + }); + + it('should not collect mutant coverage if coverageAnalysis is "off"', async () => { + testFileNames.push(''); + StrykerMochaReporter.currentInstance = reporterMock; + reporterMock.tests = []; + global.__stryker2__!.mutantCoverage = factory.mutantCoverage({ static: { 1: 2 } }); + const result = await actDryRun(factory.dryRunOptions({ coverageAnalysis: 'off' })); + assertions.expectCompleted(result); + expect(result.mutantCoverage).undefined; + }); + + it('should result in the reported tests', async () => { + testFileNames.push(''); + const expectedTests = [factory.successTestResult(), factory.failedTestResult()]; + StrykerMochaReporter.currentInstance = reporterMock; + reporterMock.tests = expectedTests; + const result = await actDryRun(factory.dryRunOptions({ coverageAnalysis: 'off' })); + assertions.expectCompleted(result); + expect(result.tests).eq(expectedTests); + }); + + it("should result an error if the StrykerMochaReporter isn't set correctly", async () => { + testFileNames.push(''); + const result = await actDryRun(factory.dryRunOptions({ coverageAnalysis: 'off' })); + assertions.expectErrored(result); + expect(result.errorMessage).eq("Mocha didn't instantiate the StrykerMochaReporter correctly. Test result cannot be reported."); }); - it('should purge cached sandbox files', async () => { + it('should collect and purge the requireCache between runs', async () => { // Arrange - sut = createSut({ fileNames: ['foo.js', 'bar.js'] }); - discoveredFiles.push('foo.js'); // should still purge 'bar.js' - sut.init(); - require.cache['foo.js'] = 'foo' as any; - require.cache['bar.js'] = 'bar' as any; - require.cache['baz.js'] = 'baz' as any; + testFileNames.push(''); // Act - await actRun(); + await actDryRun(factory.dryRunOptions()); // Assert - expect(require.cache['foo.js']).undefined; - expect(require.cache['bar.js']).undefined; - expect(require.cache['baz.js']).eq('baz'); + expect(directoryRequireCacheMock.clear).called; + expect(directoryRequireCacheMock.record).called; + expect(directoryRequireCacheMock.clear).calledBefore(directoryRequireCacheMock.record); + }); + + it('should dispose of mocha when it supports it', async () => { + mocha.dispose = sinon.stub(); + await actDryRun(); + expect(mocha.dispose).called; }); + + async function actDryRun(options = factory.dryRunOptions()) { + mocha.run.onFirstCall().callsArg(0); + return sut.dryRun(options); + } }); - describe('when mocha version >=8', () => { + describe(MochaTestRunner.prototype.mutantRun.name, () => { + let sut: MochaTestRunner; beforeEach(() => { - handleFilesStub.returns(['src/math.js', 'test/math.spec.js']); + sut = createSut(); + sut.testFileNames = []; + sut.mochaOptions = {}; + StrykerMochaReporter.currentInstance = reporterMock; }); - it('should handle require and allow for rootHooks', async () => { - handleRequiresStub.resolves(['root-hook1', 'bar-hook']); - const mochaOptions: Partial = { require: ['./setup.js', 'babel-register'] }; - sut = createSut({ mochaOptions }); - await sut.init(); - expect(handleRequiresStub).calledWithExactly(['./setup.js', 'babel-register']); - expect(loadRootHooks).calledWithExactly(['root-hook1', 'bar-hook']); + it('should active the given mutant', async () => { + await actMutantRun(factory.mutantRunOptions({ activeMutant: factory.mutant({ id: 42 }) })); + expect(global.__stryker2__?.activeMutant).eq(42); }); - it('should pass rootHooks to the mocha instance', async () => { - handleRequiresStub.resolves(['root-hook1', 'bar-hook']); - const rootHooks = { beforeEach() {} }; - loadRootHooks.resolves(rootHooks); - const mochaOptions: Partial = { require: ['./setup.js', 'babel-register'] }; - sut = createSut({ mochaOptions }); - await sut.init(); - await actRun(); - expect(LibWrapper.Mocha).calledWithMatch({ rootHooks }); + it('should use `grep` to when the test filter is specified', async () => { + await actMutantRun(factory.mutantRunOptions({ testFilter: ['foo should be bar', 'baz should be qux'] })); + expect(mocha.grep).calledWith(new RegExp('(foo should be bar)|(baz should be qux)')); }); - }); - async function actRun(options: RunOptions = { timeout: 0 }) { - mocha.run.callsArg(0); - return sut.run(options); - } + it('should escape regex characters when filtering', async () => { + await actMutantRun(factory.mutantRunOptions({ testFilter: ['should escape *.\\, but not /'] })); + expect(mocha.grep).calledWith(new RegExp('(should escape \\*\\.\\\\, but not /)')); + }); + + it('should be able to report a killed mutant when a test fails', async () => { + reporterMock.tests = [factory.successTestResult(), factory.failedTestResult({ id: 'foo should be bar', failureMessage: 'foo was baz' })]; + const result = await actMutantRun(); + const expectedResult: KilledMutantRunResult = { + failureMessage: 'foo was baz', + killedBy: 'foo should be bar', + status: MutantRunStatus.Killed, + nrOfTests: 2, + }; + expect(result).deep.eq(expectedResult); + }); + + it('should be able report a survived mutant when all test succeed', async () => { + reporterMock.tests = [factory.successTestResult(), factory.successTestResult()]; + const result = await actMutantRun(); + assertions.expectSurvived(result); + }); + + async function actMutantRun(options = factory.mutantRunOptions()) { + mocha.run.callsArg(0); + return sut.mutantRun(options); + } + }); }); diff --git a/packages/mocha-runner/testResources/big-project/src/big-text.js b/packages/mocha-runner/testResources/big-project/src/big-text.js new file mode 100644 index 0000000000..b6cd664ae5 --- /dev/null +++ b/packages/mocha-runner/testResources/big-project/src/big-text.js @@ -0,0 +1,6 @@ + +// Change the text each iteration to prevent nodejs from optimizing it into one value on the heap +if (!global.n) { + global.n = 500000; +} +module.exports.text = new Array(global.n++).fill('i').join(','); diff --git a/packages/mocha-runner/testResources/big-project/test/big-text.spec.js b/packages/mocha-runner/testResources/big-project/test/big-text.spec.js new file mode 100644 index 0000000000..860dab4e9e --- /dev/null +++ b/packages/mocha-runner/testResources/big-project/test/big-text.spec.js @@ -0,0 +1,9 @@ +const { text } = require('../src/big-text'); + +describe('Big text', () => { + it('should contain i', () => { + if (text.indexOf('i') === -1) { + throw new Error(); + } + }); +}); diff --git a/packages/mocha-runner/testResources/sample-project-instrumented/MyMath.js b/packages/mocha-runner/testResources/sample-project-instrumented/MyMath.js new file mode 100644 index 0000000000..b3a16ffba3 --- /dev/null +++ b/packages/mocha-runner/testResources/sample-project-instrumented/MyMath.js @@ -0,0 +1,117 @@ +// This file is generated with tasks/instrument-test-resources.js + 'use strict'; + +function stryNS_9fa48() { + var g = new Function("return this")(); + var ns = g.__stryker2__ || (g.__stryker2__ = {}); + + if (ns.activeMutant === undefined && g.process && g.process.env && g.process.env.__STRYKER_ACTIVE_MUTANT__) { + ns.activeMutant = Number(g.process.env.__STRYKER_ACTIVE_MUTANT__); + } + + function retrieveNS() { + return ns; + } + + stryNS_9fa48 = retrieveNS; + return retrieveNS(); +} + +stryNS_9fa48(); + +function stryCov_9fa48() { + var ns = stryNS_9fa48(); + var cov = ns.mutantCoverage || (ns.mutantCoverage = { + static: {}, + perTest: {} + }); + + function cover() { + var c = cov.static; + + if (ns.currentTestId) { + c = cov.perTest[ns.currentTestId] = cov.perTest[ns.currentTestId] || {}; + } + + var a = arguments; + + for (var i = 0; i < a.length; i++) { + c[a[i]] = (c[a[i]] || 0) + 1; + } + } + + stryCov_9fa48 = cover; + cover.apply(null, arguments); +} + +function stryMutAct_9fa48(id) { + var ns = stryNS_9fa48(); + + function isActive(id) { + return ns.activeMutant === id; + } + + stryMutAct_9fa48 = isActive; + return isActive(id); +} + +const pi = stryMutAct_9fa48(0) ? 3 - .14 : (stryCov_9fa48(0), 3 + .14); + +function MyMath() { + if (stryMutAct_9fa48(1)) { + {} + } else { + stryCov_9fa48(1); + this.pi = pi; + } +} + +MyMath.prototype.add = function (num1, num2) { + if (stryMutAct_9fa48(2)) { + {} + } else { + stryCov_9fa48(2); + return stryMutAct_9fa48(3) ? num1 - num2 : (stryCov_9fa48(3), num1 + num2); + } +}; + +MyMath.prototype.addOne = function (number) { + if (stryMutAct_9fa48(4)) { + {} + } else { + stryCov_9fa48(4); + stryMutAct_9fa48(5) ? number-- : (stryCov_9fa48(5), number++); + return number; + } +}; + +MyMath.prototype.negate = function (number) { + if (stryMutAct_9fa48(6)) { + {} + } else { + stryCov_9fa48(6); + return stryMutAct_9fa48(7) ? +number : (stryCov_9fa48(7), -number); + } +}; + +MyMath.prototype.isNegativeNumber = function (number) { + if (stryMutAct_9fa48(8)) { + {} + } else { + stryCov_9fa48(8); + var isNegative = stryMutAct_9fa48(9) ? true : (stryCov_9fa48(9), false); + + if (stryMutAct_9fa48(13) ? number >= 0 : stryMutAct_9fa48(12) ? number <= 0 : stryMutAct_9fa48(11) ? false : stryMutAct_9fa48(10) ? true : (stryCov_9fa48(10, 11, 12, 13), number < 0)) { + if (stryMutAct_9fa48(14)) { + {} + } else { + stryCov_9fa48(14); + isNegative = stryMutAct_9fa48(15) ? false : (stryCov_9fa48(15), true); + } + } + + return isNegative; + } +}; + +module.exports = MyMath; \ No newline at end of file diff --git a/packages/mocha-runner/testResources/sampleProject/MyMathSpec.js b/packages/mocha-runner/testResources/sample-project-instrumented/MyMathSpec.js similarity index 100% rename from packages/mocha-runner/testResources/sampleProject/MyMathSpec.js rename to packages/mocha-runner/testResources/sample-project-instrumented/MyMathSpec.js diff --git a/packages/mocha-runner/testResources/sampleProject/Error.js b/packages/mocha-runner/testResources/sample-project/Error.js similarity index 100% rename from packages/mocha-runner/testResources/sampleProject/Error.js rename to packages/mocha-runner/testResources/sample-project/Error.js diff --git a/packages/mocha-runner/testResources/sample-project/MyMath.js b/packages/mocha-runner/testResources/sample-project/MyMath.js new file mode 100644 index 0000000000..18e67210de --- /dev/null +++ b/packages/mocha-runner/testResources/sample-project/MyMath.js @@ -0,0 +1,31 @@ +'use strict'; + +const pi = 3 + .14; + +function MyMath() { + this.pi = pi; +} + +MyMath.prototype.add = function(num1, num2) { + return num1 + num2; +}; + +MyMath.prototype.addOne = function(number) { + number++; + return number; +}; + +MyMath.prototype.negate = function(number) { + return -number; +}; + +MyMath.prototype.isNegativeNumber = function(number) { + var isNegative = false; + if(number < 0){ + isNegative = true; + } + return isNegative; +}; + +module.exports = MyMath; + diff --git a/packages/mocha-runner/testResources/sampleProject/MyMathFailedSpec.js b/packages/mocha-runner/testResources/sample-project/MyMathFailedSpec.js similarity index 100% rename from packages/mocha-runner/testResources/sampleProject/MyMathFailedSpec.js rename to packages/mocha-runner/testResources/sample-project/MyMathFailedSpec.js diff --git a/packages/mocha-runner/testResources/sample-project/MyMathSpec.js b/packages/mocha-runner/testResources/sample-project/MyMathSpec.js new file mode 100644 index 0000000000..df41c58b5f --- /dev/null +++ b/packages/mocha-runner/testResources/sample-project/MyMathSpec.js @@ -0,0 +1,58 @@ +var expect = require('chai').expect; +var MyMath = require('./MyMath'); + +describe('MyMath', function () { + var myMath; + + beforeEach(function () { + try { + myMath = new MyMath(); + } catch (err) { + console.log(err); + } + }); + + it('should be able to add two numbers', function () { + var num1 = 2; + var num2 = 5; + var expected = num1 + num2; + + var actual = myMath.add(num1, num2); + + expect(actual).to.equal(expected); + }); + + it('should be able 1 to a number', function () { + var number = 2; + var expected = 3; + + var actual = myMath.addOne(number); + + expect(actual).to.equal(expected); + }); + + it('should be able negate a number', function () { + var number = 2; + var expected = -2; + + var actual = myMath.negate(number); + + expect(actual).to.equal(expected); + }); + + it('should be able to recognize a negative number', function () { + var number = -2; + + var isNegative = myMath.isNegativeNumber(number); + + expect(isNegative).to.equal(true); + }); + + it('should be able to recognize that 0 is not a negative number', function () { + var number = 0; + + var isNegative = myMath.isNegativeNumber(number); + + expect(isNegative).to.equal(false); + }); +}); diff --git a/packages/mocha-runner/testResources/sampleProject/MyMath.js b/packages/mocha-runner/testResources/sampleProject/MyMath.js deleted file mode 100644 index ff101ce828..0000000000 --- a/packages/mocha-runner/testResources/sampleProject/MyMath.js +++ /dev/null @@ -1,29 +0,0 @@ -'use strict'; - -function MyMath() { - -} - -MyMath.prototype.add = function(num1, num2) { - return num1 + num2; -}; - -MyMath.prototype.addOne = function(number) { - number++; - return number; -}; - -MyMath.prototype.negate = function(number) { - return -number; -}; - -MyMath.prototype.isNegativeNumber = function(number) { - var isNegative = false; - if(number < 0){ - isNegative = true; - } - return isNegative; -}; - -module.exports = MyMath; - diff --git a/packages/mocha-runner/tsconfig.stryker.json b/packages/mocha-runner/tsconfig.stryker.json deleted file mode 100644 index 5ba0808b0e..0000000000 --- a/packages/mocha-runner/tsconfig.stryker.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "./tsconfig.test.json", - "include": [ - "src-generated", - "src", - "schema/*.json", - "test" - ], -} diff --git a/packages/mocha-runner/typings/global.d.ts b/packages/mocha-runner/typings/global.d.ts new file mode 100644 index 0000000000..f12ce79d7a --- /dev/null +++ b/packages/mocha-runner/typings/global.d.ts @@ -0,0 +1,7 @@ +declare namespace NodeJS { + interface Global { + __stryker__: import('@stryker-mutator/api/core').InstrumenterContext | undefined; + // used during testing, so we can actually run stryker on the @stryker-mutator/mocha-runner package itself + __stryker2__: import('@stryker-mutator/api/core').InstrumenterContext | undefined; + } +} diff --git a/packages/mutator-specification/.npmignore b/packages/mutator-specification/.npmignore deleted file mode 100644 index 5ad76d0ac9..0000000000 --- a/packages/mutator-specification/.npmignore +++ /dev/null @@ -1,6 +0,0 @@ -**/* -!bin/** -!src/** -!readme.md -!LICENSE -!CHANGELOG.md \ No newline at end of file diff --git a/packages/mutator-specification/CHANGELOG.md b/packages/mutator-specification/CHANGELOG.md deleted file mode 100644 index 944daa92a1..0000000000 --- a/packages/mutator-specification/CHANGELOG.md +++ /dev/null @@ -1,415 +0,0 @@ -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -## [3.3.1](https://github.com/stryker-mutator/stryker/compare/v3.3.0...v3.3.1) (2020-07-04) - -**Note:** Version bump only for package @stryker-mutator/mutator-specification - - - - - -# [3.3.0](https://github.com/stryker-mutator/stryker/compare/v3.2.4...v3.3.0) (2020-06-16) - -**Note:** Version bump only for package @stryker-mutator/mutator-specification - - - - - -## [3.2.4](https://github.com/stryker-mutator/stryker/compare/v3.2.3...v3.2.4) (2020-05-18) - -**Note:** Version bump only for package @stryker-mutator/mutator-specification - - - - - -## [3.2.3](https://github.com/stryker-mutator/stryker/compare/v3.2.2...v3.2.3) (2020-05-15) - -**Note:** Version bump only for package @stryker-mutator/mutator-specification - - - - - -## [3.2.2](https://github.com/stryker-mutator/stryker/compare/v3.2.1...v3.2.2) (2020-05-15) - -**Note:** Version bump only for package @stryker-mutator/mutator-specification - - - - - -## [3.2.1](https://github.com/stryker-mutator/stryker/compare/v3.2.0...v3.2.1) (2020-05-15) - -**Note:** Version bump only for package @stryker-mutator/mutator-specification - - - - - -# [3.2.0](https://github.com/stryker-mutator/stryker/compare/v3.1.0...v3.2.0) (2020-05-13) - -**Note:** Version bump only for package @stryker-mutator/mutator-specification - - - - - - -# [3.1.0](https://github.com/stryker-mutator/stryker/compare/v3.0.2...v3.1.0) (2020-03-29) - -**Note:** Version bump only for package @stryker-mutator/mutator-specification - - - - - -## [3.0.2](https://github.com/stryker-mutator/stryker/compare/v3.0.1...v3.0.2) (2020-03-13) - - -### Bug Fixes - -* **nodejs requirement:** set NodeJS requirement to at least Node 10 ([8c08059](https://github.com/stryker-mutator/stryker/commit/8c080594a87d638ea4349ee69e05ed6c7eba6463)) - - - - - -## [3.0.1](https://github.com/stryker-mutator/stryker/compare/v3.0.0...v3.0.1) (2020-03-12) - -**Note:** Version bump only for package @stryker-mutator/mutator-specification - - - - - -# [3.0.0](https://github.com/stryker-mutator/stryker/compare/v2.5.0...v3.0.0) (2020-03-11) - - -### Features - -* **excludedMutations:** remove deprecated mutation names ([#2027](https://github.com/stryker-mutator/stryker/issues/2027)) ([6f7bfe1](https://github.com/stryker-mutator/stryker/commit/6f7bfe13e8ec681d73c97d9b7fbd3f88a313ed6d)) - - -### BREAKING CHANGES - -* **excludedMutations:** removes auto-fix for the old names of mutations. - -### Migrating: -Almost every mutator has been renamed and/or split. Stryker will warn you about any deprecated mutator names in the `mutator.excludedMutations` section of your config. - -To migrate, please run stryker to see if your project is affected. If this is the case, please take a look at the mutator types on the handbook (see above). - -These are the changes: - -| Old mutation | New mutation(s) | -|------------------------ |------------------------------------------------------- | -| ArrayLiteral | ArrayDeclaration | -| ArrayNewExpression | ArrayDeclaration | -| BinaryExpression | ArithmeticOperator, EqualityOperator, LogicalOperator | -| Block | BlockStatement | -| BooleanSubstitution | BooleanLiteral | -| DoStatement | ConditionalExpression | -| ForStatement | ConditionalExpression | -| IfStatement | ConditionalExpression | -| PrefixUnaryExpression | UnaryOperator, UpdateOperator, BooleanLiteral | -| PostfixUnaryExpression | UpdateOperator | -| SwitchCase | ConditionalExpression | -| WhileStatement | ConditionalExpression | - - -### New mutations -Due to the migration, some new mutations were added to the **javascript** mutator. -* The mutation _ArrayDeclaration_ will now mutate `new Array()` to `new Array([])` -* The mutation _ArrayDeclaration_ will now mutate `[]` to `["Stryker was here"]` - -These mutations were already performed by the typescript mutator. - - - - - - -# [2.5.0](https://github.com/stryker-mutator/stryker/compare/v2.4.0...v2.5.0) (2020-01-12) - - -### Features - -* **TypeScript mutator:** mutate Array constructor calls without the new keyword ([#1903](https://github.com/stryker-mutator/stryker/issues/1903)) ([aecd944](https://github.com/stryker-mutator/stryker/commit/aecd944)), closes [#1902](https://github.com/stryker-mutator/stryker/issues/1902) - - - - - -# [2.4.0](https://github.com/stryker-mutator/stryker/compare/v2.3.0...v2.4.0) (2019-11-24) - - -### Features - -* **excludedMutations:** Implement new naming of mutators ([#1855](https://github.com/stryker-mutator/stryker/issues/1855)) ([c9b3bcb](https://github.com/stryker-mutator/stryker/commit/c9b3bcb)) - - - - - -# [2.3.0](https://github.com/stryker-mutator/stryker/compare/v2.2.1...v2.3.0) (2019-11-13) - -**Note:** Version bump only for package @stryker-mutator/mutator-specification - - - - - -## [2.2.1](https://github.com/stryker-mutator/stryker/compare/v2.2.0...v2.2.1) (2019-11-06) - -**Note:** Version bump only for package @stryker-mutator/mutator-specification - - - - - -# [2.2.0](https://github.com/stryker-mutator/stryker/compare/v2.1.0...v2.2.0) (2019-11-06) - -**Note:** Version bump only for package @stryker-mutator/mutator-specification - - - - - -# [2.1.0](https://github.com/stryker-mutator/stryker/compare/v2.0.2...v2.1.0) (2019-09-08) - -**Note:** Version bump only for package @stryker-mutator/mutator-specification - - - - - -## [2.0.2](https://github.com/stryker-mutator/stryker/compare/v2.0.1...v2.0.2) (2019-07-11) - -**Note:** Version bump only for package @stryker-mutator/mutator-specification - - - - - -## [2.0.1](https://github.com/stryker-mutator/stryker/compare/v2.0.0...v2.0.1) (2019-07-02) - -**Note:** Version bump only for package @stryker-mutator/mutator-specification - - - - - -# [2.0.0](https://github.com/stryker-mutator/stryker/compare/v1.3.1...v2.0.0) (2019-05-17) - - -### Features - -* **node 6:** drop support for node 6 ([#1517](https://github.com/stryker-mutator/stryker/issues/1517)) ([801d7cd](https://github.com/stryker-mutator/stryker/commit/801d7cd)) - - -### BREAKING CHANGES - -* **node 6:** support for Node 6 has been dropped. Node 8 or higher is now required. - - - - - -## [1.3.1](https://github.com/stryker-mutator/stryker/compare/v1.3.0...v1.3.1) (2019-04-26) - -**Note:** Version bump only for package @stryker-mutator/mutator-specification - - - - - -# [1.3.0](https://github.com/stryker-mutator/stryker/compare/v1.2.0...v1.3.0) (2019-04-24) - -**Note:** Version bump only for package @stryker-mutator/mutator-specification - - - - - -# [1.2.0](https://github.com/stryker-mutator/stryker/compare/v1.1.1...v1.2.0) (2019-04-02) - -**Note:** Version bump only for package @stryker-mutator/mutator-specification - - - - - -## [1.1.1](https://github.com/stryker-mutator/stryker/compare/v1.1.0...v1.1.1) (2019-03-21) - -**Note:** Version bump only for package @stryker-mutator/mutator-specification - - - - - -# [1.1.0](https://github.com/stryker-mutator/stryker/compare/v1.0.3...v1.1.0) (2019-03-04) - -**Note:** Version bump only for package @stryker-mutator/mutator-specification - - - - - -## [1.0.3](https://github.com/stryker-mutator/stryker/compare/v1.0.2...v1.0.3) (2019-02-26) - -**Note:** Version bump only for package @stryker-mutator/mutator-specification - - - - - -## [1.0.0](https://github.com/stryker-mutator/stryker/compare/stryker-mutator-specification@0.7.1...@stryker-mutator/mutator-specification@1.0.0) (2019-02-13) - - -### Features - -* **rename:** rename `stryker-xxx-xxx` -> `[@stryker-mutator](https://github.com/stryker-mutator)/xxx-xxx` ([1bbd6ff](https://github.com/stryker-mutator/stryker/commit/1bbd6ff)) - - -### BREAKING CHANGES - -* **rename:** The core package and plugins have been renamed: stryker-mutator-specification -> @stryker-mutator/mutator-specification - - - - - -## [0.7.1](https://github.com/stryker-mutator/stryker/compare/stryker-mutator-specification@0.7.0...stryker-mutator-specification@0.7.1) (2019-02-08) - -**Note:** Version bump only for package stryker-mutator-specification - - - - - - -# [0.7.0](https://github.com/stryker-mutator/stryker/compare/stryker-mutator-specification@0.6.0...stryker-mutator-specification@0.7.0) (2018-11-29) - - -### Bug Fixes - -* **String literal mutator:** Don't mutate export declarations ([c764ccd](https://github.com/stryker-mutator/stryker/commit/c764ccd)) - - -### Features - -* **Conditional expression mutator:** Mutate conditional operators ([#1253](https://github.com/stryker-mutator/stryker/issues/1253)) ([be4c990](https://github.com/stryker-mutator/stryker/commit/be4c990)) - - - - - -# [0.6.0](https://github.com/stryker-mutator/stryker/compare/stryker-mutator-specification@0.5.1...stryker-mutator-specification@0.6.0) (2018-10-06) - - -### Features - -* **mutator:** Object literal mutator ([#1169](https://github.com/stryker-mutator/stryker/issues/1169)) ([43d9a3a](https://github.com/stryker-mutator/stryker/commit/43d9a3a)) - - - - - -## [0.5.1](https://github.com/stryker-mutator/stryker/compare/stryker-mutator-specification@0.5.0...stryker-mutator-specification@0.5.1) (2018-09-30) - - -### Bug Fixes - -* **mutator:** Fix empty case statement unkillable mutant ([#1159](https://github.com/stryker-mutator/stryker/issues/1159)) ([e080acb](https://github.com/stryker-mutator/stryker/commit/e080acb)) - - - - - -# [0.5.0](https://github.com/stryker-mutator/stryker/compare/stryker-mutator-specification@0.4.0...stryker-mutator-specification@0.5.0) (2018-09-14) - - -### Features - -* **mutator:** add SwitchCase statement mutator ([#1127](https://github.com/stryker-mutator/stryker/issues/1127)) ([cec6a39](https://github.com/stryker-mutator/stryker/commit/cec6a39)) - - - - - -# [0.4.0](https://github.com/stryker-mutator/stryker/compare/stryker-mutator-specification@0.3.1...stryker-mutator-specification@0.4.0) (2018-07-20) - - -### Features - -* **logging:** Allow log to a file ([#954](https://github.com/stryker-mutator/stryker/issues/954)) ([c2f6b82](https://github.com/stryker-mutator/stryker/commit/c2f6b82)), closes [#748](https://github.com/stryker-mutator/stryker/issues/748) - - - - - -## [0.3.1](https://github.com/stryker-mutator/stryker/compare/stryker-mutator-specification@0.3.0...stryker-mutator-specification@0.3.1) (2018-05-31) - - -### Bug Fixes - -* **String mutator:** do not mutate prologue directives ([#829](https://github.com/stryker-mutator/stryker/issues/829)) ([6e80251](https://github.com/stryker-mutator/stryker/commit/6e80251)) - - - - - -# [0.3.0](https://github.com/stryker-mutator/stryker/compare/stryker-mutator-specification@0.2.3...stryker-mutator-specification@0.3.0) (2018-04-30) - - -### Features - -* **node version:** drop node 4 support ([#724](https://github.com/stryker-mutator/stryker/issues/724)) ([a038931](https://github.com/stryker-mutator/stryker/commit/a038931)) - - -### BREAKING CHANGES - -* **node version:** Node 4 is no longer supported. - - - - - -## [0.2.3](https://github.com/stryker-mutator/stryker/compare/stryker-mutator-specification@0.2.2...stryker-mutator-specification@0.2.3) (2018-04-20) - - -### Bug Fixes - -* **String mutator:** do not mutate jsx attributes ([#711](https://github.com/stryker-mutator/stryker/issues/711)) ([6656621](https://github.com/stryker-mutator/stryker/commit/6656621)), closes [#701](https://github.com/stryker-mutator/stryker/issues/701) - - - - - -## [0.2.2](https://github.com/stryker-mutator/stryker/compare/stryker-mutator-specification@0.2.1...stryker-mutator-specification@0.2.2) (2018-03-21) - - - - -**Note:** Version bump only for package stryker-mutator-specification - - -## [0.2.1](https://github.com/stryker-mutator/stryker/compare/stryker-mutator-specification@0.2.0...stryker-mutator-specification@0.2.1) (2018-01-12) - - - - -**Note:** Version bump only for package stryker-mutator-specification - - -# 0.2.0 (2017-11-24) - - -### Features - -* **JavaScript mutator:** Add stryker-javascript-mutator package ([#467](https://github.com/stryker-mutator/stryker/issues/467)) ([06d6bac](https://github.com/stryker-mutator/stryker/commit/06d6bac)), closes [#429](https://github.com/stryker-mutator/stryker/issues/429) diff --git a/packages/mutator-specification/README.md b/packages/mutator-specification/README.md deleted file mode 100644 index 9124180b6b..0000000000 --- a/packages/mutator-specification/README.md +++ /dev/null @@ -1,12 +0,0 @@ -[![NPM](https://img.shields.io/npm/dm/@stryker-mutator/mutator-specification.svg)](https://www.npmjs.com/package/@stryker-mutator/mutator-specification) -[![Node version](https://img.shields.io/node/v/@stryker-mutator/mutator-specification.svg)](https://img.shields.io/node/v/@stryker-mutator/mutator-specification.svg) -[![Slack Chat](https://img.shields.io/badge/slack-chat-brightgreen.svg?logo=slack)](https://join.slack.com/t/stryker-mutator/shared_invite/enQtOTUyMTYyNTg1NDQ0LTU4ODNmZDlmN2I3MmEyMTVhYjZlYmJkOThlNTY3NTM1M2QxYmM5YTM3ODQxYmJjY2YyYzllM2RkMmM1NjNjZjM) -![Stryker](https://github.com/stryker-mutator/stryker/raw/master/stryker-80x80.png) - -# Stryker mutator specification - -This package contains a specification for mutators for [Stryker](https://stryker-mutator.io) - The JavaScript mutation testing framework. - -Stryker is language agnostic, examples of mutators are the [JavaScript mutator](https://github.com/stryker-mutator/stryker/tree/master/packages/javascript-mutator) and the [TypeScript mutator](https://github.com/stryker-mutator/stryker/tree/master/packages/typescript). However, they share a common set of mutators specified in this package. So this package defines a common set of specifications to which a mutator *could* conform. - -The specifications are written as mocha tests, so it's easy to run them inside your own build as part of *insert your custom mutator here*. Please take a look at stryker-typescript or stryker-javascript-mutator if you want to know how. \ No newline at end of file diff --git a/packages/mutator-specification/package.json b/packages/mutator-specification/package.json deleted file mode 100644 index ebc18b1f48..0000000000 --- a/packages/mutator-specification/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@stryker-mutator/mutator-specification", - "version": "3.3.1", - "description": "A package for maintaining common mutator specifications for Stryker - the JavaScript mutation testing framework", - "keywords": [ - "stryker" - ], - "publishConfig": { - "access": "public" - }, - "main": "src/index.js", - "author": "Nico Jansen ", - "repository": { - "type": "git", - "url": "https://github.com/stryker-mutator/stryker" - }, - "engines": { - "node": ">=10" - }, - "homepage": "https://github.com/stryker-mutator/stryker/tree/master/packages/javascript-mutator#readme", - "license": "Apache-2.0", - "devDependencies": { - "@types/node": "^14.0.1" - } -} diff --git a/packages/mutator-specification/src/ArithmeticOperatorMutatorSpec.ts b/packages/mutator-specification/src/ArithmeticOperatorMutatorSpec.ts deleted file mode 100644 index d6f232e639..0000000000 --- a/packages/mutator-specification/src/ArithmeticOperatorMutatorSpec.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { expect } from 'chai'; - -import ExpectMutation from './ExpectMutation'; - -export default function ArithmeticOperatorMutatorSpec(name: string, expectMutation: ExpectMutation) { - describe('ArithmeticOperatorMutator', () => { - it('should have name "ArithmeticOperator"', () => { - expect(name).eq('ArithmeticOperator'); - }); - - it('should mutate + and -', () => { - expectMutation('a + b', 'a - b'); - expectMutation('a - b', 'a + b'); - }); - - it('should mutate *, % and /', () => { - expectMutation('a * b', 'a / b'); - expectMutation('a / b', 'a * b'); - expectMutation('a % b', 'a * b'); - }); - }); -} diff --git a/packages/mutator-specification/src/ArrayDeclarationMutatorSpec.ts b/packages/mutator-specification/src/ArrayDeclarationMutatorSpec.ts deleted file mode 100644 index f5d2e2bfb8..0000000000 --- a/packages/mutator-specification/src/ArrayDeclarationMutatorSpec.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { expect } from 'chai'; - -import ExpectMutation from './ExpectMutation'; - -export default function ArrayDeclarationMutatorSpec(name: string, expectMutation: ExpectMutation) { - describe('ArrayDeclarationMutator', () => { - it('should have name "ArrayDeclaration"', () => { - expect(name).eq('ArrayDeclaration'); - }); - - it('should mutate filled array literals as empty arrays', () => { - expectMutation('[a, 1 + 1]', '[]'); - expectMutation("['val']", '[]'); - }); - - it('should mutate empty array literals as a filled array', () => { - expectMutation('[]', '["Stryker was here"]'); - }); - - it('should mutate filled Array constructor calls as empty arrays', () => { - expectMutation('new Array(a, 1 + 1)', 'new Array()'); - expectMutation("new Array('val')", 'new Array()'); - expectMutation("Array('val')", 'Array()'); - expectMutation('Array(a, 1 + 1)', 'Array()'); - }); - - it('should not mutate other new expressions', () => { - expectMutation('new Object(21, 2)'); - expectMutation('new Arrays(21, 2)'); - }); - - it('should mutate empty array constructor call as a filled array', () => { - expectMutation('new Array()', 'new Array([])'); - expectMutation('Array()', 'Array([])'); - }); - - it('should not mutate other function call expressions', () => { - expectMutation('window.Array(21, 2)'); - expectMutation('window["Array"](21, 2)'); - }); - }); -} diff --git a/packages/mutator-specification/src/ArrowFunctionMutatorSpec.ts b/packages/mutator-specification/src/ArrowFunctionMutatorSpec.ts deleted file mode 100644 index 3f27ae47a8..0000000000 --- a/packages/mutator-specification/src/ArrowFunctionMutatorSpec.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { expect } from 'chai'; - -import ExpectMutation from './ExpectMutation'; - -export default function ArrowFunctionMutatorSpec(name: string, expectMutation: ExpectMutation) { - describe('ArrowFunctionMutator', () => { - it('should have name "ArrowFunction"', () => { - expect(name).eq('ArrowFunction'); - }); - - it('should mutate an anonymous function with an inline return', () => { - expectMutation('const b = () => 4;', 'const b = () => undefined;'); - }); - - it('should not mutate an anonymous function with a block as a body', () => { - expectMutation('const b = () => { return 4; }'); - }); - }); -} diff --git a/packages/mutator-specification/src/BlockStatementMutatorSpec.ts b/packages/mutator-specification/src/BlockStatementMutatorSpec.ts deleted file mode 100644 index 71df981b6a..0000000000 --- a/packages/mutator-specification/src/BlockStatementMutatorSpec.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { expect } from 'chai'; - -import ExpectMutation from './ExpectMutation'; - -export default function BlockStatementMutatorSpec(name: string, expectMutation: ExpectMutation) { - describe('BlockStatementMutator', () => { - it('should have name "BlockStatement"', () => { - expect(name).eq('BlockStatement'); - }); - - it('should mutate the block of a function into an empty block', () => { - expectMutation('(function() { return 4; })', '(function() {})'); - }); - - it('should mutate a single block', () => { - expectMutation('const a = 3; { const b = a; }', 'const a = 3; {}'); - }); - - it('should not mutate an already empty block', () => { - expectMutation('(function() { })'); - }); - - it('should mutate the body of an anonymous function if defined as a block', () => { - expectMutation('const b = () => { return 4; }', 'const b = () => {}'); - }); - - it('should not mutate the body of an anonymous function if not defined as a block', () => { - expectMutation('const b = () => 4;'); - }); - - // switch/case tests - it('should not mutate the body of a switch or case statement, as not a block', () => { - expectMutation('switch (v) { case 42: a = "spam"; break; }'); - }); - - it('should mutate the body of a case statement if defined as a block', () => { - expectMutation('switch (v) { case 42: { a = "spam"; break; } }', 'switch (v) { case 42: {} }'); - }); - - // object tests - it('should not mutate an object declaration, as not a block', () => { - expectMutation('const o = { foo: "bar" }'); - }); - }); -} diff --git a/packages/mutator-specification/src/BooleanLiteralMutatorSpec.ts b/packages/mutator-specification/src/BooleanLiteralMutatorSpec.ts deleted file mode 100644 index 0935e87084..0000000000 --- a/packages/mutator-specification/src/BooleanLiteralMutatorSpec.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { expect } from 'chai'; - -import ExpectMutation from './ExpectMutation'; - -export default function BooleanLiteralMutatorSpec(name: string, expectMutation: ExpectMutation) { - describe('BooleanLiteralMutator', () => { - it('should have name "BooleanLiteral"', () => { - expect(name).eq('BooleanLiteral'); - }); - - it('should mutate `true` into `false`', () => { - expectMutation('true', 'false'); - }); - - it('should mutate `false` into `true`', () => { - expectMutation('false', 'true'); - }); - - it('should mutate !a to a', () => { - expectMutation('!a', 'a'); - }); - }); -} diff --git a/packages/mutator-specification/src/ConditionalExpressionMutatorSpec.ts b/packages/mutator-specification/src/ConditionalExpressionMutatorSpec.ts deleted file mode 100644 index 969ea28bf0..0000000000 --- a/packages/mutator-specification/src/ConditionalExpressionMutatorSpec.ts +++ /dev/null @@ -1,92 +0,0 @@ -import { expect } from 'chai'; - -import ExpectMutation from './ExpectMutation'; - -export default function ConditionalExpressionMutatorSpec(name: string, expectMutation: ExpectMutation) { - describe('ConditionalExpressionMutator', () => { - it('should have name "ConditionalExpression"', () => { - expect(name).eq('ConditionalExpression'); - }); - - it('should mutate ternary operator', () => { - expectMutation('a < 3? b : c', 'false? b : c', 'true? b : c'); - }); - - it('should mutate < and >', () => { - expectMutation('a < b', 'true', 'false'); - expectMutation('a > b', 'true', 'false'); - }); - - it('should mutate <= and >=', () => { - expectMutation('a <= b', 'true', 'false'); - expectMutation('a >= b', 'true', 'false'); - }); - - it('should mutate == and ===', () => { - expectMutation('a == b', 'true', 'false'); - expectMutation('a === b', 'true', 'false'); - }); - - it('should mutate != and !==', () => { - expectMutation('a != b', 'true', 'false'); - expectMutation('a !== b', 'true', 'false'); - }); - - it('should mutate && and ||', () => { - expectMutation('a && b', 'true', 'false'); - expectMutation('a || b', 'true', 'false'); - }); - - it('should not mutate + and -', () => { - expectMutation('a + b'); - expectMutation('a - b'); - }); - - it('should not mutate *, % and /', () => { - expectMutation('a * b'); - expectMutation('a / b'); - expectMutation('a % b'); - }); - - it('should not mutate assignments', () => { - expectMutation('let displayName; displayName = "Label";'); - }); - - it('should mutate the expression of a do statement', () => { - expectMutation('do { console.log(); } while(a < b);', 'do { console.log(); } while(false);'); - }); - - it('should mutate the condition of a for statement', () => { - expectMutation('for(let i=0;i<10; i++) { console.log(); }', 'for(let i=0;false; i++) { console.log(); }'); - }); - - it('should mutate the condition of a for statement without a condition', () => { - expectMutation('for(let i=0;; i++) { console.log(); }', 'for (let i = 0; false; i++) { console.log(); }'); - }); - - it('should mutate an expression to `true` and `false`', () => { - expectMutation('if (something) { a++ }', 'if (true) { a++ }', 'if (false) { a++ }'); - }); - - it('should remove all cases one at a time', () => { - expectMutation( - 'switch (v) {case 0: a = "foo"; case 1: a = "qux"; break; default: a = "spam";}', - 'switch (v) {case 0: case 1: a = "qux"; break; default: a = "spam";}', - 'switch (v) {case 0: a = "foo"; case 1: default: a = "spam";}', - 'switch (v) {case 0: a = "foo"; case 1: a = "qux"; break; default:}' - ); - }); - - it('should not mutate empty cases (0 consequent statements)', () => { - expectMutation( - 'switch (v) {case 0: case 1: break; default: a = "spam";}', - 'switch (v) {case 0: case 1: default: a = "spam";}', - 'switch (v) {case 0: case 1: break; default:}' - ); - }); - - it('should mutate the expression of a while statement', () => { - expectMutation('while(a < b) { console.log(); }', 'while(false) { console.log(); }'); - }); - }); -} diff --git a/packages/mutator-specification/src/EqualityOperatorMutatorSpec.ts b/packages/mutator-specification/src/EqualityOperatorMutatorSpec.ts deleted file mode 100644 index b82bb902a8..0000000000 --- a/packages/mutator-specification/src/EqualityOperatorMutatorSpec.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { expect } from 'chai'; - -import ExpectMutation from './ExpectMutation'; - -export default function EqualityOperatorMutatorSpec(name: string, expectMutation: ExpectMutation) { - describe('EqualityOperatorMutator', () => { - it('should have name "EqualityOperator"', () => { - expect(name).eq('EqualityOperator'); - }); - - it('should mutate < and >', () => { - expectMutation('a < b', 'a >= b', 'a <= b'); - expectMutation('a > b', 'a <= b', 'a >= b'); - }); - - it('should mutate <= and >=', () => { - expectMutation('a <= b', 'a < b', 'a > b'); - expectMutation('a >= b', 'a < b', 'a > b'); - }); - - it('should mutate == and ===', () => { - expectMutation('a == b', 'a != b'); - expectMutation('a === b', 'a !== b'); - }); - - it('should mutate != and !==', () => { - expectMutation('a != b', 'a == b'); - expectMutation('a !== b', 'a === b'); - }); - }); -} diff --git a/packages/mutator-specification/src/ExpectMutation.ts b/packages/mutator-specification/src/ExpectMutation.ts deleted file mode 100644 index 454e5547fb..0000000000 --- a/packages/mutator-specification/src/ExpectMutation.ts +++ /dev/null @@ -1,3 +0,0 @@ -type ExpectMutation = (originalCode: string, ...expectedMutations: string[]) => void; - -export default ExpectMutation; diff --git a/packages/mutator-specification/src/LogicalOperatorMutatorSpec.ts b/packages/mutator-specification/src/LogicalOperatorMutatorSpec.ts deleted file mode 100644 index 0e7c3ad244..0000000000 --- a/packages/mutator-specification/src/LogicalOperatorMutatorSpec.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { expect } from 'chai'; - -import ExpectMutation from './ExpectMutation'; - -export default function LogicalOperatorMutatorSpec(name: string, expectMutation: ExpectMutation) { - describe('LogicalOperatorMutator', () => { - it('should have name "LogicalOperator"', () => { - expect(name).eq('LogicalOperator'); - }); - - it('should mutate && and ||', () => { - expectMutation('a && b', 'a || b'); - expectMutation('a || b', 'a && b'); - }); - }); -} diff --git a/packages/mutator-specification/src/ObjectLiteralMutatorSpec.ts b/packages/mutator-specification/src/ObjectLiteralMutatorSpec.ts deleted file mode 100644 index 67457e6298..0000000000 --- a/packages/mutator-specification/src/ObjectLiteralMutatorSpec.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { expect } from 'chai'; - -import ExpectMutation from './ExpectMutation'; - -export default function ObjectLiteralMutatorSpec(name: string, expectMutation: ExpectMutation) { - describe('ObjectLiteralMutator', () => { - it('should have name "ObjectLiteral"', () => { - expect(name).eq('ObjectLiteral'); - }); - - it('should empty an object declaration', () => { - expectMutation('const o = { foo: "bar" }', 'const o = {}'); - }); - - it('should empty an object declaration of all properties', () => { - expectMutation('const o = { foo: "bar", baz: "qux" }', 'const o = {}'); - }); - - it('should empty string object keys', () => { - expectMutation('const o = { ["foo"]: "bar" }', 'const o = {}'); - }); - - it('shoud not mutate empty object declarations', () => { - expectMutation('const o = {}'); - }); - }); -} diff --git a/packages/mutator-specification/src/StringLiteralMutatorSpec.ts b/packages/mutator-specification/src/StringLiteralMutatorSpec.ts deleted file mode 100644 index 7cb6094036..0000000000 --- a/packages/mutator-specification/src/StringLiteralMutatorSpec.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { expect } from 'chai'; - -import ExpectMutation from './ExpectMutation'; - -export default function StringLiteralMutatorSpec(name: string, expectMutation: ExpectMutation) { - describe('StringLiteralMutator', () => { - it('should have name "StringLiteral"', () => { - expect(name).eq('StringLiteral'); - }); - - it('should mutate a string literal with double quotes', () => { - expectMutation('const b = "Hello world!";', 'const b = "";'); - }); - - it('should mutate a string literal with single quotes', () => { - expectMutation("const b = 'Hello world!';", 'const b = "";'); - }); - - it('should mutate a template string', () => { - expectMutation('const b = `Hello world!`;', 'const b = "";'); - }); - - it('should mutate a template string referencing another variable', () => { - expectMutation('const a = 10; const b = `${a} mutations`;', 'const a = 10; const b = "";'); - expectMutation('const a = 10; const b = `mutations: ${a}`;', 'const a = 10; const b = "";'); - expectMutation('const a = 10; const b = `mutations: ${a} out of 10`;', 'const a = 10; const b = "";'); - }); - - it('should mutate empty strings', () => { - expectMutation('const b = "";', 'const b = "Stryker was here!";'); - }); - - it('should mutate empty template strings', () => { - expectMutation('const b = ``;', 'const b = "Stryker was here!";'); - }); - - it('should not mutate import statements', () => { - expectMutation('import * as foo from "foo";'); - expectMutation('import { foo } from "foo";'); - expectMutation('import foo from "foo";'); - expectMutation('import "foo";'); - }); - - it('should not mutate export statements', () => { - expectMutation('export * from "./foo";'); - expectMutation('export { foo as boo } from "./foo";'); - }); - - it('should not mutate type declarations', () => { - expectMutation('const a: "hello" = "hello";', 'const a: "hello" = "";'); - expectMutation('const a: Record<"id", number> = { id: 10 }'); - }); - - it('should not mutate string JSX attributes', () => { - expectMutation(''); - }); - - it('should not mutate directive prologues', () => { - expectMutation('"use strict";"use asm";'); - expectMutation('function a() {"use strict";"use asm";}'); - }); - }); -} diff --git a/packages/mutator-specification/src/UnaryOperatorMutatorSpec.ts b/packages/mutator-specification/src/UnaryOperatorMutatorSpec.ts deleted file mode 100644 index e25fc552e1..0000000000 --- a/packages/mutator-specification/src/UnaryOperatorMutatorSpec.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { expect } from 'chai'; - -import ExpectMutation from './ExpectMutation'; - -export default function UnaryOperatorMutatorSpec(name: string, expectMutation: ExpectMutation) { - describe('UnaryOperatorMutator', () => { - it('should have name "UnaryOperator"', () => { - expect(name).eq('UnaryOperator'); - }); - - it('should mutate -a to +a', () => { - expectMutation('-a', '+a'); - }); - - it('should mutate +a to -a', () => { - expectMutation('+a', '-a'); - }); - - it('should mutate ~a to a', () => { - expectMutation('~a', 'a'); - }); - - it('should not mutate a+a', () => { - expectMutation('a+a'); - }); - - it('should not mutate a-a', () => { - expectMutation('a-a'); - }); - }); -} diff --git a/packages/mutator-specification/src/UpdateOperatorMutatorSpec.ts b/packages/mutator-specification/src/UpdateOperatorMutatorSpec.ts deleted file mode 100644 index f7ec5a4903..0000000000 --- a/packages/mutator-specification/src/UpdateOperatorMutatorSpec.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { expect } from 'chai'; - -import ExpectMutation from './ExpectMutation'; - -export default function UpdateOperatorMutatorSpec(name: string, expectMutation: ExpectMutation) { - describe('UpdateOperatorMutator', () => { - it('should have name "UpdateOperator"', () => { - expect(name).eq('UpdateOperator'); - }); - - it('should mutate a++ to a--', () => { - expectMutation('a++', 'a--'); - }); - - it('should mutate a-- to a++', () => { - expectMutation('a--', 'a++'); - }); - - it('should mutate ++a to --a', () => { - expectMutation('++a', '--a'); - }); - - it('should mutate --a to ++a', () => { - expectMutation('--a', '++a'); - }); - }); -} diff --git a/packages/mutator-specification/src/index.ts b/packages/mutator-specification/src/index.ts deleted file mode 100644 index f5f08ebdfd..0000000000 --- a/packages/mutator-specification/src/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -export { default as ArithmeticOperatorMutatorSpec } from './ArithmeticOperatorMutatorSpec'; -export { default as ArrayDeclarationMutatorSpec } from './ArrayDeclarationMutatorSpec'; -export { default as ArrowFunctionMutatorSpec } from './ArrowFunctionMutatorSpec'; -export { default as BlockStatementMutatorSpec } from './BlockStatementMutatorSpec'; -export { default as BooleanLiteralMutatorSpec } from './BooleanLiteralMutatorSpec'; -export { default as ConditionalExpressionMutatorSpec } from './ConditionalExpressionMutatorSpec'; -export { default as EqualityOperatorMutatorSpec } from './EqualityOperatorMutatorSpec'; -export { default as LogicalOperatorMutatorSpec } from './LogicalOperatorMutatorSpec'; -export { default as ObjectLiteralMutatorSpec } from './ObjectLiteralMutatorSpec'; -export { default as StringLiteralMutatorSpec } from './StringLiteralMutatorSpec'; -export { default as UnaryOperatorMutatorSpec } from './UnaryOperatorMutatorSpec'; -export { default as UpdateOperatorMutatorSpec } from './UpdateOperatorMutatorSpec'; diff --git a/packages/mutator-specification/tsconfig.json b/packages/mutator-specification/tsconfig.json deleted file mode 100644 index 050108a9da..0000000000 --- a/packages/mutator-specification/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "files": [], - "references": [ - { - "path": "./tsconfig.src.json" - } - ] -} \ No newline at end of file diff --git a/packages/mutator-specification/tsconfig.src.json b/packages/mutator-specification/tsconfig.src.json deleted file mode 100644 index 2e22b6f1ed..0000000000 --- a/packages/mutator-specification/tsconfig.src.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../tsconfig.settings.json", - "compilerOptions": { - "rootDir": ".", - "types": [ - "node", - "mocha" - ] - }, - "include": [ - "src" - ] -} \ No newline at end of file diff --git a/packages/test-helpers/CHANGELOG.md b/packages/test-helpers/CHANGELOG.md index 82bfd8088c..6dd967e1ea 100644 --- a/packages/test-helpers/CHANGELOG.md +++ b/packages/test-helpers/CHANGELOG.md @@ -3,6 +3,141 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [4.0.0-beta.10](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.9...v4.0.0-beta.10) (2020-10-05) + + +### Features + +* **instrumenter:** add excludedMutations support ([#2513](https://github.com/stryker-mutator/stryker/issues/2513)) ([bfd714f](https://github.com/stryker-mutator/stryker/commit/bfd714fe1b4f9c3b2468164a95d0c5bd0cbc8fcf)) + + + + + +# [4.0.0-beta.9](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.8...v4.0.0-beta.9) (2020-09-30) + +**Note:** Version bump only for package @stryker-mutator/test-helpers + + + + + +# [4.0.0-beta.8](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.7...v4.0.0-beta.8) (2020-09-22) + +**Note:** Version bump only for package @stryker-mutator/test-helpers + + + + + +# [4.0.0-beta.7](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.6...v4.0.0-beta.7) (2020-09-17) + +**Note:** Version bump only for package @stryker-mutator/test-helpers + + + + + +# [4.0.0-beta.6](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.5...v4.0.0-beta.6) (2020-09-10) + +**Note:** Version bump only for package @stryker-mutator/test-helpers + + + + + +# [4.0.0-beta.5](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.4...v4.0.0-beta.5) (2020-09-09) + + +### Features + +* **typescript:** Disable type checking ([#2446](https://github.com/stryker-mutator/stryker/issues/2446)) ([3ff996b](https://github.com/stryker-mutator/stryker/commit/3ff996b7516b7782434d86aa9aecbee334978a7f)), closes [#2438](https://github.com/stryker-mutator/stryker/issues/2438) + + + + + +# [4.0.0-beta.4](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.3...v4.0.0-beta.4) (2020-08-29) + + +### Bug Fixes + +* **input files:** support emojis in file names ([#2430](https://github.com/stryker-mutator/stryker/issues/2430)) ([139f9f3](https://github.com/stryker-mutator/stryker/commit/139f9f3ea9aa2349198cb824ceb444f7c6b013b6)) + + +### Features + +* **api:** rename test_runner2 -> test_runner ([#2442](https://github.com/stryker-mutator/stryker/issues/2442)) ([4d3ae97](https://github.com/stryker-mutator/stryker/commit/4d3ae9764dbd689c895b76e44f2eea76c82fabc8)) +* **options:** deprecate old stryker options ([#2395](https://github.com/stryker-mutator/stryker/issues/2395)) ([7c637c8](https://github.com/stryker-mutator/stryker/commit/7c637c8714169a03facd42a7521f7670b7606a32)) +* **reporter-api:** support mutation switching ([67f1ed5](https://github.com/stryker-mutator/stryker/commit/67f1ed52f4d17df4306362064180d267ed5445c7)) + + +### BREAKING CHANGES + +* **api:** Plugin creators should now use `'test_runner'` instead of `'test_runner2'`. +* **reporter-api:** The `onMutantTested` and `onAllMutantsTested` methods on the `Reporter` api have changed + + + + + +# [4.0.0-beta.3](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.2...v4.0.0-beta.3) (2020-08-19) + + +### Bug Fixes + +* **core:** exit process on error ([#2378](https://github.com/stryker-mutator/stryker/issues/2378)) ([af18a59](https://github.com/stryker-mutator/stryker/commit/af18a590fc916d75d54bcfaf2dda1d6a90bd4df8)), closes [#2315](https://github.com/stryker-mutator/stryker/issues/2315) + + +### Features + +* **core:** add ability to override file headers ([#2363](https://github.com/stryker-mutator/stryker/issues/2363)) ([430d6d3](https://github.com/stryker-mutator/stryker/commit/430d6d3d17fe2ad8e2cef3b858afa7efb86c2342)) +* **test runner api:** remove `sandboxFileNames` injectable values ([#2369](https://github.com/stryker-mutator/stryker/issues/2369)) ([92f3bf5](https://github.com/stryker-mutator/stryker/commit/92f3bf528d0b01be1f6c219b37a5f90da0431686)), closes [#2351](https://github.com/stryker-mutator/stryker/issues/2351) + + + + + +# [4.0.0-beta.2](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.1...v4.0.0-beta.2) (2020-08-07) + + +### Features + +* **command:** Support command test runner with mutation switching ([#2345](https://github.com/stryker-mutator/stryker/issues/2345)) ([59b1cfc](https://github.com/stryker-mutator/stryker/commit/59b1cfc06c4f8f5ec1e55dce4823e0f9c384b16c)) +* **jest-runner:** support mutation switching ([#2350](https://github.com/stryker-mutator/stryker/issues/2350)) ([9e6e6e0](https://github.com/stryker-mutator/stryker/commit/9e6e6e077731344ed0588d64b5c8ba2f19c8492e)) + + + + + +# [4.0.0-beta.1](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.0...v4.0.0-beta.1) (2020-07-17) + +**Note:** Version bump only for package @stryker-mutator/test-helpers + + + + + +# [4.0.0-beta.0](https://github.com/stryker-mutator/stryker/compare/v3.3.1...v4.0.0-beta.0) (2020-07-10) + + +### Features + +* **api:** add id to Mutant interface ([#2255](https://github.com/stryker-mutator/stryker/issues/2255)) ([cfc9053](https://github.com/stryker-mutator/stryker/commit/cfc90537d0b9815cba2b44b9681d171ca602766e)) +* **api:** remove support for options editors ([5e56d0e](https://github.com/stryker-mutator/stryker/commit/5e56d0ea6982faf11048c8ca4bbb912ee17e88eb)) +* **checker:** add checker api ([#2240](https://github.com/stryker-mutator/stryker/issues/2240)) ([d463f86](https://github.com/stryker-mutator/stryker/commit/d463f8639437c114da4fe30115652e8a470dd179)), closes [#1514](https://github.com/stryker-mutator/stryker/issues/1514) [#1980](https://github.com/stryker-mutator/stryker/issues/1980) +* **core:** add support for checker plugins ([#2285](https://github.com/stryker-mutator/stryker/issues/2285)) ([69358e1](https://github.com/stryker-mutator/stryker/commit/69358e1423701c730e29d303119a08d74081f340)) +* **jasmine-runner:** implement new test runner api ([#2256](https://github.com/stryker-mutator/stryker/issues/2256)) ([871db8c](https://github.com/stryker-mutator/stryker/commit/871db8c24c3389133d9b4476acd33b0ddd956a36)), closes [#2249](https://github.com/stryker-mutator/stryker/issues/2249) + + +### BREAKING CHANGES + +* **core:** * `--maxConcurrentTestRunners` is now deprecated. Please use `--concurrency` instead. + + + + + ## [3.3.1](https://github.com/stryker-mutator/stryker/compare/v3.3.0...v3.3.1) (2020-07-04) **Note:** Version bump only for package @stryker-mutator/test-helpers diff --git a/packages/test-helpers/package.json b/packages/test-helpers/package.json index 632f8a4c2f..3bf0d68b41 100644 --- a/packages/test-helpers/package.json +++ b/packages/test-helpers/package.json @@ -1,7 +1,7 @@ { "name": "@stryker-mutator/test-helpers", "private": true, - "version": "3.3.1", + "version": "4.0.0-beta.10", "description": "A helper package for testing", "main": "src/index.js", "scripts": {}, @@ -17,12 +17,12 @@ "homepage": "https://github.com/stryker-mutator/stryker/tree/master/packages/test-helpers#readme", "license": "ISC", "dependencies": { - "ajv": "^6.12.0", + "ajv": "~6.12.0", "mutation-testing-metrics": "~1.4.0" }, "devDependencies": { - "@stryker-mutator/api": "^3.3.1", + "@stryker-mutator/api": "4.0.0-beta.10", "@types/node": "^14.0.1", - "typed-inject": "~2.2.1" + "typed-inject": "~3.0.0" } } diff --git a/packages/test-helpers/src/TestInjector.ts b/packages/test-helpers/src/TestInjector.ts index 16e536be61..ab79a5787a 100644 --- a/packages/test-helpers/src/TestInjector.ts +++ b/packages/test-helpers/src/TestInjector.ts @@ -1,41 +1,26 @@ -import { MutatorDescriptor, StrykerOptions } from '@stryker-mutator/api/core'; +import { StrykerOptions } from '@stryker-mutator/api/core'; import { Logger } from '@stryker-mutator/api/logging'; -import { commonTokens, OptionsContext, PluginResolver } from '@stryker-mutator/api/plugin'; +import { commonTokens, PluginContext, PluginResolver } from '@stryker-mutator/api/plugin'; import * as sinon from 'sinon'; -import { Injector, rootInjector, Scope } from 'typed-inject'; +import { Injector, createInjector } from 'typed-inject'; import * as factory from './factory'; class TestInjector { - private readonly providePluginResolver = (): PluginResolver => { - return this.pluginResolver; - }; - private readonly provideLogger = (): Logger => { - return this.logger; - }; - private readonly provideOptions = () => { - return this.options; - }; - private readonly provideMutatorDescriptor = () => { - return this.mutatorDescriptor; - }; - public pluginResolver: sinon.SinonStubbedInstance; public options: StrykerOptions; - public mutatorDescriptor: MutatorDescriptor; public logger: sinon.SinonStubbedInstance; - public injector: Injector = rootInjector - .provideValue(commonTokens.getLogger, this.provideLogger) - .provideFactory(commonTokens.logger, this.provideLogger, Scope.Transient) - .provideFactory(commonTokens.options, this.provideOptions, Scope.Transient) - .provideFactory(commonTokens.pluginResolver, this.providePluginResolver, Scope.Transient) - .provideFactory(commonTokens.mutatorDescriptor, this.provideMutatorDescriptor, Scope.Transient); + public injector: Injector; public reset() { - this.mutatorDescriptor = factory.mutatorDescriptor(); this.options = factory.strykerOptions(); this.logger = factory.logger(); this.pluginResolver = factory.pluginResolver(); + this.injector = createInjector() + .provideValue(commonTokens.getLogger, () => this.logger) + .provideValue(commonTokens.logger, this.logger) + .provideValue(commonTokens.options, this.options) + .provideValue(commonTokens.pluginResolver, this.pluginResolver); } } diff --git a/packages/test-helpers/src/assertions.ts b/packages/test-helpers/src/assertions.ts new file mode 100644 index 0000000000..370b4076d8 --- /dev/null +++ b/packages/test-helpers/src/assertions.ts @@ -0,0 +1,61 @@ +import assert = require('assert'); + +import { expect } from 'chai'; + +import { + MutantRunResult, + SurvivedMutantRunResult, + ErrorDryRunResult, + KilledMutantRunResult, + MutantRunStatus, + DryRunResult, + CompleteDryRunResult, + DryRunStatus, + ErrorMutantRunResult, + TestResult, + FailedTestResult, + TestStatus, +} from '@stryker-mutator/api/test_runner'; +import { File } from '@stryker-mutator/api/core'; +import { CheckResult, FailedCheckResult, CheckStatus } from '@stryker-mutator/api/check'; + +export function expectKilled(result: MutantRunResult): asserts result is KilledMutantRunResult { + assert.equal(result.status, MutantRunStatus.Killed); +} + +export function expectFailed(result: TestResult): asserts result is FailedTestResult { + assert.equal(result.status, TestStatus.Failed); +} + +export function expectCompleted(runResult: DryRunResult): asserts runResult is CompleteDryRunResult { + assert.equal(runResult.status, DryRunStatus.Complete); +} + +export function expectCompileError(checkResult: CheckResult): asserts checkResult is FailedCheckResult { + assert.equal(checkResult.status, CheckStatus.CompileError); +} + +export function expectErrored(runResult: MutantRunResult): asserts runResult is ErrorMutantRunResult; +export function expectErrored(runResult: DryRunResult): asserts runResult is ErrorDryRunResult; +export function expectErrored(runResult: DryRunResult | MutantRunResult): asserts runResult is ErrorDryRunResult | MutantRunResult; +export function expectErrored(runResult: DryRunResult | MutantRunResult): void { + assert.equal(runResult.status, DryRunStatus.Error); +} +export function expectSurvived(runResult: MutantRunResult): asserts runResult is SurvivedMutantRunResult { + assert.equal(runResult.status, MutantRunStatus.Survived); +} + +export function expectTextFileEqual(actual: File, expected: File) { + expect(fileToJson(actual)).deep.eq(fileToJson(expected)); +} + +export function expectTextFilesEqual(actual: readonly File[], expected: readonly File[]) { + expect(actual.map(fileToJson)).deep.eq(expected.map(fileToJson)); +} + +function fileToJson(file: File) { + return { + name: file.name, + textContent: file.textContent, + }; +} diff --git a/packages/test-helpers/src/factory.ts b/packages/test-helpers/src/factory.ts index b96561c52d..b31f89bc48 100644 --- a/packages/test-helpers/src/factory.ts +++ b/packages/test-helpers/src/factory.ts @@ -1,25 +1,50 @@ import Ajv = require('ajv'); -import { ConfigEditor } from '@stryker-mutator/api/config'; import { File, Location, MutationScoreThresholds, StrykerOptions, - MutatorDescriptor, strykerCoreSchema, WarningOptions, + Mutant, + MutantCoverage, } from '@stryker-mutator/api/core'; import { Logger } from '@stryker-mutator/api/logging'; -import { Mutant } from '@stryker-mutator/api/mutant'; -import { MatchedMutant, MutantResult, MutantStatus, mutationTestReportSchema, Reporter } from '@stryker-mutator/api/report'; -import { TestFramework, TestSelection } from '@stryker-mutator/api/test_framework'; -import { RunResult, RunStatus, TestResult, TestStatus } from '@stryker-mutator/api/test_runner'; -import { Transpiler } from '@stryker-mutator/api/transpile'; +import { + MatchedMutant, + MutantStatus, + mutationTestReportSchema, + Reporter, + KilledMutantResult, + InvalidMutantResult, + UndetectedMutantResult, + TimeoutMutantResult, + IgnoredMutantResult, +} from '@stryker-mutator/api/report'; import { Metrics, MetricsResult } from 'mutation-testing-metrics'; import * as sinon from 'sinon'; import { Injector } from 'typed-inject'; -import { OptionsEditor } from '@stryker-mutator/api/src/core/OptionsEditor'; import { PluginResolver } from '@stryker-mutator/api/plugin'; +import { + MutantRunOptions, + DryRunOptions, + DryRunStatus, + TestRunner, + SuccessTestResult, + FailedTestResult, + SkippedTestResult, + CompleteDryRunResult, + ErrorDryRunResult, + TimeoutDryRunResult, + KilledMutantRunResult, + SurvivedMutantRunResult, + MutantRunStatus, + TimeoutMutantRunResult, + ErrorMutantRunResult, + TestStatus, + TestResult, +} from '@stryker-mutator/api/test_runner'; +import { Checker, CheckResult, CheckStatus, FailedCheckResult } from '@stryker-mutator/api/check'; const ajv = new Ajv({ useDefaults: true }); @@ -59,9 +84,10 @@ export function pluginResolver(): sinon.SinonStubbedInstance { export const warningOptions = factoryMethod(() => ({ unknownOptions: true, + preprocessorErrors: true, })); -export const mutantResult = factoryMethod(() => ({ +export const killedMutantResult = factoryMethod(() => ({ id: '256', location: location(), mutatedLines: '', @@ -69,9 +95,64 @@ export const mutantResult = factoryMethod(() => ({ originalLines: '', range: [0, 0], replacement: '', - sourceFilePath: 'file.js', + fileName: 'file.js', status: MutantStatus.Killed, - testsRan: [''], + killedBy: '', + nrOfTestsRan: 2, +})); +export const timeoutMutantResult = factoryMethod(() => ({ + id: '256', + location: location(), + mutatedLines: '', + mutatorName: '', + originalLines: '', + range: [0, 0], + replacement: '', + fileName: 'file.js', + status: MutantStatus.TimedOut, + nrOfTestsRan: 0, +})); + +export const invalidMutantResult = factoryMethod(() => ({ + id: '256', + location: location(), + mutatedLines: '', + mutatorName: '', + originalLines: '', + range: [0, 0], + replacement: '', + fileName: 'file.js', + status: MutantStatus.RuntimeError, + errorMessage: 'expected error', + nrOfTestsRan: 2, +})); + +export const ignoredMutantResult = factoryMethod(() => ({ + id: '256', + location: location(), + mutatedLines: '', + mutatorName: '', + originalLines: '', + range: [0, 0], + replacement: '', + fileName: 'file.js', + status: MutantStatus.Ignored, + ignoreReason: 'Ignored by "fooMutator" in excludedMutations', + nrOfTestsRan: 2, +})); + +export const undetectedMutantResult = factoryMethod(() => ({ + id: '256', + location: location(), + mutatedLines: '', + mutatorName: '', + originalLines: '', + range: [0, 0], + replacement: '', + fileName: 'file.js', + status: MutantStatus.NoCoverage, + testFilter: undefined, + nrOfTestsRan: 2, })); export const mutationTestReportSchemaMutantResult = factoryMethod(() => ({ @@ -105,9 +186,11 @@ export const mutationTestReportSchemaMutationTestResult = factoryMethod(() => ({ + id: 42, fileName: 'file', mutatorName: 'foobarMutator', range: [0, 0], + location: location(), replacement: 'replacement', })); @@ -152,29 +235,106 @@ export function logger(): sinon.SinonStubbedInstance { }; } -export function testFramework(): TestFramework { +export function testRunner(): sinon.SinonStubbedInstance> { return { - beforeEach(codeFragment: string) { - return `beforeEach(){ ${codeFragment}}`; - }, - afterEach(codeFragment: string) { - return `afterEach(){ ${codeFragment}}`; - }, - filter(selections: TestSelection[]) { - return `filter: ${selections}`; - }, + init: sinon.stub(), + dryRun: sinon.stub(), + mutantRun: sinon.stub(), + dispose: sinon.stub(), }; } +export function checker(): sinon.SinonStubbedInstance { + return { + check: sinon.stub(), + init: sinon.stub(), + }; +} + +export const checkResult = factoryMethod(() => ({ + status: CheckStatus.Passed, +})); + +export const failedCheckResult = factoryMethod(() => ({ + status: CheckStatus.CompileError, + reason: 'Cannot call "foo" of undefined', +})); + export const testResult = factoryMethod(() => ({ + id: 'spec1', name: 'name', status: TestStatus.Success, timeSpentMs: 10, })); +export const successTestResult = factoryMethod(() => ({ + id: 'spec1', + name: 'foo should be bar', + status: TestStatus.Success, + timeSpentMs: 32, +})); +export const failedTestResult = factoryMethod(() => ({ + id: 'spec2', + name: 'foo should be bar', + status: TestStatus.Failed, + timeSpentMs: 32, + failureMessage: 'foo was baz', +})); +export const skippedTestResult = factoryMethod(() => ({ + id: 'spec31', + status: TestStatus.Skipped, + timeSpentMs: 0, + name: 'qux should be quux', +})); + +export const mutantRunOptions = factoryMethod(() => ({ + activeMutant: mutant(), + timeout: 2000, + sandboxFileName: '.stryker-tmp/sandbox123/file', +})); + +export const dryRunOptions = factoryMethod(() => ({ + coverageAnalysis: 'off', + timeout: 2000, +})); + +export const completeDryRunResult = factoryMethod(() => ({ + status: DryRunStatus.Complete, + tests: [], +})); + +export const mutantCoverage = factoryMethod(() => ({ + perTest: {}, + static: {}, +})); + +export const errorDryRunResult = factoryMethod(() => ({ + status: DryRunStatus.Error, + errorMessage: 'example error', +})); + +export const timeoutDryRunResult = factoryMethod(() => ({ + status: DryRunStatus.Timeout, +})); + +export const killedMutantRunResult = factoryMethod(() => ({ + status: MutantRunStatus.Killed, + killedBy: 'spec1', + failureMessage: 'foo should be bar', + nrOfTests: 1, +})); + +export const survivedMutantRunResult = factoryMethod(() => ({ + status: MutantRunStatus.Survived, + nrOfTests: 2, +})); -export const runResult = factoryMethod(() => ({ - status: RunStatus.Complete, - tests: [testResult()], +export const timeoutMutantRunResult = factoryMethod(() => ({ + status: MutantRunStatus.Timeout, +})); + +export const errorMutantRunResult = factoryMethod(() => ({ + status: MutantRunStatus.Error, + errorMessage: 'Cannot find foo of undefined', })); export const mutationScoreThresholds = factoryMethod(() => ({ @@ -193,12 +353,6 @@ export const strykerWithPluginOptions = (pluginOptions: T): T & StrykerOption return { ...strykerOptions(), ...pluginOptions }; }; -export const mutatorDescriptor = factoryMethod(() => ({ - excludedMutations: [], - name: 'fooMutator', - plugins: null, -})); - export const ALL_REPORTER_EVENTS: Array = [ 'onSourceFileRead', 'onAllSourceFilesRead', @@ -215,38 +369,15 @@ export function reporter(name = 'fooReporter'): sinon.SinonStubbedInstance { - return { - edit: sinon.stub(), - }; -} -export function optionsEditor(): sinon.SinonStubbedInstance { - return { - edit: sinon.stub(), - }; -} - -export function transpiler(): sinon.SinonStubbedInstance { - return { - transpile: sinon.stub(), - }; -} - -export function matchedMutant(numberOfTests: number, mutantId = numberOfTests.toString(), runAllTests = false): MatchedMutant { - const scopedTestIds: number[] = []; - for (let i = 0; i < numberOfTests; i++) { - scopedTestIds.push(1); - } - return { - fileName: '', - id: mutantId, - mutatorName: '', - runAllTests, - replacement: '', - scopedTestIds, - timeSpentScopedTests: 0, - }; -} +export const matchedMutant = factoryMethod(() => ({ + testFilter: undefined, + fileName: '', + id: '1', + mutatorName: '', + runAllTests: false, + replacement: '', + timeSpentScopedTests: 0, +})); export function injector(): sinon.SinonStubbedInstance { const injectorMock: sinon.SinonStubbedInstance = { diff --git a/packages/test-helpers/src/index.ts b/packages/test-helpers/src/index.ts index b922c3037a..d23e437ff9 100644 --- a/packages/test-helpers/src/index.ts +++ b/packages/test-helpers/src/index.ts @@ -1,5 +1,5 @@ -import * as factory from './factory'; - +export * as factory from './factory'; +export * as assertions from './assertions'; export * from './TestInjector'; -export { factory }; export * from './LoggingServer'; +export * from './tick'; diff --git a/packages/test-helpers/src/tick.ts b/packages/test-helpers/src/tick.ts new file mode 100644 index 0000000000..d331cafa30 --- /dev/null +++ b/packages/test-helpers/src/tick.ts @@ -0,0 +1,12 @@ +import { promisify } from 'util'; + +/** + * Wait `n` ticks. This allows async tasks to progress. + * @param n The number of ticks to wait + */ +export async function tick(n = 1) { + const nextTickAsPromised = promisify(process.nextTick); + for await (const _ of Array.from({ length: n })) { + await nextTickAsPromised(); + } +} diff --git a/packages/typescript-checker/.eslintrc b/packages/typescript-checker/.eslintrc new file mode 100644 index 0000000000..7e107338ab --- /dev/null +++ b/packages/typescript-checker/.eslintrc @@ -0,0 +1,3 @@ +{ + "extends": "../../.eslintrc.js" +} \ No newline at end of file diff --git a/packages/typescript-checker/.mocharc.jsonc b/packages/typescript-checker/.mocharc.jsonc new file mode 100644 index 0000000000..8dedcc00ec --- /dev/null +++ b/packages/typescript-checker/.mocharc.jsonc @@ -0,0 +1,3 @@ +{ + "require": ["dist/test/setup.js"] +} diff --git a/packages/typescript-checker/.npmignore b/packages/typescript-checker/.npmignore new file mode 100644 index 0000000000..3fc43583d9 --- /dev/null +++ b/packages/typescript-checker/.npmignore @@ -0,0 +1,7 @@ +* + +!dist/src/**/*.js +!dist/src/**/*.map +!dist/src/**/*.ts +!src/**/* +!dist/schema/*.json diff --git a/packages/typescript-checker/.npmrc b/packages/typescript-checker/.npmrc new file mode 100644 index 0000000000..9cf9495031 --- /dev/null +++ b/packages/typescript-checker/.npmrc @@ -0,0 +1 @@ +package-lock=false \ No newline at end of file diff --git a/packages/typescript-checker/.nycrc.json b/packages/typescript-checker/.nycrc.json new file mode 100644 index 0000000000..97a046bc16 --- /dev/null +++ b/packages/typescript-checker/.nycrc.json @@ -0,0 +1,13 @@ +{ + "lines": 90, + "statements": 90, + "functions": 80, + "branches": 90, + "excludeAfterRemap": false, + "checkCoverage": true, + "reporter": ["text", "html"], + "reportDir": "reports/coverage", + "include": [ + "dist/src/**/*.js" + ] +} diff --git a/packages/typescript-checker/.vscode/launch.json b/packages/typescript-checker/.vscode/launch.json new file mode 100644 index 0000000000..cd597552b2 --- /dev/null +++ b/packages/typescript-checker/.vscode/launch.json @@ -0,0 +1,23 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Unit / Integration tests", + "program": "${workspaceRoot}/../../node_modules/mocha/bin/_mocha", + "internalConsoleOptions": "openOnSessionStart", + "outFiles": [ + "${workspaceRoot}/dist/**/*.js" + ], + "skipFiles": [ + "/**" + ], + "args": [ + "--no-timeout", + "dist/test/unit/**/*.js", + "dist/test/integration/**/*.js" + ] + } + ] +} diff --git a/packages/typescript-checker/CHANGELOG.md b/packages/typescript-checker/CHANGELOG.md new file mode 100644 index 0000000000..37b7cee1da --- /dev/null +++ b/packages/typescript-checker/CHANGELOG.md @@ -0,0 +1,107 @@ +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +# [4.0.0-beta.10](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.9...v4.0.0-beta.10) (2020-10-05) + +**Note:** Version bump only for package @stryker-mutator/typescript-checker + + + + + +# [4.0.0-beta.9](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.8...v4.0.0-beta.9) (2020-09-30) + +**Note:** Version bump only for package @stryker-mutator/typescript-checker + + + + + +# [4.0.0-beta.8](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.7...v4.0.0-beta.8) (2020-09-22) + +**Note:** Version bump only for package @stryker-mutator/typescript-checker + + + + + +# [4.0.0-beta.7](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.6...v4.0.0-beta.7) (2020-09-17) + +**Note:** Version bump only for package @stryker-mutator/typescript-checker + + + + + +# [4.0.0-beta.6](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.5...v4.0.0-beta.6) (2020-09-10) + +**Note:** Version bump only for package @stryker-mutator/typescript-checker + + + + + +# [4.0.0-beta.5](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.4...v4.0.0-beta.5) (2020-09-09) + +**Note:** Version bump only for package @stryker-mutator/typescript-checker + + + + + +# [4.0.0-beta.4](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.3...v4.0.0-beta.4) (2020-08-29) + +**Note:** Version bump only for package @stryker-mutator/typescript-checker + + + + + +# [4.0.0-beta.3](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.2...v4.0.0-beta.3) (2020-08-19) + + +### Features + +* **core:** strip comments in sandbox ([#2365](https://github.com/stryker-mutator/stryker/issues/2365)) ([55f27f2](https://github.com/stryker-mutator/stryker/commit/55f27f29b6994096c9aad038958ee93e9fa0f035)), closes [#2364](https://github.com/stryker-mutator/stryker/issues/2364) +* **test runner api:** remove `sandboxFileNames` injectable values ([#2369](https://github.com/stryker-mutator/stryker/issues/2369)) ([92f3bf5](https://github.com/stryker-mutator/stryker/commit/92f3bf528d0b01be1f6c219b37a5f90da0431686)), closes [#2351](https://github.com/stryker-mutator/stryker/issues/2351) + + + + + +# [4.0.0-beta.2](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.1...v4.0.0-beta.2) (2020-08-07) + +**Note:** Version bump only for package @stryker-mutator/typescript-checker + + + + + +# [4.0.0-beta.1](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.0...v4.0.0-beta.1) (2020-07-17) + +**Note:** Version bump only for package @stryker-mutator/typescript-checker + + + + + +# [4.0.0-beta.0](https://github.com/stryker-mutator/stryker/compare/v3.3.1...v4.0.0-beta.0) (2020-07-10) + + +### Bug Fixes + +* **typescript-checker:** support empty files ([#2310](https://github.com/stryker-mutator/stryker/issues/2310)) ([284a28c](https://github.com/stryker-mutator/stryker/commit/284a28cbe831ad4c4ed161f2d700fa88663120ca)) + + +### Features + +* **core:** add support for checker plugins ([#2285](https://github.com/stryker-mutator/stryker/issues/2285)) ([69358e1](https://github.com/stryker-mutator/stryker/commit/69358e1423701c730e29d303119a08d74081f340)) +* **tsconfig:** rewrite tsconfig references ([#2292](https://github.com/stryker-mutator/stryker/issues/2292)) ([4ee4950](https://github.com/stryker-mutator/stryker/commit/4ee4950bebd8db9c2f5a514edee57de55c040526)), closes [#2276](https://github.com/stryker-mutator/stryker/issues/2276) +* **typescript-checker:** a typescript type checker plugin ([#2241](https://github.com/stryker-mutator/stryker/issues/2241)) ([42adb95](https://github.com/stryker-mutator/stryker/commit/42adb9561cdd10172f955fda044854bcc1b7b515)), closes [/github.com/stryker-mutator/stryker/blob/f44008993a543dc3f38ca99516f56d315fdcb735/packages/typescript/src/transpiler/TranspilingLanguageService.ts#L23](https://github.com//github.com/stryker-mutator/stryker/blob/f44008993a543dc3f38ca99516f56d315fdcb735/packages/typescript/src/transpiler/TranspilingLanguageService.ts/issues/L23) [#391](https://github.com/stryker-mutator/stryker/issues/391) + + +### BREAKING CHANGES + +* **core:** * `--maxConcurrentTestRunners` is now deprecated. Please use `--concurrency` instead. diff --git a/packages/typescript-checker/README.md b/packages/typescript-checker/README.md new file mode 100644 index 0000000000..4f1e57377e --- /dev/null +++ b/packages/typescript-checker/README.md @@ -0,0 +1,82 @@ +**NOTE:** This readme describes a checker plugin set to release in Stryker v4. It is not usable yet! +Please see the [master branch](https://github.com/stryker-mutator/stryker/tree/master) for the current release of Stryker. + +[![Mutation testing badge](https://img.shields.io/endpoint?style=flat&url=https%3A%2F%2Fbadge-api.stryker-mutator.io%2Fgithub.com%2Fstryker-mutator%2Fstryker%2Fmaster%3Fmodule%3Dtypescript)](https://dashboard.stryker-mutator.io/reports/github.com/stryker-mutator/stryker/master?module=typescript-checker) +[![Build Status](https://github.com/stryker-mutator/stryker/workflows/CI/badge.svg)](https://github.com/stryker-mutator/stryker/actions?query=workflow%3ACI+branch%3Amaster) +[![NPM](https://img.shields.io/npm/dm/@stryker-mutator/typescript-checker.svg)](https://www.npmjs.com/package/@stryker-mutator/typescript-checker) +[![Node version](https://img.shields.io/node/v/@stryker-mutator/typescript.svg)](https://img.shields.io/node/v/@stryker-mutator/typescript-checker.svg) +[![Slack Chat](https://img.shields.io/badge/slack-chat-brightgreen.svg?logo=slack)](https://join.slack.com/t/stryker-mutator/shared_invite/enQtOTUyMTYyNTg1NDQ0LTU4ODNmZDlmN2I3MmEyMTVhYjZlYmJkOThlNTY3NTM1M2QxYmM5YTM3ODQxYmJjY2YyYzllM2RkMmM1NjNjZjM) + +![Stryker](https://github.com/stryker-mutator/stryker/raw/master/stryker-80x80.png) + +# Typescript checker + +A TypeScript type checker plugin for [Stryker](https://stryker-mutator.io), the ~~JavaScript~~ _TypeScript_ Mutation testing framework. +This plugin enables type checking on mutants, so you won't have to waste time on mutants which results in a type error. + +## Features + +👽 Type check each mutant. Invalid mutants will be marked as `CompileError` in your Stryker report. +🧒 Easy to setup, only your `tsconfig.json` file is needed. +🔢 Type check is done in-memory, no side effects on disk. +🎁 Support for both single typescript projects as well as projects with project references (`--build` mode). + +## Install + +First, install Stryker itself (you can follow the [quickstart on the website](https://stryker-mutator.io/quickstart.html)) + +Next, install this package: + +```bash +npm install --save-dev @stryker-mutator/typescript-checker +``` + +## Configuring + +You can configure the typescript checker in the `stryker.conf.js` (or `stryker.conf.json`) file. + +```js +// stryker.conf.json +{ + "checkers": ["typescript"], + "tsconfigFile": "tsconfig.json" +} +``` + +### `tsconfigFile` [`string`] + +Default: `'tsconfig.json'` + +The path to your [tsconfig](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html). Project references _are supported_, `--build` mode will be enabled automatically when references are found in your tsconfig.json file. + +_Note: the following compiler options are always overridden by @stryker-mutator/typescript-checker to ovoid false positives. See [issue 391](https://github.com/stryker-mutator/stryker/issues/391#issue-259829320) for more information on this_ + +```json +{ + "compilerOptions": { + "allowUnreachableCode": true, + "noUnusedLocals": false, + "noUnusedParameters": false + } +} +``` + +## Peer dependencies + +The `@stryker-mutator/typescript-checker` package for `stryker` to enable `typescript` support. As such, you should make sure you have the correct versions of its dependencies installed: + +- `typescript` +- `@stryker-mutator/core` + +For the current versions, see the `peerDependencies` section in the [package.json](https://github.com/stryker-mutator/stryker/blob/master/packages/typescript/package.json). + +## Troubleshooting + + + +## Load the plugin + +In this plugin the `@stryker-mutator/typescript-checker`' must be loaded into Stryker. +The easiest way to achieve this, is _not have a `plugins` section_ in your config file. That way, all plugins starting with `"@stryker-mutator/"` will be loaded. + +If you do decide to choose specific modules, don't forget to add `"@stryker-mutator/typescript-checker"` to the list of plugins to load. diff --git a/packages/typescript-checker/package.json b/packages/typescript-checker/package.json new file mode 100644 index 0000000000..719aaa6f65 --- /dev/null +++ b/packages/typescript-checker/package.json @@ -0,0 +1,48 @@ +{ + "name": "@stryker-mutator/typescript-checker", + "version": "4.0.0-beta.10", + "description": "A typescript type checker plugin to be used in Stryker, the JavaScript mutation testing framework", + "main": "dist/src/index.js", + "scripts": { + "test": "nyc npm run test:all", + "mocha": "mocha", + "test:all": "npm run test:unit && npm run test:integration", + "test:unit": "mocha 'dist/test/unit/**/*.js'", + "test:integration": "mocha --timeout 10000 'dist/test/integration/**/*.js'", + "stryker": "node ../core/bin/stryker run" + }, + "repository": { + "type": "git", + "url": "https://github.com/stryker-mutator/stryker", + "directory": "packages/typescript-checker" + }, + "engines": { + "node": ">=10" + }, + "publishConfig": { + "access": "public" + }, + "author": "Nico Jansen ", + "contributors": [ + "Simon de Lang ", + "Nico Jansen " + ], + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/stryker-mutator/stryker/issues" + }, + "homepage": "https://stryker-mutator.io", + "dependencies": { + "@stryker-mutator/api": "4.0.0-beta.10", + "@stryker-mutator/util": "4.0.0-beta.10", + "semver": "~7.3.2" + }, + "devDependencies": { + "@stryker-mutator/test-helpers": "4.0.0-beta.10", + "@types/semver": "~7.3.3" + }, + "peerDependencies": { + "@stryker-mutator/core": "~4.0.0", + "typescript": ">=3.6" + } +} diff --git a/packages/typescript-checker/src/fs/hybrid-file-system.ts b/packages/typescript-checker/src/fs/hybrid-file-system.ts new file mode 100644 index 0000000000..478db7ce2b --- /dev/null +++ b/packages/typescript-checker/src/fs/hybrid-file-system.ts @@ -0,0 +1,76 @@ +import ts from 'typescript'; +import { Mutant } from '@stryker-mutator/api/core'; +import { Logger } from '@stryker-mutator/api/logging'; +import { tokens, commonTokens } from '@stryker-mutator/api/plugin'; + +import { ScriptFile } from './script-file'; + +function toTSFileName(fileName: string) { + return fileName.replace(/\\/g, '/'); +} + +/** + * A very simple hybrid file system. + * * Readonly from disk + * * Writes in-memory + * * Hard caching + * * Ability to mutate one file + */ +export class HybridFileSystem { + private readonly files = new Map(); + private mutatedFile: ScriptFile | undefined; + + public static inject = tokens(commonTokens.logger); + constructor(private readonly log: Logger) {} + + public writeFile(fileName: string, data: string) { + fileName = toTSFileName(fileName); + const existingFile = this.files.get(fileName); + if (existingFile) { + existingFile.write(data); + } else { + this.log.trace('Writing to file "%s"', fileName); + this.files.set(fileName, new ScriptFile(data, fileName)); + } + } + + public mutate(mutant: Pick) { + const fileName = toTSFileName(mutant.fileName); + const file = this.files.get(fileName); + if (!file) { + throw new Error(`File "${mutant.fileName}" cannot be found.`); + } + if (this.mutatedFile && this.mutatedFile !== file) { + this.mutatedFile.resetMutant(); + } + file.mutate(mutant); + this.mutatedFile = file; + } + + public watchFile(fileName: string, watcher: ts.FileWatcherCallback) { + const file = this.getFile(fileName); + if (!file) { + throw new Error(`Cannot find file ${fileName} for watching`); + } + this.log.trace('Registering watcher for file "%s"', fileName); + file.watcher = watcher; + } + + public getFile(fileName: string): ScriptFile | undefined { + fileName = toTSFileName(fileName); + if (!this.files.has(fileName)) { + let content = ts.sys.readFile(fileName); + if (typeof content === 'string') { + let modifiedTime = ts.sys.getModifiedTime!(fileName)!; + this.files.set(fileName, new ScriptFile(content, fileName, modifiedTime)); + } else { + this.files.set(fileName, undefined); + } + } + return this.files.get(fileName); + } + + public existsInMemory(fileName: string): boolean { + return !!this.files.get(toTSFileName(fileName)); + } +} diff --git a/packages/typescript-checker/src/fs/index.ts b/packages/typescript-checker/src/fs/index.ts new file mode 100644 index 0000000000..a338212607 --- /dev/null +++ b/packages/typescript-checker/src/fs/index.ts @@ -0,0 +1 @@ +export * from './hybrid-file-system'; diff --git a/packages/typescript-checker/src/fs/script-file.ts b/packages/typescript-checker/src/fs/script-file.ts new file mode 100644 index 0000000000..f1404dd6e6 --- /dev/null +++ b/packages/typescript-checker/src/fs/script-file.ts @@ -0,0 +1,42 @@ +import ts from 'typescript'; +import { Mutant } from '@stryker-mutator/api/core'; +import { FileWatcherCallback } from 'typescript'; + +export class ScriptFile { + private readonly originalContent: string; + constructor(public content: string, public fileName: string, public modifiedTime = new Date()) { + this.originalContent = content; + } + + public write(content: string) { + this.content = content; + this.touch(); + } + + public watcher: FileWatcherCallback | undefined; + + public mutate(mutant: Pick) { + this.guardMutationIsWatched(); + this.content = `${this.originalContent.substr(0, mutant.range[0])}${mutant.replacement}${this.originalContent.substr(mutant.range[1])}`; + this.touch(); + } + + public resetMutant() { + this.guardMutationIsWatched(); + this.content = this.originalContent; + this.touch(); + } + + private guardMutationIsWatched() { + if (!this.watcher) { + throw new Error( + `Tried to check file "${this.fileName}" (which is part of your typescript project), but no watcher is registered for it. Changes would go unnoticed. This probably means that you need to expand the files that are included in your project.` + ); + } + } + + private touch() { + this.modifiedTime = new Date(); + this.watcher?.(this.fileName, ts.FileWatcherEventKind.Changed); + } +} diff --git a/packages/typescript-checker/src/index.ts b/packages/typescript-checker/src/index.ts new file mode 100644 index 0000000000..cd56925f45 --- /dev/null +++ b/packages/typescript-checker/src/index.ts @@ -0,0 +1,7 @@ +import { PluginKind, declareFactoryPlugin } from '@stryker-mutator/api/plugin'; + +import { create } from './typescript-checker'; + +export const strykerPlugins = [declareFactoryPlugin(PluginKind.Checker, 'typescript', create)]; + +export const createTypescriptChecker = create; diff --git a/packages/typescript-checker/src/plugin-tokens.ts b/packages/typescript-checker/src/plugin-tokens.ts new file mode 100644 index 0000000000..ecb64f9a01 --- /dev/null +++ b/packages/typescript-checker/src/plugin-tokens.ts @@ -0,0 +1 @@ +export const fs = 'fs'; diff --git a/packages/typescript-checker/src/tsconfig-helpers.ts b/packages/typescript-checker/src/tsconfig-helpers.ts new file mode 100644 index 0000000000..a9ecd4d0f6 --- /dev/null +++ b/packages/typescript-checker/src/tsconfig-helpers.ts @@ -0,0 +1,74 @@ +import { resolve } from 'path'; + +import ts from 'typescript'; +import semver from 'semver'; + +// Override some compiler options that have to do with code quality. When mutating, we're not interested in the resulting code quality +// See https://github.com/stryker-mutator/stryker/issues/391 for more info +const COMPILER_OPTIONS_OVERRIDES: Readonly> = Object.freeze({ + allowUnreachableCode: true, + noUnusedLocals: false, + noUnusedParameters: false, +}); + +// When we're running in 'single-project' mode, we can safely disable emit +const NO_EMIT_OPTIONS_FOR_SINGLE_PROJECT: Readonly> = Object.freeze({ + noEmit: true, + incremental: false, // incremental and composite off: https://github.com/microsoft/TypeScript/issues/36917 + composite: false, + declaration: false, +}); + +// When we're running in 'project references' mode, we need to enable declaration output +const LOW_EMIT_OPTIONS_FOR_PROJECT_REFERENCES: Readonly> = Object.freeze({ + emitDeclarationOnly: true, + noEmit: false, + declarationMap: false, +}); + +export function guardTSVersion() { + if (!semver.satisfies(ts.version, '>=3.6')) { + throw new Error(`@stryker-mutator/typescript-checker only supports typescript@3.6 our higher. Found typescript@${ts.version}`); + } +} + +/** + * Determines whether or not to use `--build` mode based on "references" being there in the config file + * @param tsconfigFileName The tsconfig file to parse + */ +export function determineBuildModeEnabled(tsconfigFileName: string) { + const tsconfigFile = ts.sys.readFile(tsconfigFileName); + if (!tsconfigFile) { + throw new Error(`File "${tsconfigFileName}" not found!`); + } + const useProjectReferences = 'references' in ts.parseConfigFileTextToJson(tsconfigFileName, tsconfigFile).config; + return useProjectReferences; +} + +/** + * Overrides some options to speed up compilation and disable some code quality checks we don't want during mutation testing + * @param parsedConfig The parsed config file + * @param useBuildMode whether or not `--build` mode is used + */ +export function overrideOptions(parsedConfig: { config?: any }, useBuildMode: boolean) { + const config = { + ...parsedConfig.config, + compilerOptions: { + ...parsedConfig.config?.compilerOptions, + ...COMPILER_OPTIONS_OVERRIDES, + ...(useBuildMode ? LOW_EMIT_OPTIONS_FOR_PROJECT_REFERENCES : NO_EMIT_OPTIONS_FOR_SINGLE_PROJECT), + }, + }; + return JSON.stringify(config); +} + +/** + * Retrieves the referenced config files based on parsed configuration + * @param parsedConfig The parsed config file + */ +export function retrieveReferencedProjects(parsedConfig: { config?: any }): string[] { + if (Array.isArray(parsedConfig.config?.references)) { + return parsedConfig.config?.references.map((reference: any) => resolve(ts.resolveProjectReferencePath(reference))); + } + return []; +} diff --git a/packages/typescript-checker/src/tsconfig.json b/packages/typescript-checker/src/tsconfig.json new file mode 100644 index 0000000000..72cd608aa5 --- /dev/null +++ b/packages/typescript-checker/src/tsconfig.json @@ -0,0 +1,22 @@ +{ + "extends": "../../../tsconfig.settings.json", + "compilerOptions": { + "outDir": "../dist", + "rootDir": "..", + "esModuleInterop": true, + "resolveJsonModule": true, + "noImplicitThis": true, + "types": [ + "node" + ], + }, + "references": [ + { + "path": "../../api/tsconfig.src.json" + }, + { + "path": "../../util/tsconfig.src.json" + } + ], + "include": ["**/*.ts", "../src-generated/**/*.ts", "../schema/typescript-checker-options.json"] +} diff --git a/packages/typescript-checker/src/typescript-checker.ts b/packages/typescript-checker/src/typescript-checker.ts new file mode 100644 index 0000000000..b9ff390910 --- /dev/null +++ b/packages/typescript-checker/src/typescript-checker.ts @@ -0,0 +1,200 @@ +import { EOL } from 'os'; +import path from 'path'; + +import ts from 'typescript'; +import { Checker, CheckResult, CheckStatus } from '@stryker-mutator/api/check'; +import { tokens, commonTokens, PluginContext, Injector, Scope } from '@stryker-mutator/api/plugin'; +import { Logger, LoggerFactoryMethod } from '@stryker-mutator/api/logging'; +import { Task, propertyPath } from '@stryker-mutator/util'; +import { Mutant, StrykerOptions } from '@stryker-mutator/api/core'; + +import { HybridFileSystem } from './fs'; +import { determineBuildModeEnabled, overrideOptions, retrieveReferencedProjects, guardTSVersion } from './tsconfig-helpers'; +import * as pluginTokens from './plugin-tokens'; + +const diagnosticsHost: ts.FormatDiagnosticsHost = { + getCanonicalFileName: (fileName) => fileName, + getCurrentDirectory: process.cwd, + getNewLine: () => EOL, +}; + +const FILE_CHANGE_DETECTED_DIAGNOSTIC_CODE = 6032; + +typescriptCheckerLoggerFactory.inject = tokens(commonTokens.getLogger, commonTokens.target); +// eslint-disable-next-line @typescript-eslint/ban-types +function typescriptCheckerLoggerFactory(loggerFactory: LoggerFactoryMethod, target: Function | undefined) { + const targetName = target?.name ?? TypescriptChecker.name; + const category = targetName === TypescriptChecker.name ? TypescriptChecker.name : `${TypescriptChecker.name}.${targetName}`; + return loggerFactory(category); +} + +create.inject = tokens(commonTokens.injector); +export function create(injector: Injector): TypescriptChecker { + return injector + .provideFactory(commonTokens.logger, typescriptCheckerLoggerFactory, Scope.Transient) + .provideClass(pluginTokens.fs, HybridFileSystem) + .injectClass(TypescriptChecker); +} + +/** + * An in-memory type checker implementation which validates type errors of mutants. + */ +export class TypescriptChecker implements Checker { + private currentTask: Task; + private readonly currentErrors: ts.Diagnostic[] = []; + /** + * Keep track of all tsconfig files which are read during compilation (for project references) + */ + private readonly allTSConfigFiles: Set; + + public static inject = tokens(commonTokens.logger, commonTokens.options, pluginTokens.fs); + private readonly tsconfigFile: string; + + constructor(private readonly logger: Logger, options: StrykerOptions, private readonly fs: HybridFileSystem) { + this.tsconfigFile = options.tsconfigFile; + this.allTSConfigFiles = new Set([path.resolve(this.tsconfigFile)]); + } + + /** + * Starts the typescript compiler and does a dry run + */ + public async init(): Promise { + guardTSVersion(); + this.guardTSConfigFileExists(); + this.currentTask = new Task(); + const buildModeEnabled = determineBuildModeEnabled(this.tsconfigFile); + const compiler = ts.createSolutionBuilderWithWatch( + ts.createSolutionBuilderWithWatchHost( + { + ...ts.sys, + readFile: (fileName) => { + const content = this.fs.getFile(fileName)?.content; + if (content && this.allTSConfigFiles.has(path.resolve(fileName))) { + return this.adjustTSConfigFile(fileName, content, buildModeEnabled); + } + return content; + }, + watchFile: (path: string, callback: ts.FileWatcherCallback) => { + this.fs.watchFile(path, callback); + return { + close: () => { + delete this.fs.getFile(path)!.watcher; + }, + }; + }, + writeFile: (path, data) => { + this.fs.writeFile(path, data); + }, + createDirectory: () => { + // Idle, no need to create directories in the hybrid fs + }, + clearScreen() { + // idle, never clear the screen + }, + getModifiedTime: (fileName) => { + return this.fs.getFile(fileName)!.modifiedTime; + }, + watchDirectory: (): ts.FileWatcher => { + // this is used to see if new files are added to a directory. Can safely be ignored for mutation testing. + return { + close() {}, + }; + }, + }, + undefined, + (error) => this.currentErrors.push(error), + (status) => this.logDiagnostic('status')(status), + (summary) => { + this.logDiagnostic('summary')(summary); + summary.code !== FILE_CHANGE_DETECTED_DIAGNOSTIC_CODE && this.resolveCheckResult(); + } + ), + [this.tsconfigFile], + {} + ); + compiler.build(); + const result = await this.currentTask.promise; + if (result.status === CheckStatus.CompileError) { + throw new Error(`TypeScript error(s) found in dry run compilation: ${result.reason}`); + } + } + + private guardTSConfigFileExists() { + if (!ts.sys.fileExists(this.tsconfigFile)) { + throw new Error( + `The tsconfig file does not exist at: "${path.resolve( + this.tsconfigFile + )}". Please configure the tsconfig file in your stryker.conf file using "${propertyPath('tsconfigFile')}"` + ); + } + } + + /** + * Checks whether or not a mutant results in a compile error. + * Will simply pass through if the file mutated isn't part of the typescript project + * @param mutant The mutant to check + */ + public async check(mutant: Mutant): Promise { + if (this.fs.existsInMemory(mutant.fileName)) { + this.clearCheckState(); + this.fs.mutate(mutant); + return this.currentTask.promise; + } else { + // We allow people to mutate files that are not included in this ts project + return { + status: CheckStatus.Passed, + }; + } + } + + /** + * Post processes the content of a tsconfig file. Adjusts some options for speed and alters quality options. + * @param fileName The tsconfig file name + * @param content The tsconfig content + * @param buildModeEnabled Whether or not `--build` mode is used + */ + private adjustTSConfigFile(fileName: string, content: string, buildModeEnabled: boolean) { + const parsedConfig = ts.parseConfigFileTextToJson(fileName, content); + if (parsedConfig.error) { + return content; // let the ts compiler deal with this error + } else { + for (const referencedProject of retrieveReferencedProjects(parsedConfig)) { + this.allTSConfigFiles.add(referencedProject); + } + return overrideOptions(parsedConfig, buildModeEnabled); + } + } + + /** + * Resolves the task that is currently running. Will report back the check result. + */ + private resolveCheckResult(): void { + if (this.currentErrors.length) { + const errorText = ts.formatDiagnostics(this.currentErrors, { + getCanonicalFileName: (fileName) => fileName, + getCurrentDirectory: process.cwd, + getNewLine: () => EOL, + }); + this.currentTask.resolve({ + status: CheckStatus.CompileError, + reason: errorText, + }); + } + this.currentTask.resolve({ status: CheckStatus.Passed }); + } + + /** + * Clear state between checks + */ + private clearCheckState() { + while (this.currentErrors.pop()) { + // Idle + } + this.currentTask = new Task(); + } + private readonly logDiagnostic = (label: string) => { + return (d: ts.Diagnostic) => { + this.logger.trace(`${label} ${ts.formatDiagnostics([d], diagnosticsHost)}`); + }; + }; +} diff --git a/packages/typescript-checker/stryker.conf.js b/packages/typescript-checker/stryker.conf.js new file mode 100644 index 0000000000..e00d510b33 --- /dev/null +++ b/packages/typescript-checker/stryker.conf.js @@ -0,0 +1,7 @@ +const path = require('path'); +const settings = require('../../stryker.parent.conf'); +const moduleName = __dirname.split(path.sep).pop(); +settings.plugins = settings.plugins.map(p => path.resolve(p)); +settings.mochaOptions.spec = ['dist/test/**/*.js']; +settings.dashboard.module = moduleName; +module.exports = settings; diff --git a/packages/typescript-checker/test/integration/project-references.it.spec.ts b/packages/typescript-checker/test/integration/project-references.it.spec.ts new file mode 100644 index 0000000000..165dcedb07 --- /dev/null +++ b/packages/typescript-checker/test/integration/project-references.it.spec.ts @@ -0,0 +1,72 @@ +import path from 'path'; +import fs from 'fs'; + +import { expect } from 'chai'; +import { Mutant, Range } from '@stryker-mutator/api/core'; +import { CheckResult, CheckStatus } from '@stryker-mutator/api/check'; +import { testInjector, factory } from '@stryker-mutator/test-helpers'; + +import { createTypescriptChecker } from '../../src'; +import { TypescriptChecker } from '../../src/typescript-checker'; + +const resolveTestResource = (path.resolve.bind( + path, + __dirname, + '..' /* integration */, + '..' /* test */, + '..' /* dist */, + 'testResources', + 'project-references' +) as unknown) as typeof path.resolve; + +describe('Typescript checker on a project with project references', () => { + let sut: TypescriptChecker; + + beforeEach(() => { + process.chdir(resolveTestResource()); + testInjector.options.tsconfigFile = 'tsconfig.root.json'; + sut = testInjector.injector.injectFunction(createTypescriptChecker); + return sut.init(); + }); + + it('should not write output to disk', () => { + expect(fs.existsSync(resolveTestResource('dist')), 'Output was written to disk!').false; + }); + + it('should be able to validate a mutant', async () => { + const mutant = createMutant('src/todo.ts', 'TodoList.allTodos.push(newItem)', 'newItem ? 42 : 43'); + const expectedResult: CheckResult = { + status: CheckStatus.Passed, + }; + const actualResult = await sut.check(mutant); + expect(actualResult).deep.eq(expectedResult); + }); + + it('should allow unused local variables (override options)', async () => { + const mutant = createMutant('src/todo.ts', 'TodoList.allTodos.push(newItem)', '42'); + const expectedResult: CheckResult = { + status: CheckStatus.Passed, + }; + const actual = await sut.check(mutant); + expect(actual).deep.eq(expectedResult); + }); +}); + +const fileContents = Object.freeze({ + ['src/todo.ts']: fs.readFileSync(resolveTestResource('src', 'todo.ts'), 'utf8'), + ['test/todo.spec.ts']: fs.readFileSync(resolveTestResource('test', 'todo.spec.ts'), 'utf8'), +}); + +function createMutant(fileName: 'src/todo.ts' | 'test/todo.spec.ts', findText: string, replacement: string, offset: number = 0): Mutant { + const originalOffset: number = fileContents[fileName].indexOf(findText); + if (originalOffset === -1) { + throw new Error(`Cannot find ${findText} in ${fileName}`); + } + const range: Range = [originalOffset + offset, originalOffset + findText.length]; + return factory.mutant({ + fileName: resolveTestResource(fileName), + mutatorName: 'foo-mutator', + range, + replacement, + }); +} diff --git a/packages/typescript-checker/test/integration/single-project.it.spec.ts b/packages/typescript-checker/test/integration/single-project.it.spec.ts new file mode 100644 index 0000000000..3397bca8e9 --- /dev/null +++ b/packages/typescript-checker/test/integration/single-project.it.spec.ts @@ -0,0 +1,124 @@ +import path from 'path'; +import fs from 'fs'; + +import { testInjector, factory, assertions } from '@stryker-mutator/test-helpers'; +import { expect } from 'chai'; +import { Mutant, Range } from '@stryker-mutator/api/core'; +import { CheckResult, CheckStatus } from '@stryker-mutator/api/check'; + +import { createTypescriptChecker } from '../../src'; +import { TypescriptChecker } from '../../src/typescript-checker'; + +const resolveTestResource = (path.resolve.bind( + path, + __dirname, + '..' /* integration */, + '..' /* test */, + '..' /* dist */, + 'testResources', + 'single-project' +) as unknown) as typeof path.resolve; + +describe('Typescript checker on a single project', () => { + let sut: TypescriptChecker; + + beforeEach(() => { + process.chdir(resolveTestResource()); + sut = testInjector.injector.injectFunction(createTypescriptChecker); + return sut.init(); + }); + + it('should not write output to disk', () => { + expect(fs.existsSync(resolveTestResource('dist')), 'Output was written to disk!').false; + }); + + it('should be able to validate a mutant that does not result in an error', async () => { + const mutant = createMutant('todo.ts', 'TodoList.allTodos.push(newItem)', 'newItem? 42: 43'); + const expectedResult: CheckResult = { + status: CheckStatus.Passed, + }; + const actual = await sut.check(mutant); + expect(actual).deep.eq(expectedResult); + }); + + it('should be able invalidate a mutant that does result in a compile error', async () => { + const mutant = createMutant('todo.ts', 'TodoList.allTodos.push(newItem)', '"This should not be a string 🙄"'); + const actual = await sut.check(mutant); + assertions.expectCompileError(actual); + expect(actual.reason).has.string('todo.ts(15,9): error TS2322'); + }); + + it('should be able validate a mutant that does not result in a compile error after a compile error', async () => { + // Arrange + const mutantCompileError = createMutant('todo.ts', 'TodoList.allTodos.push(newItem)', '"This should not be a string 🙄"'); + const mutantWithoutError = createMutant('todo.ts', 'return TodoList.allTodos', '[]', 7); + const expectedResult: CheckResult = { + status: CheckStatus.Passed, + }; + + // Act + await sut.check(mutantCompileError); + const actual = await sut.check(mutantWithoutError); + + // Assert + expect(actual).deep.eq(expectedResult); + }); + + it('should be able to invalidate a mutant that results in an error in a different file', async () => { + const actual = await sut.check(createMutant('todo.ts', 'return totalCount;', '')); + assertions.expectCompileError(actual); + expect(actual.reason).has.string('todo.spec.ts(4,7): error TS2322'); + }); + + it('should be able to validate a mutant after a mutant in a different file resulted in a transpile error', async () => { + // Act + await sut.check(createMutant('todo.ts', 'return totalCount;', '')); + const result = await sut.check(createMutant('todo.spec.ts', "'Mow lawn'", "'this is valid, right?'")); + + // Assert + const expectedResult: CheckResult = { + status: CheckStatus.Passed, + }; + expect(result).deep.eq(expectedResult); + }); + + it('should be allow mutations in unrelated files', async () => { + // Act + const result = await sut.check(createMutant('not-type-checked.js', 'bar', 'baz')); + + // Assert + const expectedResult: CheckResult = { + status: CheckStatus.Passed, + }; + expect(result).deep.eq(expectedResult); + }); + + it('should allow unused local variables (override options)', async () => { + const mutant = createMutant('todo.ts', 'TodoList.allTodos.push(newItem)', '42'); + const expectedResult: CheckResult = { + status: CheckStatus.Passed, + }; + const actual = await sut.check(mutant); + expect(actual).deep.eq(expectedResult); + }); +}); + +const fileContents = Object.freeze({ + ['todo.ts']: fs.readFileSync(resolveTestResource('src', 'todo.ts'), 'utf8'), + ['todo.spec.ts']: fs.readFileSync(resolveTestResource('src', 'todo.spec.ts'), 'utf8'), + ['not-type-checked.js']: fs.readFileSync(resolveTestResource('src', 'not-type-checked.js'), 'utf8'), +}); + +function createMutant(fileName: 'todo.ts' | 'todo.spec.ts' | 'not-type-checked.js', findText: string, replacement: string, offset = 0): Mutant { + const originalOffset: number = fileContents[fileName].indexOf(findText); + if (originalOffset === -1) { + throw new Error(`Cannot find ${findText} in ${fileName}`); + } + const range: Range = [originalOffset + offset, originalOffset + findText.length]; + return factory.mutant({ + fileName: resolveTestResource('src', fileName), + mutatorName: 'foo-mutator', + range, + replacement, + }); +} diff --git a/packages/typescript-checker/test/integration/typescript-checkers-errors.it.spec.ts b/packages/typescript-checker/test/integration/typescript-checkers-errors.it.spec.ts new file mode 100644 index 0000000000..4eb73dcbf7 --- /dev/null +++ b/packages/typescript-checker/test/integration/typescript-checkers-errors.it.spec.ts @@ -0,0 +1,45 @@ +import path from 'path'; + +import { testInjector } from '@stryker-mutator/test-helpers'; +import { expect } from 'chai'; + +import { createTypescriptChecker } from '../../src'; +import { TypescriptChecker } from '../../src/typescript-checker'; + +const resolveTestResource = (path.resolve.bind( + path, + __dirname, + '..' /* integration */, + '..' /* test */, + '..' /* dist */, + 'testResources', + 'errors' +) as unknown) as typeof path.resolve; + +describe('Typescript checker errors', () => { + let sut: TypescriptChecker; + + beforeEach(() => { + sut = testInjector.injector.injectFunction(createTypescriptChecker); + }); + + it('should reject initialization if initial compilation failed', async () => { + process.chdir(resolveTestResource('compile-error')); + await expect(sut.init()).rejectedWith('TypeScript error(s) found in dry run compilation: add.ts(2,3): error TS2322:'); + }); + + it('should reject initialization if tsconfig was invalid', async () => { + process.chdir(resolveTestResource('invalid-tsconfig')); + await expect(sut.init()).rejectedWith('TypeScript error(s) found in dry run compilation: tsconfig.json(1,1): error TS1005:'); + }); + + it("should reject when tsconfig file doesn't exist", async () => { + process.chdir(resolveTestResource('empty-dir')); + await expect(sut.init()).rejectedWith( + `The tsconfig file does not exist at: "${resolveTestResource( + 'empty-dir', + 'tsconfig.json' + )}". Please configure the tsconfig file in your stryker.conf file using "tsconfigFile"` + ); + }); +}); diff --git a/packages/typescript-checker/test/setup.ts b/packages/typescript-checker/test/setup.ts new file mode 100644 index 0000000000..e117d8e4f9 --- /dev/null +++ b/packages/typescript-checker/test/setup.ts @@ -0,0 +1,23 @@ +import 'source-map-support/register'; +import chai from 'chai'; +import chaiAsPromised from 'chai-as-promised'; +import sinonChai from 'sinon-chai'; +import sinon from 'sinon'; +import { testInjector } from '@stryker-mutator/test-helpers'; + +chai.use(sinonChai); +chai.use(chaiAsPromised); + +let originalCwd: string; + +export const mochaHooks = { + beforeEach() { + originalCwd = process.cwd(); + }, + + afterEach() { + sinon.restore(); + testInjector.reset(); + process.chdir(originalCwd); + }, +}; diff --git a/packages/typescript-checker/test/tsconfig.json b/packages/typescript-checker/test/tsconfig.json new file mode 100644 index 0000000000..c3f30c9d6a --- /dev/null +++ b/packages/typescript-checker/test/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "../../../tsconfig.settings.json", + "compilerOptions": { + "outDir": "../dist/test", + "rootDir": ".", + "esModuleInterop": true, + "types": [ + "mocha", + "node" + ] + }, + "references": [ + { + "path": "../src" + }, + { + "path": "../../test-helpers/tsconfig.src.json" + } + ] +} diff --git a/packages/typescript-checker/test/unit/fs/hybrid-file-system.spec.ts b/packages/typescript-checker/test/unit/fs/hybrid-file-system.spec.ts new file mode 100644 index 0000000000..c083c15e63 --- /dev/null +++ b/packages/typescript-checker/test/unit/fs/hybrid-file-system.spec.ts @@ -0,0 +1,197 @@ +import sinon from 'sinon'; +import ts from 'typescript'; +import { expect } from 'chai'; +import { testInjector } from '@stryker-mutator/test-helpers'; + +import { HybridFileSystem } from '../../../src/fs'; + +describe('fs', () => { + describe(HybridFileSystem.name, () => { + class Helper { + public readFileStub = sinon.stub(ts.sys, 'readFile'); + public getModifiedTimeStub = sinon.stub(ts.sys, 'getModifiedTime'); + } + let sut: HybridFileSystem; + let helper: Helper; + beforeEach(() => { + helper = new Helper(); + sut = testInjector.injector.injectClass(HybridFileSystem); + }); + + describe(HybridFileSystem.prototype.writeFile.name, () => { + it('should create a new in-memory file', () => { + sut.writeFile('add.js', 'a + b'); + const file = sut.getFile('add.js'); + expect(file).ok; + expect(file!.content).eq('a + b'); + expect(file!.fileName).eq('add.js'); + }); + + it('should override an existing file', () => { + sut.writeFile('add.js', 'a + b'); + sut.writeFile('add.js', 'a - b'); + const file = sut.getFile('add.js'); + expect(file!.content).eq('a - b'); + }); + + it('should convert path separator to forward slashes', () => { + sut.writeFile('test\\foo\\a.js', 'a'); + const actual = sut.getFile('test/foo/a.js'); + expect(actual).ok; + expect(actual!.content).eq('a'); + }); + }); + + describe(HybridFileSystem.prototype.getFile.name, () => { + it("should read the file from disk if it wasn't loaded yet", () => { + // Arrange + const modifiedTime = new Date(2010, 1, 1); + helper.readFileStub.returns('content from disk'); + helper.getModifiedTimeStub.returns(modifiedTime); + + // Act + const actual = sut.getFile('foo.js'); + + // Assert + expect(helper.readFileStub).calledWith('foo.js'); + expect(helper.getModifiedTimeStub).calledWith('foo.js'); + expect(actual).ok; + expect(actual!.fileName).eq('foo.js'); + expect(actual!.content).eq('content from disk'); + expect(actual!.modifiedTime).eq(modifiedTime); + }); + + it('should convert path separator to forward slashes', () => { + helper.readFileStub.returns('content from disk'); + helper.getModifiedTimeStub.returns(new Date(2010, 1, 1)); + sut.getFile('test\\foo\\a.js'); + expect(helper.readFileStub).calledWith('test/foo/a.js'); + expect(helper.getModifiedTimeStub).calledWith('test/foo/a.js'); + }); + + it('should support empty files', () => { + helper.readFileStub.returns(''); + helper.getModifiedTimeStub.returns(new Date(2010, 1, 1)); + const actual = sut.getFile('foo.js'); + expect(actual).ok; + expect(actual!.fileName).eq('foo.js'); + expect(actual!.content).eq(''); + }); + + it("should cache a file that doesn't exists", () => { + sut.getFile('not-exists.js'); + sut.getFile('not-exists.js'); + expect(helper.readFileStub).calledOnce; + }); + }); + + describe(HybridFileSystem.prototype.watchFile.name, () => { + it('should register a watcher', () => { + // Arrange + helper.readFileStub.returns('foobar'); + const watcherCallback = sinon.stub(); + + // Act + sut.watchFile('foo.js', watcherCallback); + sut.writeFile('foo.js', 'some-content'); + + // Asset + expect(watcherCallback).calledWith('foo.js', ts.FileWatcherEventKind.Changed); + }); + + it('should convert path separator to forward slashes', () => { + helper.readFileStub.returns('content from disk'); + helper.getModifiedTimeStub.returns(new Date(2010, 1, 1)); + sut.watchFile('test\\foo\\a.js', sinon.stub()); + expect(helper.readFileStub).calledWith('test/foo/a.js'); + }); + + it("should throw if file doesn't exist", () => { + expect(() => sut.watchFile('not-exists.js', sinon.stub())).throws('Cannot find file not-exists.js for watching'); + }); + + it('should log that the file is watched', () => { + helper.readFileStub.returns('foobar'); + const watcherCallback = sinon.stub(); + sut.watchFile('foo.js', watcherCallback); + expect(testInjector.logger.trace).calledWith('Registering watcher for file "%s"', 'foo.js'); + }); + }); + + describe(HybridFileSystem.prototype.mutate.name, () => { + it('should mutate the file in-memory', () => { + // Arrange + helper.readFileStub.returns('a + b'); + sut.watchFile('a.js', sinon.stub()); + + // Act + sut.mutate({ fileName: 'a.js', range: [2, 3], replacement: '-' }); + + // Assert + expect(sut.getFile('a.js')!.content).eq('a - b'); + }); + + it('should convert path separator to forward slashes', () => { + helper.readFileStub.returns('a + b'); + sut.watchFile('test/foo/a.js', sinon.stub()); + sut.mutate({ fileName: 'test\\foo\\a.js', range: [2, 3], replacement: '-' }); + expect(sut.getFile('test/foo/a.js')!.content).eq('a - b'); + }); + + it('should notify the watcher', () => { + // Arrange + const watcher = sinon.stub(); + helper.readFileStub.returns('a + b'); + sut.watchFile('a.js', watcher); + + // Act + sut.mutate({ fileName: 'a.js', range: [2, 3], replacement: '-' }); + + // Assert + expect(watcher).calledWith('a.js', ts.FileWatcherEventKind.Changed); + }); + + it('should reset previously mutated file', () => { + // Arrange + helper.readFileStub.withArgs('a.js').returns('a + b').withArgs('b.js').returns('"foo" + "bar"'); + sut.watchFile('a.js', sinon.stub()); + sut.watchFile('b.js', sinon.stub()); + + // Act + sut.mutate({ fileName: 'a.js', range: [2, 3], replacement: '-' }); + sut.mutate({ fileName: 'b.js', range: [6, 7], replacement: '-' }); + + // Assert + expect(sut.getFile('a.js')!.content).eq('a + b'); + expect(sut.getFile('b.js')!.content).eq('"foo" - "bar"'); + }); + + it("should throw if file doesn't exist", () => { + expect(() => sut.mutate({ fileName: 'a.js', range: [2, 3], replacement: '-' })).throws('File "a.js" cannot be found.'); + }); + }); + + describe(HybridFileSystem.prototype.existsInMemory.name, () => { + it('should return true if it exists', () => { + sut.writeFile('a.js', 'a + b'); + expect(sut.existsInMemory('a.js')).true; + }); + + it('should return false if it does not exist', () => { + sut.writeFile('b.js', 'a + b'); + expect(sut.existsInMemory('a.js')).false; + }); + + it('should return false it is cached to not exist', () => { + helper.readFileStub.returns(undefined); + sut.getFile('a.js'); // caches that it doesn't exists + expect(sut.existsInMemory('a.js')).false; + }); + + it('should convert path separator to forward slashes', () => { + sut.writeFile('test/foo/a.js', 'foobar'); + expect(sut.existsInMemory('test\\foo\\a.js')).true; + }); + }); + }); +}); diff --git a/packages/typescript-checker/test/unit/fs/script-file.spec.ts b/packages/typescript-checker/test/unit/fs/script-file.spec.ts new file mode 100644 index 0000000000..5d63101a27 --- /dev/null +++ b/packages/typescript-checker/test/unit/fs/script-file.spec.ts @@ -0,0 +1,143 @@ +import { expect } from 'chai'; +import sinon from 'sinon'; +import ts from 'typescript'; + +import { ScriptFile } from '../../../src/fs/script-file'; + +describe('fs', () => { + describe(ScriptFile.name, () => { + beforeEach(() => { + sinon.useFakeTimers(); + }); + describe('constructor', () => { + it('should reflect content, name and modified date', () => { + const modifiedTime = new Date(2010, 1, 1, 2, 3, 4, 4); + const sut = new ScriptFile('foo()', 'foo.js', modifiedTime); + expect(sut.fileName).eq('foo.js'); + expect(sut.content).eq('foo()'); + expect(sut.modifiedTime).eq(modifiedTime); + }); + + it('should default modifiedDate to now', () => { + const now = new Date(2010, 1, 2, 3, 4, 5, 6); + sinon.clock.setSystemTime(now); + const sut = new ScriptFile('', ''); + expect(sut.modifiedTime.valueOf()).eq(new Date(2010, 1, 2, 3, 4, 5, 6).valueOf()); + }); + }); + + describe(ScriptFile.prototype.mutate.name, () => { + let sut: ScriptFile; + beforeEach(() => { + sut = new ScriptFile('add(a, b) { return a + b };', 'add.js', new Date(2010, 1, 1)); + sut.watcher = sinon.stub(); + }); + + it('should throw when no watcher is registered', () => { + sut.watcher = undefined; + expect(() => sut.mutate({ range: [21, 22], replacement: '-' })).throws( + 'ried to check file "add.js" (which is part of your typescript project), but no watcher is registered for it. Changes would go unnoticed. This probably means that you need to expand the files that are included in your project' + ); + }); + + it('should mutate the current content', () => { + sut.mutate({ range: [21, 22], replacement: '-' }); + expect(sut.content).eq('add(a, b) { return a - b };'); + }); + + it('should update the modified date', () => { + // Arrange + const now = new Date(2015, 1, 2, 3, 4, 5, 6); + sinon.clock.setSystemTime(now); + + // Act + sut.mutate({ range: [1, 2], replacement: '' }); + + // Assert + expect(sut.modifiedTime).deep.eq(now); + }); + + it('should notify the file system watcher', () => { + sut.mutate({ range: [1, 2], replacement: '' }); + expect(sut.watcher).calledWith('add.js', ts.FileWatcherEventKind.Changed); + }); + }); + + describe(ScriptFile.prototype.resetMutant.name, () => { + let sut: ScriptFile; + + beforeEach(() => { + sut = new ScriptFile('add(a, b) { return a + b };', 'add.js', new Date(2010, 1, 1)); + sut.watcher = sinon.stub(); + }); + + it('should reset the content after a mutation', () => { + sut.mutate({ replacement: 'replaces', range: [0, sut.content.length] }); + sut.resetMutant(); + expect(sut.content).eq('add(a, b) { return a + b };'); + }); + + it('should throw when no watcher is registered', () => { + sut.watcher = undefined; + expect(() => sut.resetMutant()).throws( + 'ried to check file "add.js" (which is part of your typescript project), but no watcher is registered for it. Changes would go unnoticed. This probably means that you need to expand the files that are included in your project' + ); + }); + + it('should reset the content after two mutations', () => { + sut.mutate({ replacement: 'replaces', range: [0, sut.content.length] }); + sut.mutate({ replacement: 'replaced a second time', range: [0, sut.content.length] }); + sut.resetMutant(); + expect(sut.content).eq('add(a, b) { return a + b };'); + }); + + it('should notify the file system watcher', () => { + sut.resetMutant(); + expect(sut.watcher).calledWith('add.js', ts.FileWatcherEventKind.Changed); + }); + + it('should update the modified date', () => { + // Arrange + const now = new Date(2015, 1, 2, 3, 4, 5, 6); + sinon.clock.setSystemTime(now); + + // Act + sut.resetMutant(); + + // Assert + expect(sut.modifiedTime).deep.eq(now); + }); + }); + + describe(ScriptFile.prototype.write.name, () => { + let sut: ScriptFile; + + beforeEach(() => { + sut = new ScriptFile('add(a, b) { return a + b };', 'add.js', new Date(2010, 1, 1)); + }); + + it('should write to the content', () => { + sut.write('overridden'); + expect(sut.content).eq('overridden'); + }); + + it('should inform the fs watcher', () => { + sut.watcher = sinon.stub(); + sut.write('overridden'); + expect(sut.watcher).calledWith('add.js', ts.FileWatcherEventKind.Changed); + }); + + it('should update the modified date', () => { + // Arrange + const now = new Date(2015, 1, 2, 3, 4, 5, 6); + sinon.clock.setSystemTime(now); + + // Act + sut.write('overridden'); + + // Assert + expect(sut.modifiedTime).deep.eq(now); + }); + }); + }); +}); diff --git a/packages/typescript-checker/test/unit/typescript-helpers.spec.ts b/packages/typescript-checker/test/unit/typescript-helpers.spec.ts new file mode 100644 index 0000000000..34db146d0e --- /dev/null +++ b/packages/typescript-checker/test/unit/typescript-helpers.spec.ts @@ -0,0 +1,135 @@ +import path from 'path'; + +import sinon from 'sinon'; +import ts from 'typescript'; +import { expect } from 'chai'; + +import { determineBuildModeEnabled, overrideOptions, retrieveReferencedProjects, guardTSVersion } from '../../src/tsconfig-helpers'; + +describe('typescript-helpers', () => { + describe(determineBuildModeEnabled.name, () => { + let readFileStub: sinon.SinonStub; + + beforeEach(() => { + readFileStub = sinon.stub(ts.sys, 'readFile'); + }); + + it('should throw an error if the tsconfig file could not be found', () => { + expect(() => determineBuildModeEnabled('tsconfig.json')).throws('File "tsconfig.json" not found'); + }); + + it('should return true if the tsconfig file has references', () => { + readFileStub.returns('{ "references": [] }'); + expect(determineBuildModeEnabled('foo.json')).true; + expect(readFileStub).calledWith('foo.json'); + }); + + it('should return true if the tsconfig file has no references', () => { + readFileStub.returns('{ "compilerOptions": {} }'); + expect(determineBuildModeEnabled('foo.json')).false; + }); + }); + + describe(overrideOptions.name, () => { + it('should allow unreachable and unused code', () => { + expect(JSON.parse(overrideOptions({ config: {} }, false)).compilerOptions).deep.include({ + allowUnreachableCode: true, + noUnusedLocals: false, + noUnusedParameters: false, + }); + expect( + JSON.parse( + overrideOptions({ config: { compilerOptions: { allowUnreachableCode: false, noUnusedLocals: true, noUnusedParameters: true } } }, false) + ).compilerOptions + ).deep.include({ + allowUnreachableCode: true, + noUnusedLocals: false, + noUnusedParameters: false, + }); + }); + + it('should set --noEmit options when `--build` mode is off', () => { + expect(JSON.parse(overrideOptions({ config: {} }, false)).compilerOptions).deep.include({ + noEmit: true, + incremental: false, + composite: false, + declaration: false, + }); + expect( + JSON.parse( + overrideOptions( + { + config: { + compilerOptions: { + noEmit: false, + incremental: true, + composite: true, + declaration: true, + }, + }, + }, + false + ) + ).compilerOptions + ).deep.include({ + noEmit: true, + incremental: false, + composite: false, + declaration: false, + }); + }); + + it('should set --emitDeclarationOnly options when `--build` mode is on', () => { + expect(JSON.parse(overrideOptions({ config: {} }, true)).compilerOptions).deep.include({ + emitDeclarationOnly: true, + noEmit: false, + declarationMap: false, + }); + expect( + JSON.parse( + overrideOptions( + { + config: { + compilerOptions: { + emitDeclarationOnly: false, + noEmit: true, + declarationMap: true, + }, + }, + }, + true + ) + ).compilerOptions + ).deep.include({ + emitDeclarationOnly: true, + noEmit: false, + declarationMap: false, + }); + }); + }); + + describe(retrieveReferencedProjects.name, () => { + it('should result in an empty array when references are missing', () => { + expect(retrieveReferencedProjects({ config: { compilerOptions: {} } })).deep.eq([]); + }); + + it('should retrieve referenced projects', () => { + expect(retrieveReferencedProjects({ config: { references: [{ path: 'some.json' }] } })).deep.eq([path.resolve('some.json')]); + }); + }); + + describe(guardTSVersion.name, () => { + it('should throw if typescript@2.5.0', () => { + sinon.stub(ts, 'version').value('3.5.0'); + expect(guardTSVersion).throws('@stryker-mutator/typescript-checker only supports typescript@3.6 our higher. Found typescript@3.5.0'); + }); + it('should not throw if typescript@3.6.0', () => { + sinon.stub(ts, 'version').value('3.6.0'); + expect(guardTSVersion).not.throws(); + }); + it('should not throw if typescript@4.0.0', () => { + sinon.stub(ts, 'version').value('4.0.0'); + expect(guardTSVersion).not.throws(); + }); + }); +}); diff --git a/packages/typescript-checker/testResources/errors/compile-error/add.ts b/packages/typescript-checker/testResources/errors/compile-error/add.ts new file mode 100644 index 0000000000..5c40274cca --- /dev/null +++ b/packages/typescript-checker/testResources/errors/compile-error/add.ts @@ -0,0 +1,3 @@ +function add(a: number, b: number): string { + return a + b; +} diff --git a/packages/typescript-checker/testResources/errors/compile-error/tsconfig.json b/packages/typescript-checker/testResources/errors/compile-error/tsconfig.json new file mode 100644 index 0000000000..b8a31e14ea --- /dev/null +++ b/packages/typescript-checker/testResources/errors/compile-error/tsconfig.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "target": "ES5", + "types": [] + } +} diff --git a/packages/typescript-checker/testResources/errors/empty-dir/.gitkeep b/packages/typescript-checker/testResources/errors/empty-dir/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/typescript-checker/testResources/errors/invalid-tsconfig/tsconfig.json b/packages/typescript-checker/testResources/errors/invalid-tsconfig/tsconfig.json new file mode 100644 index 0000000000..072ca9248e --- /dev/null +++ b/packages/typescript-checker/testResources/errors/invalid-tsconfig/tsconfig.json @@ -0,0 +1 @@ +invalid tsconfig file diff --git a/packages/typescript-checker/testResources/project-references/src/todo.ts b/packages/typescript-checker/testResources/project-references/src/todo.ts new file mode 100644 index 0000000000..7ac1dd6631 --- /dev/null +++ b/packages/typescript-checker/testResources/project-references/src/todo.ts @@ -0,0 +1,23 @@ +export interface ITodo { + name: string; + description: string; + completed: boolean; +} + +class Todo implements ITodo { + constructor(public name: string, public description: string, public completed: boolean) { } +} + +export class TodoList { + public static allTodos: Todo[] = []; + createTodoItem(name: string, description: string) { + let newItem = new Todo(name, description, false); + let totalCount: number = TodoList.allTodos.push(newItem); + return totalCount; + } + + allTodoItems(): ITodo[] { + return TodoList.allTodos; + } +} + diff --git a/packages/typescript-checker/testResources/project-references/src/tsconfig.json b/packages/typescript-checker/testResources/project-references/src/tsconfig.json new file mode 100644 index 0000000000..af64ba5a29 --- /dev/null +++ b/packages/typescript-checker/testResources/project-references/src/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "../tsconfig.settings", + "compilerOptions": { + "outDir": "../dist/src" + } +} diff --git a/packages/typescript-checker/testResources/project-references/test/todo.spec.ts b/packages/typescript-checker/testResources/project-references/test/todo.spec.ts new file mode 100644 index 0000000000..4d0aa4f7a2 --- /dev/null +++ b/packages/typescript-checker/testResources/project-references/test/todo.spec.ts @@ -0,0 +1,11 @@ +import { TodoList } from '../src/todo'; + +const list = new TodoList(); +const n: number = list.createTodoItem('Mow lawn', 'Mow moving forward.') +console.log(n); + +function addTodo(name = 'test', description = 'test') { + list.createTodoItem(name, description); +} + +addTodo(); diff --git a/packages/typescript-checker/testResources/project-references/test/tsconfig.json b/packages/typescript-checker/testResources/project-references/test/tsconfig.json new file mode 100644 index 0000000000..22f321ef72 --- /dev/null +++ b/packages/typescript-checker/testResources/project-references/test/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../tsconfig.settings", + "compilerOptions": { + "outDir": "../dist/test" + }, + "references": [ + { "path": "../src" } + ] +} diff --git a/packages/typescript-checker/testResources/project-references/tsconfig.root.json b/packages/typescript-checker/testResources/project-references/tsconfig.root.json new file mode 100644 index 0000000000..d54e2806ef --- /dev/null +++ b/packages/typescript-checker/testResources/project-references/tsconfig.root.json @@ -0,0 +1,7 @@ +{ + "files": [], + "references": [ + { "path": "./src" }, + { "path": "./test" } + ] +} diff --git a/packages/typescript-checker/testResources/project-references/tsconfig.settings.json b/packages/typescript-checker/testResources/project-references/tsconfig.settings.json new file mode 100644 index 0000000000..447ab8f8ac --- /dev/null +++ b/packages/typescript-checker/testResources/project-references/tsconfig.settings.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "strict": true, + "target": "es5", + "esModuleInterop": true, + "moduleResolution": "node", + "module": "commonjs", + "composite": true, + "declaration": true, + "declarationMap": true, + + // These settings should be overridden by the typescript checker + "noUnusedLocals": true, + "noUnusedParameters": true, + + "types": [] + } +} diff --git a/packages/typescript-checker/testResources/single-project/src/not-type-checked.js b/packages/typescript-checker/testResources/single-project/src/not-type-checked.js new file mode 100644 index 0000000000..74aa322268 --- /dev/null +++ b/packages/typescript-checker/testResources/single-project/src/not-type-checked.js @@ -0,0 +1 @@ +const foo = 'bar'; diff --git a/packages/typescript-checker/testResources/single-project/src/todo.spec.ts b/packages/typescript-checker/testResources/single-project/src/todo.spec.ts new file mode 100644 index 0000000000..7a3ec6a0c0 --- /dev/null +++ b/packages/typescript-checker/testResources/single-project/src/todo.spec.ts @@ -0,0 +1,12 @@ +import { TodoList } from './todo'; + +const list = new TodoList(); +const n: number = list.createTodoItem('Mow lawn', 'Mow moving forward.') +console.log(n); + +function addTodo(name = 'test', description = 'test') { + list.createTodoItem(name, description); +} + + +addTodo(); diff --git a/packages/typescript-checker/testResources/single-project/src/todo.ts b/packages/typescript-checker/testResources/single-project/src/todo.ts new file mode 100644 index 0000000000..7ac1dd6631 --- /dev/null +++ b/packages/typescript-checker/testResources/single-project/src/todo.ts @@ -0,0 +1,23 @@ +export interface ITodo { + name: string; + description: string; + completed: boolean; +} + +class Todo implements ITodo { + constructor(public name: string, public description: string, public completed: boolean) { } +} + +export class TodoList { + public static allTodos: Todo[] = []; + createTodoItem(name: string, description: string) { + let newItem = new Todo(name, description, false); + let totalCount: number = TodoList.allTodos.push(newItem); + return totalCount; + } + + allTodoItems(): ITodo[] { + return TodoList.allTodos; + } +} + diff --git a/packages/typescript-checker/testResources/single-project/tsconfig.json b/packages/typescript-checker/testResources/single-project/tsconfig.json new file mode 100644 index 0000000000..92e62065bc --- /dev/null +++ b/packages/typescript-checker/testResources/single-project/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "strict": true, + "target": "es5", + "esModuleInterop": true, + "moduleResolution": "node", + "module": "commonjs", + "outDir": "dist", + + // These settings should be overridden by the typescript checker + "noUnusedLocals": true, + "noUnusedParameters": true, + + "types": [] + } +} diff --git a/packages/typescript-checker/tsconfig.json b/packages/typescript-checker/tsconfig.json new file mode 100644 index 0000000000..d5c40e5337 --- /dev/null +++ b/packages/typescript-checker/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./src" + }, + { + "path": "./test" + } + ] +} diff --git a/packages/typescript/CHANGELOG.md b/packages/typescript/CHANGELOG.md index 34e4710efb..8b688a6e32 100644 --- a/packages/typescript/CHANGELOG.md +++ b/packages/typescript/CHANGELOG.md @@ -3,6 +3,100 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [4.0.0-beta.10](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.9...v4.0.0-beta.10) (2020-10-05) + +**Note:** Version bump only for package @stryker-mutator/typescript + + + + + +# [4.0.0-beta.9](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.8...v4.0.0-beta.9) (2020-09-30) + +**Note:** Version bump only for package @stryker-mutator/typescript + + + + + +# [4.0.0-beta.8](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.7...v4.0.0-beta.8) (2020-09-22) + +**Note:** Version bump only for package @stryker-mutator/typescript + + + + + +# [4.0.0-beta.7](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.6...v4.0.0-beta.7) (2020-09-17) + +**Note:** Version bump only for package @stryker-mutator/typescript + + + + + +# [4.0.0-beta.6](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.5...v4.0.0-beta.6) (2020-09-10) + +**Note:** Version bump only for package @stryker-mutator/typescript + + + + + +# [4.0.0-beta.5](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.4...v4.0.0-beta.5) (2020-09-09) + +**Note:** Version bump only for package @stryker-mutator/typescript + + + + + +# [4.0.0-beta.4](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.3...v4.0.0-beta.4) (2020-08-29) + +**Note:** Version bump only for package @stryker-mutator/typescript + + + + + +# [4.0.0-beta.3](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.2...v4.0.0-beta.3) (2020-08-19) + +**Note:** Version bump only for package @stryker-mutator/typescript + + + + + +# [4.0.0-beta.2](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.1...v4.0.0-beta.2) (2020-08-07) + +**Note:** Version bump only for package @stryker-mutator/typescript + + + + + +# [4.0.0-beta.1](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.0...v4.0.0-beta.1) (2020-07-17) + +**Note:** Version bump only for package @stryker-mutator/typescript + + + + + +# [4.0.0-beta.0](https://github.com/stryker-mutator/stryker/compare/v3.3.1...v4.0.0-beta.0) (2020-07-10) + + +### Features + +* **api:** add id to Mutant interface ([#2255](https://github.com/stryker-mutator/stryker/issues/2255)) ([cfc9053](https://github.com/stryker-mutator/stryker/commit/cfc90537d0b9815cba2b44b9681d171ca602766e)) +* **checker:** add checker api ([#2240](https://github.com/stryker-mutator/stryker/issues/2240)) ([d463f86](https://github.com/stryker-mutator/stryker/commit/d463f8639437c114da4fe30115652e8a470dd179)), closes [#1514](https://github.com/stryker-mutator/stryker/issues/1514) [#1980](https://github.com/stryker-mutator/stryker/issues/1980) +* **transpiler:** remove `Transpiler` API ([06f668b](https://github.com/stryker-mutator/stryker/commit/06f668bf8660f78b12916b2236f3fd9bf86bf23b)) +* **tsconfig:** rewrite tsconfig references ([#2292](https://github.com/stryker-mutator/stryker/issues/2292)) ([4ee4950](https://github.com/stryker-mutator/stryker/commit/4ee4950bebd8db9c2f5a514edee57de55c040526)), closes [#2276](https://github.com/stryker-mutator/stryker/issues/2276) + + + + + ## [3.3.1](https://github.com/stryker-mutator/stryker/compare/v3.3.0...v3.3.1) (2020-07-04) **Note:** Version bump only for package @stryker-mutator/typescript diff --git a/packages/typescript/package.json b/packages/typescript/package.json index e9584d9a73..652feb249d 100644 --- a/packages/typescript/package.json +++ b/packages/typescript/package.json @@ -1,13 +1,9 @@ { "name": "@stryker-mutator/typescript", - "version": "3.3.1", + "version": "4.0.0-beta.10", "description": "A plugin for TypeScript-based projects using Stryker", "main": "src/index.js", - "scripts": { - "test": "nyc --exclude-after-remap=false --check-coverage --reporter=html --report-dir=reports/coverage --lines 90 --functions 100 --branches 90 npm run mocha", - "mocha": "mocha \"test/helpers/**/*.js\" \"test/unit/**/*.js\" && mocha --timeout 20000 \"test/helpers/**/*.js\" \"test/integration/**/*.js\"", - "stryker": "node ../core/bin/stryker run" - }, + "scripts": {}, "repository": { "type": "git", "url": "https://github.com/stryker-mutator/stryker" @@ -33,30 +29,5 @@ "Nico Jansen " ], "homepage": "https://github.com/stryker-mutator/stryker/tree/master/packages/typescript#readme", - "license": "Apache-2.0", - "dependencies": { - "@stryker-mutator/api": "^3.3.1", - "@stryker-mutator/util": "^3.3.1", - "lodash.flatmap": "~4.5.0", - "semver": "~6.3.0", - "tslib": "~2.0.0" - }, - "devDependencies": { - "@stryker-mutator/mutator-specification": "^3.3.1", - "@stryker-mutator/test-helpers": "^3.3.1", - "@types/lodash.flatmap": "~4.5.3", - "@types/node": "^14.0.1", - "@types/semver": "~7.2.0", - "surrial": "~2.0.2" - }, - "peerDependencies": { - "@stryker-mutator/core": "^3.0.0", - "typescript": "^3.0.3" - }, - "initStrykerConfig": { - "tsconfigFile": "tsconfig.json", - "mutate": [ - "src/**/*.ts" - ] - } + "license": "Apache-2.0" } diff --git a/packages/typescript/schema/typescript-options.json b/packages/typescript/schema/typescript-options.json deleted file mode 100644 index 9a519204a4..0000000000 --- a/packages/typescript/schema/typescript-options.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema", - "type": "object", - "title": "TypescriptOptions", - "additionalProperties": false, - "properties": { - "tsconfigFile": { - "description": "Location of your tsconfig.json file", - "type": "string" - }, - "tsconfig": { - "description": "Override tsconfig from your tsconfig.json file", - "type": "object", - "$ref": "http://json.schemastore.org/tsconfig#/definitions/compilerOptionsDefinition/properties/compilerOptions" - } - } -} diff --git a/packages/typescript/src/TypescriptMutator.ts b/packages/typescript/src/TypescriptMutator.ts deleted file mode 100644 index f805d088c0..0000000000 --- a/packages/typescript/src/TypescriptMutator.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { File, StrykerOptions } from '@stryker-mutator/api/core'; -import { Mutant } from '@stryker-mutator/api/mutant'; -import { commonTokens, Injector, OptionsContext, tokens } from '@stryker-mutator/api/plugin'; -import * as ts from 'typescript'; - -import flatMap = require('lodash.flatmap'); - -import { getTSConfig, parseFile } from './helpers/tsHelpers'; -import { nodeMutators } from './mutator'; -import NodeMutator from './mutator/NodeMutator'; - -export function typescriptMutatorFactory(injector: Injector): TypescriptMutator { - return injector.provideValue(MUTATORS_TOKEN, nodeMutators).injectClass(TypescriptMutator); -} -typescriptMutatorFactory.inject = tokens(commonTokens.injector); - -export const MUTATORS_TOKEN = 'mutators'; -export class TypescriptMutator { - public static inject = tokens(commonTokens.options, MUTATORS_TOKEN); - constructor(private readonly options: StrykerOptions, public readonly mutators: readonly NodeMutator[]) {} - - public mutate(inputFiles: File[]): Mutant[] { - const tsConfig = getTSConfig(this.options); - const mutants = flatMap(inputFiles, (inputFile) => { - const sourceFile = parseFile(inputFile, tsConfig && tsConfig.options && tsConfig.options.target); - return this.mutateForNode(sourceFile, sourceFile); - }); - return mutants; - } - - private mutateForNode(node: T, sourceFile: ts.SourceFile): Mutant[] { - if (shouldNodeBeSkipped(node)) { - return []; - } else { - const targetMutators = this.mutators.filter((mutator) => mutator.guard(node)); - const mutants = flatMap(targetMutators, (mutator) => mutator.mutate(node, sourceFile)); - node.forEachChild((child) => { - // It is important that forEachChild does not return a true, otherwise node visiting is halted! - mutants.push(...this.mutateForNode(child, sourceFile)); - }); - return mutants; - } - } -} - -const shouldNodeBeSkipped = (node: ts.Node): boolean => { - return ( - node.kind === ts.SyntaxKind.InterfaceDeclaration || - (node.modifiers !== undefined && node.modifiers.some((modifier) => modifier.kind === ts.SyntaxKind.DeclareKeyword)) - ); -}; diff --git a/packages/typescript/src/TypescriptOptionsEditor.ts b/packages/typescript/src/TypescriptOptionsEditor.ts deleted file mode 100644 index 2579315d7e..0000000000 --- a/packages/typescript/src/TypescriptOptionsEditor.ts +++ /dev/null @@ -1,82 +0,0 @@ -import * as fs from 'fs'; -import * as os from 'os'; -import * as path from 'path'; - -import { Logger } from '@stryker-mutator/api/logging'; -import { commonTokens, tokens } from '@stryker-mutator/api/plugin'; -import * as ts from 'typescript'; -import { OptionsEditor } from '@stryker-mutator/api/core'; -import { propertyPath } from '@stryker-mutator/util'; - -import { TypescriptOptions } from '../src-generated/typescript-options'; - -import { normalizeFileForTypescript, normalizeFileFromTypescript } from './helpers/tsHelpers'; -import { TypescriptWithStrykerOptions } from './TypescriptWithStrykerOptions'; - -// Override some compiler options that have to do with code quality. When mutating, we're not interested in the resulting code quality -// See https://github.com/stryker-mutator/stryker/issues/391 for more info -const COMPILER_OPTIONS_OVERRIDES: Readonly> = Object.freeze({ - allowUnreachableCode: true, - noUnusedLocals: false, - noUnusedParameters: false, -}); - -export default class TypescriptOptionsEditor implements OptionsEditor { - public static inject = tokens(commonTokens.logger); - constructor(private readonly log: Logger) {} - - public edit(strykerConfig: TypescriptWithStrykerOptions, host: ts.ParseConfigHost = ts.sys) { - this.loadTSConfig(strykerConfig, host); - } - - private loadTSConfig(strykerConfig: TypescriptWithStrykerOptions, host: ts.ParseConfigHost) { - if (strykerConfig.tsconfigFile) { - const tsconfigFileName = path.resolve(strykerConfig.tsconfigFile); - this.log.info(`Loading tsconfig file ${tsconfigFileName}`); - const tsconfig = this.readTypescriptConfig(tsconfigFileName, host); - if (tsconfig) { - strykerConfig.tsconfig = this.overrideOptions(tsconfig) as any; - } - } else { - this.log.debug("No '%s' specified, not loading any config", propertyPath('tsconfigFile')); - } - } - - private overrideOptions(tsConfig: ts.ParsedCommandLine): ts.ParsedCommandLine { - tsConfig.options = Object.assign({}, tsConfig.options, COMPILER_OPTIONS_OVERRIDES); - tsConfig.fileNames = tsConfig.fileNames.map(normalizeFileFromTypescript); - return tsConfig; - } - - private readTypescriptConfig(tsconfigFileName: string, host: ts.ParseConfigHost) { - const configFileBase = normalizeFileForTypescript(path.dirname(tsconfigFileName)); - const configFileText = fs.readFileSync(tsconfigFileName, 'utf8'); - const tsconfigFileNameNormalizedForTypeScript = normalizeFileForTypescript(tsconfigFileName); - const parseResult = ts.parseConfigFileTextToJson(tsconfigFileNameNormalizedForTypeScript, configFileText); - if (parseResult.error) { - const error = ts.formatDiagnostics([parseResult.error], diagnosticsHost(configFileBase)); - throw new Error(`Error while loading tsconfig file '${tsconfigFileName}': ${error}`); - } else { - const tsconfig = ts.parseJsonConfigFileContent( - parseResult.config, - host, - configFileBase, - { project: configFileBase }, - tsconfigFileNameNormalizedForTypeScript - ); - if (tsconfig.errors.length) { - const error = ts.formatDiagnostics(tsconfig.errors, diagnosticsHost(configFileBase)); - this.log.error(`Error while loading tsconfig file '${tsconfigFileName}': ${error}`); - } - return tsconfig; - } - - function diagnosticsHost(configFileBase: string): ts.FormatDiagnosticsHost { - return { - getCanonicalFileName: (fileName) => path.resolve(fileName), - getCurrentDirectory: () => configFileBase, - getNewLine: () => os.EOL, - }; - } - } -} diff --git a/packages/typescript/src/TypescriptTranspiler.ts b/packages/typescript/src/TypescriptTranspiler.ts deleted file mode 100644 index 4c97ff523b..0000000000 --- a/packages/typescript/src/TypescriptTranspiler.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { File, StrykerOptions } from '@stryker-mutator/api/core'; -import { LoggerFactoryMethod } from '@stryker-mutator/api/logging'; -import { commonTokens, tokens } from '@stryker-mutator/api/plugin'; -import { Transpiler } from '@stryker-mutator/api/transpile'; -import * as ts from 'typescript'; - -import { getProjectDirectory, getTSConfig, guardTypescriptVersion, isHeaderFile as isDeclarationFile } from './helpers/tsHelpers'; -import TranspileFilter from './transpiler/TranspileFilter'; -import TranspilingLanguageService from './transpiler/TranspilingLanguageService'; -import { TypescriptWithStrykerOptions } from './TypescriptWithStrykerOptions'; - -export default class TypescriptTranspiler implements Transpiler { - private languageService: TranspilingLanguageService; - private readonly filter: TranspileFilter; - private readonly options: TypescriptWithStrykerOptions; - - public static inject = tokens(commonTokens.options, commonTokens.produceSourceMaps, commonTokens.getLogger); - constructor(options: StrykerOptions, private readonly produceSourceMaps: boolean, private readonly getLogger: LoggerFactoryMethod) { - guardTypescriptVersion(); - this.options = options; - this.filter = TranspileFilter.create(options); - } - - public transpile(files: readonly File[]): Promise { - const typescriptFiles = this.filterIsIncluded(files); - if (this.languageService) { - this.languageService.replace(typescriptFiles); - } else { - this.languageService = this.createLanguageService(typescriptFiles); - } - const error = this.languageService.getSemanticDiagnostics(typescriptFiles); - if (error.length) { - return Promise.reject(new Error(error)); - } else { - const resultFiles = this.transpileFiles(files); - return Promise.resolve(resultFiles); - } - } - - private filterIsIncluded(files: readonly File[]): readonly File[] { - return files.filter((file) => this.filter.isIncluded(file.name)); - } - - private createLanguageService(typescriptFiles: readonly File[]) { - const tsConfig = getTSConfig(this.options); - const compilerOptions: ts.CompilerOptions = (tsConfig && tsConfig.options) || {}; - return new TranspilingLanguageService( - compilerOptions, - typescriptFiles, - getProjectDirectory(this.options), - this.produceSourceMaps, - this.getLogger - ); - } - - private transpileFiles(files: readonly File[]): readonly File[] { - let isSingleOutput = false; - const fileDictionary: { [name: string]: File } = {}; - files.forEach((file) => (fileDictionary[file.name] = file)); - files.forEach((file) => { - if (!isDeclarationFile(file.name) && !this.hasJsonOutput(file.name)) { - if (this.filter.isIncluded(file.name)) { - // File is to be transpiled. Only emit if more output is expected. - if (!isSingleOutput) { - const emitOutput = this.languageService.emit(file.name); - isSingleOutput = emitOutput.singleResult; - emitOutput.outputFiles.forEach((file) => (fileDictionary[file.name] = file)); - } - - // Remove original file - delete fileDictionary[file.name]; - } - } - }); - - return Object.keys(fileDictionary).map((name) => fileDictionary[name]); - } - private hasJsonOutput(fileName: string): boolean { - return fileName.endsWith('.json') && !getTSConfig(this.options).options.outDir; - } -} diff --git a/packages/typescript/src/TypescriptWithStrykerOptions.ts b/packages/typescript/src/TypescriptWithStrykerOptions.ts deleted file mode 100644 index bbe8d8f22d..0000000000 --- a/packages/typescript/src/TypescriptWithStrykerOptions.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { StrykerOptions } from '@stryker-mutator/api/core'; - -import { TypescriptOptions } from '../src-generated/typescript-options'; - -export interface TypescriptWithStrykerOptions extends TypescriptOptions, StrykerOptions {} diff --git a/packages/typescript/src/helpers/tsHelpers.ts b/packages/typescript/src/helpers/tsHelpers.ts deleted file mode 100644 index 6c59447ccd..0000000000 --- a/packages/typescript/src/helpers/tsHelpers.ts +++ /dev/null @@ -1,85 +0,0 @@ -import * as os from 'os'; -import * as path from 'path'; - -import { File } from '@stryker-mutator/api/core'; -import * as semver from 'semver'; -import * as ts from 'typescript'; - -import { TypescriptWithStrykerOptions } from '../TypescriptWithStrykerOptions'; - -export function parseFile(file: File, target: ts.ScriptTarget | undefined) { - return ts.createSourceFile(file.name, file.textContent, target || ts.ScriptTarget.ES5, /*setParentNodes*/ true); -} - -/** - * For some reason, typescript on windows doesn't like back slashes - * @param fileName The file name to be normalized - */ -export function normalizeFileForTypescript(fileName: string) { - return fileName.replace(/\\/g, '/'); -} - -/** - * For some reason, typescript on windows doesn't like back slashes - * @param fileName The file name to be normalized - */ -export function normalizeFileFromTypescript(fileName: string) { - return path.normalize(fileName); -} - -export function getTSConfig(options: TypescriptWithStrykerOptions): ts.ParsedCommandLine { - return (options.tsconfig as unknown) as ts.ParsedCommandLine; -} - -export function getProjectDirectory(options: TypescriptWithStrykerOptions) { - return path.dirname(options.tsconfigFile || '.'); -} - -/** - * Verifies that the installed version of typescript satisfies '>=2.4` and otherwise: throws an exception - */ -export function guardTypescriptVersion() { - if (!semver.satisfies(ts.version, '>=2.4')) { - throw new Error( - `Installed typescript version ${ts.version} is not supported by stryker-typescript. Please install version 2.5 or higher (\`npm install typescript@^2.5\`).` - ); - } -} - -const printer = ts.createPrinter({ - newLine: os.EOL === '\r\n' ? ts.NewLineKind.CarriageReturnLineFeed : ts.NewLineKind.LineFeed, - removeComments: false, -}); - -export function printNode(node: ts.Node, originalSourceFile: ts.SourceFile): string { - return printer.printNode(ts.EmitHint.Unspecified, node, originalSourceFile); -} - -function tsExtensions() { - // Since ts 2.5 the ts.Extension enum is a string-based enum - if (semver.satisfies(ts.version, '>=2.5')) { - return Object.keys(ts.Extension).map((extension) => ts.Extension[extension as keyof typeof ts.Extension]); - } else { - // We know that pre 2.5 should have these extensions: - return ['.ts', '.tsx', '.js', '.jsx']; - } -} - -export function isTypescriptFile(fileName: string) { - return tsExtensions().some((extension) => fileName.endsWith(extension)); -} - -export function isJavaScriptFile(file: ts.OutputFile) { - return file.name.endsWith('.js') || file.name.endsWith('.jsx') || file.name.endsWith('.json'); -} - -export function isMapFile(file: ts.OutputFile) { - return file.name.endsWith('.map'); -} - -/** - * Determines whether or not given file is a typescript header file (*.d.ts) - */ -export function isHeaderFile(fileName: string) { - return fileName.endsWith('.d.ts'); -} diff --git a/packages/typescript/src/index.ts b/packages/typescript/src/index.ts index 12d50d3a05..be5d74ce69 100644 --- a/packages/typescript/src/index.ts +++ b/packages/typescript/src/index.ts @@ -1,15 +1 @@ -import { declareClassPlugin, declareFactoryPlugin, PluginKind } from '@stryker-mutator/api/plugin'; - -import * as strykerValidationSchema from '../schema/typescript-options.json'; - -import TypescriptOptionsEditor from './TypescriptOptionsEditor'; -import { typescriptMutatorFactory } from './TypescriptMutator'; -import TypescriptTranspiler from './TypescriptTranspiler'; - -export const strykerPlugins = [ - declareClassPlugin(PluginKind.OptionsEditor, 'typescript', TypescriptOptionsEditor), - declareClassPlugin(PluginKind.Transpiler, 'typescript', TypescriptTranspiler), - declareFactoryPlugin(PluginKind.Mutator, 'typescript', typescriptMutatorFactory), -]; - -export { strykerValidationSchema }; +console.warn('The @stryker-mutator/typescript package does not have any function in Stryker 4.0. Please remove it from your devDependencies.'); diff --git a/packages/typescript/src/mutator/ArithmeticOperatorMutator.ts b/packages/typescript/src/mutator/ArithmeticOperatorMutator.ts deleted file mode 100644 index 3c208f44f4..0000000000 --- a/packages/typescript/src/mutator/ArithmeticOperatorMutator.ts +++ /dev/null @@ -1,28 +0,0 @@ -import * as ts from 'typescript'; - -import NodeMutator, { NodeReplacement } from './NodeMutator'; - -const replaceTokens: ts.MapLike = { - [ts.SyntaxKind.PlusToken]: '-', - [ts.SyntaxKind.MinusToken]: '+', - [ts.SyntaxKind.SlashToken]: '*', - [ts.SyntaxKind.AsteriskToken]: '/', - [ts.SyntaxKind.PercentToken]: '*', -}; - -export default class ArithmeticOperatorMutator extends NodeMutator { - public name: string = 'ArithmeticOperator'; - - public guard(node: ts.Node): node is ts.BinaryExpression { - return node.kind === ts.SyntaxKind.BinaryExpression; - } - - public identifyReplacements(node: ts.BinaryExpression): NodeReplacement[] { - const replacement = replaceTokens[node.operatorToken.kind]; - if (replacement) { - return [{ node: node.operatorToken, replacement }]; - } else { - return []; - } - } -} diff --git a/packages/typescript/src/mutator/ArrayDeclarationMutator.ts b/packages/typescript/src/mutator/ArrayDeclarationMutator.ts deleted file mode 100644 index 8b7408b0a2..0000000000 --- a/packages/typescript/src/mutator/ArrayDeclarationMutator.ts +++ /dev/null @@ -1,37 +0,0 @@ -import * as ts from 'typescript'; - -import NodeMutator, { NodeReplacement } from './NodeMutator'; - -export default class ArrayDeclarationMutator extends NodeMutator { - public name = 'ArrayDeclaration'; - - public guard(node: ts.Node): node is ts.ArrayLiteralExpression | ts.CallExpression | ts.NewExpression { - return ( - node.kind === ts.SyntaxKind.ArrayLiteralExpression || node.kind === ts.SyntaxKind.CallExpression || node.kind === ts.SyntaxKind.NewExpression - ); - } - - protected identifyReplacements( - node: ts.ArrayLiteralExpression | ts.CallExpression | ts.NewExpression, - sourceFile: ts.SourceFile - ): NodeReplacement[] { - if (node.kind === ts.SyntaxKind.ArrayLiteralExpression) { - if (node.elements.length) { - return [{ node, replacement: '[]' }]; - } else { - return [{ node, replacement: '["Stryker was here"]' }]; - } - } else if (node.kind === ts.SyntaxKind.CallExpression && node.expression.kind !== ts.SyntaxKind.Identifier) { - // extra guard in case of a function call expression - return []; - } else { - if (node.expression.getFullText(sourceFile).trim() === 'Array') { - const newPrefix = node.kind === ts.SyntaxKind.NewExpression ? 'new ' : ''; - const mutatedCallArgs = node.arguments && node.arguments.length ? '' : '[]'; - return [{ node, replacement: `${newPrefix}Array(${mutatedCallArgs})` }]; - } else { - return []; - } - } - } -} diff --git a/packages/typescript/src/mutator/ArrowFunctionMutator.ts b/packages/typescript/src/mutator/ArrowFunctionMutator.ts deleted file mode 100644 index 3a5b8b4e1d..0000000000 --- a/packages/typescript/src/mutator/ArrowFunctionMutator.ts +++ /dev/null @@ -1,20 +0,0 @@ -import * as ts from 'typescript'; - -import NodeMutator, { NodeReplacement } from './NodeMutator'; - -export default class ArrowFunctionMutator extends NodeMutator { - public name = 'ArrowFunction'; - - public guard(node: ts.Node): node is ts.ArrowFunction { - return node.kind === ts.SyntaxKind.ArrowFunction; - } - - protected identifyReplacements(fn: ts.ArrowFunction): NodeReplacement[] { - if (fn.body.kind === ts.SyntaxKind.Block) { - // This case is already handled by the BlockMutator. - return []; - } - - return [{ node: fn, replacement: '() => undefined' }]; - } -} diff --git a/packages/typescript/src/mutator/BlockStatementMutator.ts b/packages/typescript/src/mutator/BlockStatementMutator.ts deleted file mode 100644 index 9975f92332..0000000000 --- a/packages/typescript/src/mutator/BlockStatementMutator.ts +++ /dev/null @@ -1,19 +0,0 @@ -import * as ts from 'typescript'; - -import NodeMutator, { NodeReplacement } from './NodeMutator'; - -export default class BlockStatementMutator extends NodeMutator { - public name = 'BlockStatement'; - - public guard(node: ts.Node): node is ts.Block { - return node.kind === ts.SyntaxKind.Block; - } - - protected identifyReplacements(block: ts.Block): NodeReplacement[] { - if (block.statements.length) { - return [{ node: block, replacement: '{}' }]; - } else { - return []; - } - } -} diff --git a/packages/typescript/src/mutator/BooleanLiteralMutator.ts b/packages/typescript/src/mutator/BooleanLiteralMutator.ts deleted file mode 100644 index 33ebefcf33..0000000000 --- a/packages/typescript/src/mutator/BooleanLiteralMutator.ts +++ /dev/null @@ -1,25 +0,0 @@ -import * as ts from 'typescript'; - -import { printNode } from '../helpers/tsHelpers'; - -import NodeMutator, { NodeReplacement } from './NodeMutator'; - -export default class BooleanLiteralMutator extends NodeMutator { - public name: string = 'BooleanLiteral'; - - public guard(node: ts.Node): node is ts.BooleanLiteral | ts.PrefixUnaryExpression { - return node.kind === ts.SyntaxKind.FalseKeyword || node.kind === ts.SyntaxKind.TrueKeyword || node.kind === ts.SyntaxKind.PrefixUnaryExpression; - } - - protected identifyReplacements(node: ts.BooleanLiteral | ts.PrefixUnaryExpression, sourceFile: ts.SourceFile): NodeReplacement[] { - if (node.kind === ts.SyntaxKind.FalseKeyword) { - return [{ node, replacement: 'true' }]; - } else if (node.kind === ts.SyntaxKind.TrueKeyword) { - return [{ node, replacement: 'false' }]; - } else if (node.kind === ts.SyntaxKind.PrefixUnaryExpression && node.operator === ts.SyntaxKind.ExclamationToken) { - return [{ node, replacement: printNode(node.operand, sourceFile) }]; - } else { - return []; - } - } -} diff --git a/packages/typescript/src/mutator/ConditionalExpressionMutator.ts b/packages/typescript/src/mutator/ConditionalExpressionMutator.ts deleted file mode 100644 index 2885798cc9..0000000000 --- a/packages/typescript/src/mutator/ConditionalExpressionMutator.ts +++ /dev/null @@ -1,104 +0,0 @@ -import * as ts from 'typescript'; - -import { printNode } from '../helpers/tsHelpers'; - -import NodeMutator, { NodeReplacement } from './NodeMutator'; - -/** - * Type guard for seperating default clause from case clauses. - */ -function isDefaultClause(node: ts.CaseOrDefaultClause): node is ts.DefaultClause { - return node.kind === ts.SyntaxKind.DefaultClause; -} - -export default class ConditionalExpressionMutator extends NodeMutator< - ts.BinaryExpression | ts.DoStatement | ts.ForStatement | ts.IfStatement | ts.CaseOrDefaultClause | ts.WhileStatement -> { - public name = 'ConditionalExpression'; - - public guard(node: ts.Node): node is ts.BinaryExpression { - return ( - node.kind === ts.SyntaxKind.BinaryExpression || - node.kind === ts.SyntaxKind.CaseClause || - node.kind === ts.SyntaxKind.DefaultClause || - node.kind === ts.SyntaxKind.DoStatement || - node.kind === ts.SyntaxKind.ForStatement || - node.kind === ts.SyntaxKind.IfStatement || - node.kind === ts.SyntaxKind.WhileStatement - ); - } - - private isInvalidParent(parent: ts.Node): boolean { - switch (parent.kind) { - case ts.SyntaxKind.IfStatement: - case ts.SyntaxKind.ForStatement: - case ts.SyntaxKind.WhileStatement: - case ts.SyntaxKind.DoStatement: - case ts.SyntaxKind.LiteralType: - case ts.SyntaxKind.CaseClause: - case ts.SyntaxKind.DefaultClause: - return true; - default: - return false; - } - } - - private isInvalidOperator(operatorToken: ts.BinaryOperatorToken): boolean { - switch (operatorToken.kind) { - case ts.SyntaxKind.PlusToken: - case ts.SyntaxKind.MinusToken: - case ts.SyntaxKind.SlashToken: - case ts.SyntaxKind.AsteriskToken: - case ts.SyntaxKind.PercentToken: - case ts.SyntaxKind.EqualsToken: - return true; - default: - return false; - } - } - - protected identifyReplacements( - node: ts.BinaryExpression | ts.DoStatement | ts.ForStatement | ts.IfStatement | ts.CaseOrDefaultClause | ts.WhileStatement, - sourceFile: ts.SourceFile - ): NodeReplacement[] { - if (node.kind === ts.SyntaxKind.DoStatement || node.kind === ts.SyntaxKind.WhileStatement) { - return [{ node: node.expression, replacement: 'false' }]; - } else if (node.kind === ts.SyntaxKind.ForStatement) { - if (node.condition) { - return [{ node: node.condition, replacement: 'false' }]; - } else { - // No node to replace. Happens when for statement is defined as `for(let i=0;;i++)` - // Replace the entire node - const replacement = printNode(ts.createFor(node.initializer, ts.createFalse(), node.incrementor, node.statement), sourceFile); - return [{ node, replacement }]; - } - } else if (node.kind === ts.SyntaxKind.IfStatement) { - return [ - { node: node.expression, replacement: 'true' }, - { node: node.expression, replacement: 'false' }, - ]; - } else if (node.kind === ts.SyntaxKind.CaseClause || node.kind === ts.SyntaxKind.DefaultClause) { - // if not a fallthrough case - if (node.statements.length > 0) { - const clause = isDefaultClause(node) ? ts.createDefaultClause([]) : ts.createCaseClause(node.expression, []); - const replacement = printNode(clause, sourceFile); - return [{ node, replacement }]; - } else { - return []; - } - } else { - if ( - (node.parent && this.isInvalidParent(node.parent)) || - (node.parent && node.parent.parent && this.isInvalidParent(node.parent.parent)) || - this.isInvalidOperator(node.operatorToken) - ) { - return []; - } - - return [ - { node, replacement: 'false' }, - { node, replacement: 'true' }, - ]; - } - } -} diff --git a/packages/typescript/src/mutator/EqualityOperatorMutator.ts b/packages/typescript/src/mutator/EqualityOperatorMutator.ts deleted file mode 100644 index 05caa932c3..0000000000 --- a/packages/typescript/src/mutator/EqualityOperatorMutator.ts +++ /dev/null @@ -1,30 +0,0 @@ -import * as ts from 'typescript'; - -import NodeMutator, { NodeReplacement } from './NodeMutator'; - -const replaceTokens: ts.MapLike = { - [ts.SyntaxKind.LessThanToken]: ['<=', '>='], - [ts.SyntaxKind.LessThanEqualsToken]: ['<', '>'], - [ts.SyntaxKind.GreaterThanToken]: ['<=', '>='], - [ts.SyntaxKind.GreaterThanEqualsToken]: ['<', '>'], - [ts.SyntaxKind.EqualsEqualsToken]: ['!='], - [ts.SyntaxKind.ExclamationEqualsToken]: ['=='], - [ts.SyntaxKind.EqualsEqualsEqualsToken]: ['!=='], - [ts.SyntaxKind.ExclamationEqualsEqualsToken]: ['==='], -}; - -export default class EqualityOperatorMutator extends NodeMutator { - public name: string = 'EqualityOperator'; - - public guard(node: ts.Node): node is ts.BinaryExpression { - return node.kind === ts.SyntaxKind.BinaryExpression; - } - - public identifyReplacements(node: ts.BinaryExpression): NodeReplacement[] { - if (replaceTokens[node.operatorToken.kind]) { - return replaceTokens[node.operatorToken.kind].map((replacement) => ({ node: node.operatorToken, replacement })); - } else { - return []; - } - } -} diff --git a/packages/typescript/src/mutator/LogicalOperatorMutator.ts b/packages/typescript/src/mutator/LogicalOperatorMutator.ts deleted file mode 100644 index a7f65b910f..0000000000 --- a/packages/typescript/src/mutator/LogicalOperatorMutator.ts +++ /dev/null @@ -1,25 +0,0 @@ -import * as ts from 'typescript'; - -import NodeMutator, { NodeReplacement } from './NodeMutator'; - -const replaceTokens: ts.MapLike = { - [ts.SyntaxKind.BarBarToken]: '&&', - [ts.SyntaxKind.AmpersandAmpersandToken]: '||', -}; - -export default class LogicalOperatorMutator extends NodeMutator { - public name: string = 'LogicalOperator'; - - public guard(node: ts.Node): node is ts.BinaryExpression { - return node.kind === ts.SyntaxKind.BinaryExpression; - } - - public identifyReplacements(node: ts.BinaryExpression): NodeReplacement[] { - const replacement = replaceTokens[node.operatorToken.kind]; - if (replacement) { - return [{ node: node.operatorToken, replacement }]; - } else { - return []; - } - } -} diff --git a/packages/typescript/src/mutator/NodeMutator.ts b/packages/typescript/src/mutator/NodeMutator.ts deleted file mode 100644 index 6d71fabff0..0000000000 --- a/packages/typescript/src/mutator/NodeMutator.ts +++ /dev/null @@ -1,29 +0,0 @@ -import * as path from 'path'; - -import { Mutant } from '@stryker-mutator/api/mutant'; -import * as ts from 'typescript'; - -export interface NodeReplacement { - node: ts.Node; - replacement: string; -} - -export default abstract class NodeMutator { - public abstract name: string; - public abstract guard(node: ts.Node): node is T; - - public mutate(node: T, sourceFile: ts.SourceFile): Mutant[] { - return this.identifyReplacements(node, sourceFile).map((replacement) => this.createMutant(replacement.node, replacement.replacement, sourceFile)); - } - - protected abstract identifyReplacements(node: T, sourceFile: ts.SourceFile): NodeReplacement[]; - - private createMutant(original: ts.Node, replacement: string, sourceFile: ts.SourceFile): Mutant { - return { - fileName: sourceFile.fileName.replace(/\//g, path.sep), - mutatorName: this.name, - range: [original.getStart(sourceFile), original.getEnd()], - replacement, - }; - } -} diff --git a/packages/typescript/src/mutator/ObjectLiteralMutator.ts b/packages/typescript/src/mutator/ObjectLiteralMutator.ts deleted file mode 100644 index f7b0498de9..0000000000 --- a/packages/typescript/src/mutator/ObjectLiteralMutator.ts +++ /dev/null @@ -1,19 +0,0 @@ -import * as ts from 'typescript'; - -import NodeMutator, { NodeReplacement } from './NodeMutator'; - -export default class ObjectLiteralMutator extends NodeMutator { - public name = 'ObjectLiteral'; - - public guard(node: ts.Node): node is ts.ObjectLiteralExpression { - return node.kind === ts.SyntaxKind.ObjectLiteralExpression; - } - - protected identifyReplacements(o: ts.ObjectLiteralExpression): NodeReplacement[] { - if (o.properties.length > 0) { - return [{ node: o, replacement: '{}' }]; - } else { - return []; - } - } -} diff --git a/packages/typescript/src/mutator/StringLiteralMutator.ts b/packages/typescript/src/mutator/StringLiteralMutator.ts deleted file mode 100644 index ccaad1ce41..0000000000 --- a/packages/typescript/src/mutator/StringLiteralMutator.ts +++ /dev/null @@ -1,66 +0,0 @@ -import * as ts from 'typescript'; - -import NodeMutator, { NodeReplacement } from './NodeMutator'; - -export type AllStringLiterals = - // Regular quoted string. - | ts.StringLiteral - // Templates string with values embedded. - | ts.TemplateExpression - // A raw token is emitted if the template string has no embeds. - | ts.Token; - -export default class StringLiteralMutator extends NodeMutator { - public name = 'StringLiteral'; - - public guard(node: ts.Node): node is AllStringLiterals { - switch (node.kind) { - case ts.SyntaxKind.StringLiteral: - case ts.SyntaxKind.TemplateExpression: - case ts.SyntaxKind.FirstTemplateToken: - return true; - default: - return false; - } - } - - private isInvalidParent(parent: ts.Node): boolean { - switch (parent.kind) { - case ts.SyntaxKind.ImportDeclaration: - case ts.SyntaxKind.ExportDeclaration: - case ts.SyntaxKind.ModuleDeclaration: - case ts.SyntaxKind.ExternalModuleReference: - case ts.SyntaxKind.LastTypeNode: - case ts.SyntaxKind.JsxAttribute: - case ts.SyntaxKind.ExpressionStatement: - case ts.SyntaxKind.LiteralType: - return true; - default: - return false; - } - } - - protected identifyReplacements(str: AllStringLiterals): NodeReplacement[] { - if (str.parent && this.isInvalidParent(str.parent)) { - return []; - } - - if (this.isEmpty(str)) { - return [{ node: str, replacement: '"Stryker was here!"' }]; - } else { - return [{ node: str, replacement: '""' }]; - } - } - - private isEmpty(str: AllStringLiterals) { - function isEmptyString() { - return str.kind === ts.SyntaxKind.StringLiteral && str.text === ''; - } - - function isEmptyTemplate() { - return str.kind === ts.SyntaxKind.FirstTemplateToken && (str as ts.NoSubstitutionTemplateLiteral).text === ''; - } - - return isEmptyString() || isEmptyTemplate(); - } -} diff --git a/packages/typescript/src/mutator/UnaryOperatorMutator.ts b/packages/typescript/src/mutator/UnaryOperatorMutator.ts deleted file mode 100644 index 0b6fe6dbcf..0000000000 --- a/packages/typescript/src/mutator/UnaryOperatorMutator.ts +++ /dev/null @@ -1,28 +0,0 @@ -import * as ts from 'typescript'; - -import { printNode } from '../helpers/tsHelpers'; - -import NodeMutator, { NodeReplacement } from './NodeMutator'; - -const replaceTokens: ts.MapLike = { - [ts.SyntaxKind.PlusToken]: '-', - [ts.SyntaxKind.MinusToken]: '+', - [ts.SyntaxKind.TildeToken]: '', -}; - -export default class UnaryOperatorMutator extends NodeMutator { - public name = 'UnaryOperator'; - - public guard(node: ts.Node): node is ts.PrefixUnaryExpression { - return node.kind === ts.SyntaxKind.PrefixUnaryExpression; - } - - protected identifyReplacements(node: ts.PrefixUnaryExpression, sourceFile: ts.SourceFile): NodeReplacement[] { - const replacement = replaceTokens[node.operator]; - if (typeof replacement === 'string') { - return [{ node, replacement: replacement + printNode(node.operand, sourceFile) }]; - } else { - return []; - } - } -} diff --git a/packages/typescript/src/mutator/UpdateOperatorMutator.ts b/packages/typescript/src/mutator/UpdateOperatorMutator.ts deleted file mode 100644 index cb712685b9..0000000000 --- a/packages/typescript/src/mutator/UpdateOperatorMutator.ts +++ /dev/null @@ -1,29 +0,0 @@ -import * as ts from 'typescript'; - -import { printNode } from '../helpers/tsHelpers'; - -import NodeMutator, { NodeReplacement } from './NodeMutator'; - -const replaceTokens: ts.MapLike = { - [ts.SyntaxKind.PlusPlusToken]: '--', - [ts.SyntaxKind.MinusMinusToken]: '++', -}; - -export default class UpdateOperatorMutator extends NodeMutator { - public name = 'UpdateOperator'; - - public guard(node: ts.Node): node is ts.PrefixUnaryExpression { - return node.kind === ts.SyntaxKind.PrefixUnaryExpression || node.kind === ts.SyntaxKind.PostfixUnaryExpression; - } - - protected identifyReplacements(node: ts.PrefixUnaryExpression | ts.PostfixUnaryExpression, sourceFile: ts.SourceFile): NodeReplacement[] { - const replacementToken = replaceTokens[node.operator]; - if (typeof replacementToken === 'string') { - const operand = printNode(node.operand, sourceFile); - const replacement = node.kind === ts.SyntaxKind.PrefixUnaryExpression ? replacementToken + operand : operand + replacementToken; - return [{ node, replacement }]; - } else { - return []; - } - } -} diff --git a/packages/typescript/src/mutator/index.ts b/packages/typescript/src/mutator/index.ts deleted file mode 100644 index 4681f46631..0000000000 --- a/packages/typescript/src/mutator/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -import ArithmeticOperatorMutator from './ArithmeticOperatorMutator'; -import ArrayDeclarationMutator from './ArrayDeclarationMutator'; -import ArrowFunctionMutator from './ArrowFunctionMutator'; -import BlockStatementMutator from './BlockStatementMutator'; -import BooleanLiteralMutator from './BooleanLiteralMutator'; -import ConditionalExpressionMutator from './ConditionalExpressionMutator'; -import EqualityOperatorMutator from './EqualityOperatorMutator'; -import ObjectLiteralMutator from './ObjectLiteralMutator'; -import StringLiteralMutator from './StringLiteralMutator'; -import LogicalOperatorMutator from './LogicalOperatorMutator'; -import UnaryOperatorMutator from './UnaryOperatorMutator'; -import UpdateOperatorMutator from './UpdateOperatorMutator'; -import NodeMutator from './NodeMutator'; - -export const nodeMutators: readonly NodeMutator[] = [ - new ArithmeticOperatorMutator(), - new ArrayDeclarationMutator(), - new BlockStatementMutator(), - new BooleanLiteralMutator(), - new ConditionalExpressionMutator(), - new EqualityOperatorMutator(), - new LogicalOperatorMutator(), - new ObjectLiteralMutator(), - new StringLiteralMutator(), - new UnaryOperatorMutator(), - new UpdateOperatorMutator(), - new ArrowFunctionMutator(), -]; diff --git a/packages/typescript/src/transpiler/ScriptFile.ts b/packages/typescript/src/transpiler/ScriptFile.ts deleted file mode 100644 index 300dfc198b..0000000000 --- a/packages/typescript/src/transpiler/ScriptFile.ts +++ /dev/null @@ -1,8 +0,0 @@ -export default class ScriptFile { - constructor(public name: string, public content: string, public version = 0) {} - - public replace(newContent: string) { - this.content = newContent; - this.version++; - } -} diff --git a/packages/typescript/src/transpiler/TranspileFilter.ts b/packages/typescript/src/transpiler/TranspileFilter.ts deleted file mode 100644 index 6290c3849a..0000000000 --- a/packages/typescript/src/transpiler/TranspileFilter.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { StrykerOptions } from '@stryker-mutator/api/core'; - -import { getTSConfig, isTypescriptFile, normalizeFileFromTypescript } from '../helpers/tsHelpers'; - -/** - * Represents a transpile filter. This is the component that decides on which files needs to be transpiled. - * - * It is implemented using the composite pattern. - * If there is a tsConfig, that will be used. If not, a default is used (transpile all TS-like files) - */ -export default abstract class TranspileFilter { - public abstract isIncluded(fileName: string): boolean; - - public static create(options: StrykerOptions): TranspileFilter { - const parsedCommandLine = getTSConfig(options); - if (parsedCommandLine) { - return new TSConfigFilter(parsedCommandLine); - } else { - return new DefaultFilter(); - } - } -} - -/** - * A transpile filter based on ts config - */ -export class TSConfigFilter extends TranspileFilter { - private readonly fileNames: string[]; - - constructor({ fileNames }: { fileNames: string[] }) { - super(); - this.fileNames = fileNames.map(normalizeFileFromTypescript); - } - - public isIncluded(fileName: string): boolean { - return this.fileNames.includes(fileName); - } -} - -/** - * A default transpile filter based on file extension - */ -export class DefaultFilter extends TranspileFilter { - public isIncluded(fileName: string): boolean { - return isTypescriptFile(fileName); - } -} diff --git a/packages/typescript/src/transpiler/TranspilingLanguageService.ts b/packages/typescript/src/transpiler/TranspilingLanguageService.ts deleted file mode 100644 index 8e128b86a9..0000000000 --- a/packages/typescript/src/transpiler/TranspilingLanguageService.ts +++ /dev/null @@ -1,142 +0,0 @@ -import * as fs from 'fs'; -import * as os from 'os'; -import * as path from 'path'; - -import { Logger, LoggerFactoryMethod } from '@stryker-mutator/api/logging'; -import { File } from '@stryker-mutator/api/core'; -import * as ts from 'typescript'; - -import flatMap = require('lodash.flatmap'); - -import { isJavaScriptFile, isMapFile, normalizeFileForTypescript, normalizeFileFromTypescript } from '../helpers/tsHelpers'; - -import ScriptFile from './ScriptFile'; - -const libRegex = /^lib\.(?:\w|\.)*\.?d\.ts$/; - -export interface EmitOutput { - singleResult: boolean; - outputFiles: File[]; -} - -export default class TranspilingLanguageService { - private readonly languageService: ts.LanguageService; - private readonly logger: Logger; - private readonly compilerOptions: ts.CompilerOptions; - private readonly files: ts.MapLike = Object.create(null); - private readonly diagnosticsFormatter: ts.FormatDiagnosticsHost; - - constructor( - compilerOptions: Readonly, - rootFiles: readonly File[], - private readonly projectDirectory: string, - private readonly produceSourceMaps: boolean, - getLogger: LoggerFactoryMethod - ) { - this.compilerOptions = this.adaptCompilerOptions(compilerOptions); - rootFiles.forEach((file) => (this.files[normalizeFileForTypescript(file.name)] = new ScriptFile(file.name, file.textContent))); - const host = this.createLanguageServiceHost(); - this.languageService = ts.createLanguageService(host); - this.logger = getLogger(TranspilingLanguageService.name); - this.diagnosticsFormatter = { - getCanonicalFileName: (fileName) => fileName, - getCurrentDirectory: () => projectDirectory, - getNewLine: () => os.EOL, - }; - } - - /** - * Adapts compiler options to emit sourceMap files and disable other options for performance reasons - * - * @param source The unchanged compiler options - */ - private adaptCompilerOptions(source: ts.CompilerOptions) { - const compilerOptions = Object.assign({}, source); - compilerOptions.sourceMap = this.produceSourceMaps; - compilerOptions.inlineSourceMap = false; - compilerOptions.declaration = false; - return compilerOptions; - } - - /** - * Replaces the content of the given text files - * @param mutantCandidate The mutant used to replace the original source - */ - public replace(replacements: readonly File[]) { - replacements.forEach((replacement) => this.files[normalizeFileForTypescript(replacement.name)].replace(replacement.textContent)); - } - - public getSemanticDiagnostics(files: readonly File[]) { - const fileNames = files.map((file) => file.name); - const errors = flatMap(fileNames, (fileName) => this.languageService.getSemanticDiagnostics(normalizeFileForTypescript(fileName))); - return ts.formatDiagnostics(errors, this.diagnosticsFormatter); - } - - /** - * Get the output text file for given source file - * @param sourceFile Emit output file based on this source file - * @return Map Returns a map of source file names with their output files. - * If all output files are bundled together, only returns the output file once using the first file as key - */ - public emit(fileName: string): EmitOutput { - const emittedFiles = this.languageService.getEmitOutput(normalizeFileForTypescript(fileName)).outputFiles; - const jsFile = emittedFiles.find(isJavaScriptFile); - const mapFile = emittedFiles.find(isMapFile); - if (jsFile) { - const outputFiles: File[] = [new File(normalizeFileFromTypescript(jsFile.name), jsFile.text)]; - if (mapFile) { - outputFiles.push(new File(normalizeFileFromTypescript(mapFile.name), mapFile.text)); - } - return { singleResult: !!this.compilerOptions.outFile, outputFiles }; - } else { - throw new Error(`Emit error! Could not emit file ${fileName}`); - } - } - - private createLanguageServiceHost(): ts.LanguageServiceHost { - return { - directoryExists: ts.sys.directoryExists, - fileExists: ts.sys.fileExists, - getCompilationSettings: () => this.compilerOptions, - getCurrentDirectory: () => path.resolve(this.projectDirectory), - getDefaultLibFileName: ts.getDefaultLibFileName, - getDirectories: ts.sys.getDirectories, - getScriptFileNames: () => { - return Object.keys(this.files); - }, - getScriptSnapshot: (fileName) => { - this.pullFileIntoMemoryIfNeeded(fileName); - return this.files[fileName] && ts.ScriptSnapshot.fromString(this.files[fileName].content); - }, - getScriptVersion: (fileName) => { - this.pullFileIntoMemoryIfNeeded(fileName); - return this.files[fileName] && this.files[fileName].version.toString(); - }, - readDirectory: ts.sys.readDirectory, - readFile: ts.sys.readFile, - }; - } - - private pullFileIntoMemoryIfNeeded(fileName: string) { - if (!this.files[fileName]) { - const resolvedFile = this.resolveFileName(fileName); - if (fs.existsSync(resolvedFile)) { - this.logger.debug('Pulling file into memory: %s', fileName); - this.files[fileName] = new ScriptFile(fileName, fs.readFileSync(resolvedFile, 'utf8')); - } else { - this.logger.error(`File ${resolvedFile} does not exist.`); - } - } - } - - private resolveFileName(fileName: string) { - if (libRegex.exec(fileName)) { - const typescriptLocation = require.resolve('typescript'); - const newFileName = path.resolve(path.dirname(typescriptLocation), fileName); - this.logger.debug(`Resolving lib file ${fileName} to ${newFileName}`); - return newFileName; - } - - return fileName; - } -} diff --git a/packages/typescript/test/helpers/initSinon.ts b/packages/typescript/test/helpers/initSinon.ts deleted file mode 100644 index cd9497c373..0000000000 --- a/packages/typescript/test/helpers/initSinon.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { testInjector } from '@stryker-mutator/test-helpers'; -import * as chai from 'chai'; -import * as chaiAsPromised from 'chai-as-promised'; -import * as sinon from 'sinon'; -import * as sinonChai from 'sinon-chai'; - -chai.use(sinonChai); -chai.use(chaiAsPromised); -afterEach(() => { - sinon.restore(); - testInjector.reset(); -}); diff --git a/packages/typescript/test/helpers/initSourceMaps.ts b/packages/typescript/test/helpers/initSourceMaps.ts deleted file mode 100644 index fcfbfda16c..0000000000 --- a/packages/typescript/test/helpers/initSourceMaps.ts +++ /dev/null @@ -1 +0,0 @@ -import 'source-map-support/register'; diff --git a/packages/typescript/test/integration/allowJS.it.spec.ts b/packages/typescript/test/integration/allowJS.it.spec.ts deleted file mode 100644 index 299eb9d74f..0000000000 --- a/packages/typescript/test/integration/allowJS.it.spec.ts +++ /dev/null @@ -1,33 +0,0 @@ -import * as fs from 'fs'; -import * as path from 'path'; - -import { File } from '@stryker-mutator/api/core'; -import { testInjector, factory } from '@stryker-mutator/test-helpers'; -import { expect } from 'chai'; - -import TypescriptOptionsEditor from '../../src/TypescriptOptionsEditor'; -import TypescriptTranspiler from '../../src/TypescriptTranspiler'; -import { TypescriptWithStrykerOptions } from '../../src/TypescriptWithStrykerOptions'; - -describe('AllowJS integration', () => { - let options: TypescriptWithStrykerOptions; - let inputFiles: File[]; - - beforeEach(() => { - const optionsEditor = testInjector.injector.injectClass(TypescriptOptionsEditor); - options = factory.strykerOptions() as TypescriptWithStrykerOptions; - options.tsconfigFile = path.resolve(__dirname, '..', '..', 'testResources', 'allowJS', 'tsconfig.json'); - optionsEditor.edit(options); - inputFiles = (options.tsconfig!.fileNames as string[]).map((fileName) => new File(fileName, fs.readFileSync(fileName, 'utf8'))); - }); - - it('should be able to transpile source code', async () => { - const transpiler = new TypescriptTranspiler(options, /*produceSourceMaps: */ false, () => testInjector.logger); - const outputFiles = await transpiler.transpile(inputFiles); - expect(outputFiles.length).to.eq(2); - expect(outputFiles.map((f) => f.name)).deep.eq([ - path.resolve(__dirname, '..', '..', 'testResources', 'allowJS', 'dist', 'math.js'), - path.resolve(__dirname, '..', '..', 'testResources', 'allowJS', 'dist', 'useMath.js'), - ]); - }); -}); diff --git a/packages/typescript/test/integration/allowJsonFile.it.spec.ts b/packages/typescript/test/integration/allowJsonFile.it.spec.ts deleted file mode 100644 index 14fa8f6037..0000000000 --- a/packages/typescript/test/integration/allowJsonFile.it.spec.ts +++ /dev/null @@ -1,42 +0,0 @@ -import * as fs from 'fs'; -import * as path from 'path'; - -import { File } from '@stryker-mutator/api/core'; -import { testInjector, factory } from '@stryker-mutator/test-helpers'; -import { expect } from 'chai'; -import { ParsedCommandLine } from 'typescript'; - -import TypescriptOptionsEditor from '../../src/TypescriptOptionsEditor'; -import TypescriptTranspiler from '../../src/TypescriptTranspiler'; -import { TypescriptWithStrykerOptions } from '../../src/TypescriptWithStrykerOptions'; - -describe('AllowJsonFiles integration', () => { - let options: TypescriptWithStrykerOptions; - let inputFiles: File[]; - - beforeEach(() => { - const optionsEditor = testInjector.injector.injectClass(TypescriptOptionsEditor); - options = factory.strykerOptions(); - options.tsconfigFile = path.resolve(__dirname, '..', '..', 'testResources', 'allowJsonFiles', 'tsconfig.json'); - optionsEditor.edit(options); - inputFiles = (options.tsconfig!.fileNames as string[]).map((fileName) => new File(fileName, fs.readFileSync(fileName, 'utf8'))); - }); - - it('should be able to transpile source code', async () => { - const transpiler = new TypescriptTranspiler(options, /*produceSourceMaps: */ false, () => testInjector.logger); - const outputFiles = await transpiler.transpile(inputFiles); - expect(outputFiles.length).to.eq(2); - expect(outputFiles.map((f) => f.name)).deep.eq([ - path.resolve(__dirname, '..', '..', 'testResources', 'allowJsonFiles', 'json.json'), - path.resolve(__dirname, '..', '..', 'testResources', 'allowJsonFiles', 'index.js'), - ]); - }); - - it('should be able to transpile source code to outDir', async () => { - ((options.tsconfig as unknown) as ParsedCommandLine).options.outDir = 'dist'; - const transpiler = new TypescriptTranspiler(options, /*produceSourceMaps: */ false, () => testInjector.logger); - const outputFiles = await transpiler.transpile(inputFiles); - expect(outputFiles.length).to.eq(2); - expect(outputFiles.map((f) => f.name)).deep.eq([path.join('dist', 'index.js'), path.join('dist', 'json.json')]); - }); -}); diff --git a/packages/typescript/test/integration/configEditor.it.spec.ts b/packages/typescript/test/integration/configEditor.it.spec.ts deleted file mode 100644 index 76311b9e0f..0000000000 --- a/packages/typescript/test/integration/configEditor.it.spec.ts +++ /dev/null @@ -1,23 +0,0 @@ -import * as path from 'path'; - -import { testInjector, factory } from '@stryker-mutator/test-helpers'; -import { expect } from 'chai'; - -import TypescriptOptionsEditor from '../../src/TypescriptOptionsEditor'; -import { TypescriptWithStrykerOptions } from '../../src/TypescriptWithStrykerOptions'; - -function resolveSampleProject(relativeFileName: string) { - return path.resolve(__dirname, '..', '..', 'testResources', 'sampleProject', relativeFileName); -} - -describe('Read TS Config file integration', () => { - it('should discover files like TS does', () => { - const config = factory.strykerOptions() as TypescriptWithStrykerOptions; - config.tsconfigFile = resolveSampleProject('tsconfig.json'); - testInjector.injector.injectClass(TypescriptOptionsEditor).edit(config); - expect((config.tsconfig!.fileNames as string[]).map(path.normalize)).deep.eq([ - resolveSampleProject('math.ts'), - resolveSampleProject('useMath.ts'), - ]); - }); -}); diff --git a/packages/typescript/test/integration/ownDogFood.it.spec.ts b/packages/typescript/test/integration/ownDogFood.it.spec.ts deleted file mode 100644 index a6ad6bd6ee..0000000000 --- a/packages/typescript/test/integration/ownDogFood.it.spec.ts +++ /dev/null @@ -1,44 +0,0 @@ -import * as fs from 'fs'; -import * as path from 'path'; - -import { File } from '@stryker-mutator/api/core'; -import { testInjector, factory } from '@stryker-mutator/test-helpers'; -import { expect } from 'chai'; - -import TypescriptOptionsEditor from '../../src/TypescriptOptionsEditor'; -import TypescriptTranspiler from '../../src/TypescriptTranspiler'; -import { TypescriptWithStrykerOptions } from '../../src/TypescriptWithStrykerOptions'; - -describe('@stryker-mutator/typescript', () => { - let options: TypescriptWithStrykerOptions; - let inputFiles: File[]; - - beforeEach(() => { - const optionsEditor = testInjector.injector.injectClass(TypescriptOptionsEditor); - options = factory.strykerOptions(); - options.tsconfigFile = path.resolve(__dirname, '..', '..', 'tsconfig.src.json'); - optionsEditor.edit(options); - (options.tsconfig!.options as any)['outDir'] = 'blaat'; - inputFiles = (options.tsconfig!.fileNames as string[]).map((fileName) => new File(fileName, fs.readFileSync(fileName, 'utf8'))); - }); - - it('should be able to transpile itself', async () => { - const transpiler = new TypescriptTranspiler(options, /*produceSourceMaps: */ true, () => testInjector.logger); - const outputFiles = await transpiler.transpile(inputFiles); - expect(outputFiles.length).greaterThan(10); - }); - - it('should result in an error if a variable is declared as any and noImplicitAny = true', async () => { - const transpiler = new TypescriptTranspiler(options, /*produceSourceMaps: */ true, () => testInjector.logger); - inputFiles[0] = new File(inputFiles[0].name, inputFiles[0].textContent + 'function foo(bar) { return bar; } '); - return expect(transpiler.transpile(inputFiles)).rejectedWith("error TS7006: Parameter 'bar' implicitly has an 'any' type"); - }); - - it('should not result in an error if a variable is declared as any and noImplicitAny = false', async () => { - options.tsconfig!.noImplicitAny = false; - inputFiles[0] = new File(inputFiles[0].name, inputFiles[0].textContent + 'const shouldResultInError = 3'); - const transpiler = new TypescriptTranspiler(options, /*produceSourceMaps: */ true, () => testInjector.logger); - const outputFiles = await transpiler.transpile(inputFiles); - expect(outputFiles).lengthOf.greaterThan(0); - }); -}); diff --git a/packages/typescript/test/integration/sample.it.spec.ts b/packages/typescript/test/integration/sample.it.spec.ts deleted file mode 100644 index 3f3e0c99c5..0000000000 --- a/packages/typescript/test/integration/sample.it.spec.ts +++ /dev/null @@ -1,71 +0,0 @@ -import * as fs from 'fs'; -import * as path from 'path'; - -import { File } from '@stryker-mutator/api/core'; -import { Mutant } from '@stryker-mutator/api/mutant'; -import { testInjector, factory } from '@stryker-mutator/test-helpers'; -import { expect } from 'chai'; - -import TypescriptOptionsEditor from '../../src/TypescriptOptionsEditor'; -import { typescriptMutatorFactory } from '../../src/TypescriptMutator'; -import TypescriptTranspiler from '../../src/TypescriptTranspiler'; -import { TypescriptWithStrykerOptions } from '../../src/TypescriptWithStrykerOptions'; - -describe('Sample integration', () => { - let options: TypescriptWithStrykerOptions; - let inputFiles: File[]; - - beforeEach(() => { - const optionsEditor = testInjector.injector.injectClass(TypescriptOptionsEditor); - options = factory.strykerOptions(); - options.tsconfigFile = path.resolve(__dirname, '..', '..', 'testResources', 'sampleProject', 'tsconfig.json'); - optionsEditor.edit(options); - inputFiles = (options.tsconfig!.fileNames as string[]).map((fileName) => new File(fileName, fs.readFileSync(fileName, 'utf8'))); - testInjector.options = options; - }); - - it('should be able to generate mutants', () => { - // Generate mutants - const mutator = testInjector.injector.injectFunction(typescriptMutatorFactory); - const mutants = mutator.mutate(inputFiles); - expect(mutants.length).to.eq(5); - }); - - it('should be able to transpile source code', async () => { - const transpiler = new TypescriptTranspiler(options, /*produceSourceMaps: */ false, () => testInjector.logger); - const outputFiles = await transpiler.transpile(inputFiles); - expect(outputFiles.length).to.eq(2); - }); - - it('should be able to produce source maps', async () => { - const transpiler = new TypescriptTranspiler(options, /*produceSourceMaps: */ true, () => testInjector.logger); - const outputFiles = await transpiler.transpile(inputFiles); - expect(outputFiles).lengthOf(4); - const mapFiles = outputFiles.filter((file) => file.name.endsWith('.map')); - expect(mapFiles).lengthOf(2); - expect(mapFiles.map((file) => file.name)).deep.eq([ - path.resolve(__dirname, '..', '..', 'testResources', 'sampleProject', 'math.js.map'), - path.resolve(__dirname, '..', '..', 'testResources', 'sampleProject', 'useMath.js.map'), - ]); - }); - - it('should be able to transpile mutated code', async () => { - // Transpile mutants - const mutator = testInjector.injector.injectFunction(typescriptMutatorFactory); - const mutants = mutator.mutate(inputFiles); - const transpiler = new TypescriptTranspiler(options, /*produceSourceMaps: */ false, () => testInjector.logger); - transpiler.transpile(inputFiles); - const mathDotTS = inputFiles.filter((file) => file.name.endsWith('math.ts'))[0]; - const [firstArithmeticOperatorMutant, stringSubtractMutant] = mutants.filter((m) => m.mutatorName === 'ArithmeticOperator'); - const correctResult = await transpiler.transpile([mutateFile(mathDotTS, firstArithmeticOperatorMutant)]); - await expect(transpiler.transpile([mutateFile(mathDotTS, stringSubtractMutant)])).rejectedWith( - "error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type." - ); - expect(correctResult).lengthOf(1); - expect(path.resolve(correctResult[0].name)).eq(path.resolve(path.dirname(mathDotTS.name), 'math.js')); - }); - - function mutateFile(file: File, mutant: Mutant): File { - return new File(file.name, `${file.content.slice(0, mutant.range[0])}${mutant.replacement}${file.content.slice(mutant.range[1])}`); - } -}); diff --git a/packages/typescript/test/integration/useHeaderFile.it.spec.ts b/packages/typescript/test/integration/useHeaderFile.it.spec.ts deleted file mode 100644 index 74342cc682..0000000000 --- a/packages/typescript/test/integration/useHeaderFile.it.spec.ts +++ /dev/null @@ -1,34 +0,0 @@ -import * as fs from 'fs'; -import * as path from 'path'; - -import { File } from '@stryker-mutator/api/core'; -import { commonTokens } from '@stryker-mutator/api/plugin'; -import { testInjector, factory } from '@stryker-mutator/test-helpers'; -import { expect } from 'chai'; - -import TypescriptOptionsEditor from '../../src/TypescriptOptionsEditor'; -import TypescriptTranspiler from '../../src/TypescriptTranspiler'; -import { TypescriptWithStrykerOptions } from '../../src/TypescriptWithStrykerOptions'; - -describe('Use header file integration', () => { - let options: TypescriptWithStrykerOptions; - let inputFiles: File[]; - let transpiler: TypescriptTranspiler; - - beforeEach(() => { - const optionsEditor = testInjector.injector.injectClass(TypescriptOptionsEditor); - options = factory.strykerOptions(); - options.tsconfigFile = path.resolve(__dirname, '..', '..', 'testResources', 'useHeaderFile', 'tsconfig.json'); - optionsEditor.edit(options); - inputFiles = (options.tsconfig!.fileNames as string[]).map((fileName) => new File(fileName, fs.readFileSync(fileName, 'utf8'))); - transpiler = testInjector.injector - .provideValue(commonTokens.produceSourceMaps, false) - .provideValue(commonTokens.options, options) - .injectClass(TypescriptTranspiler); - }); - - it('should be able to transpile source code', async () => { - const outputFiles = await transpiler.transpile(inputFiles); - expect(outputFiles.length).to.eq(2); - }); -}); diff --git a/packages/typescript/test/unit/TypescriptMutator.spec.ts b/packages/typescript/test/unit/TypescriptMutator.spec.ts deleted file mode 100644 index d9c3a0aab1..0000000000 --- a/packages/typescript/test/unit/TypescriptMutator.spec.ts +++ /dev/null @@ -1,165 +0,0 @@ -import * as fs from 'fs'; -import * as path from 'path'; - -import { File } from '@stryker-mutator/api/core'; -import { testInjector } from '@stryker-mutator/test-helpers'; -import { expect } from 'chai'; -import * as ts from 'typescript'; - -import NodeMutator, { NodeReplacement } from '../../src/mutator/NodeMutator'; -import { MUTATORS_TOKEN, TypescriptMutator, typescriptMutatorFactory } from '../../src/TypescriptMutator'; - -class FunctionDeclarationMutator extends NodeMutator { - public name = 'FunctionDeclarationForTest'; - public guard(node: ts.Node): node is ts.FunctionDeclaration { - return node.kind === ts.SyntaxKind.FunctionDeclaration; - } - protected identifyReplacements(node: ts.FunctionDeclaration): NodeReplacement[] { - return [ - { node, replacement: '// Function declaration removed' }, - { node, replacement: 'changedToOtherCall()' }, - ]; - } -} - -class SourceFileMutator extends NodeMutator { - public name = 'SourceFileForTest'; - public guard(node: ts.Node): node is ts.SourceFile { - return node.kind === ts.SyntaxKind.SourceFile; - } - protected identifyReplacements(node: ts.SourceFile): NodeReplacement[] { - return [{ node, replacement: '"stryker was here"' }]; - } -} - -function createSut() { - return testInjector.injector - .provideValue(MUTATORS_TOKEN, [new SourceFileMutator(), new FunctionDeclarationMutator()]) - .injectClass(TypescriptMutator); -} - -describe('TypescriptMutator', () => { - let sut: TypescriptMutator; - - it('should register all mutators by default', () => { - // Arrange - const expectedMutatorNames = fs - .readdirSync(path.resolve(__dirname, '..', '..', 'src', 'mutator')) - .filter((mutatorFile) => path.extname(mutatorFile) === '.js' && mutatorFile !== 'NodeMutator.js' && mutatorFile !== 'index.js') - .map((fileName) => fileName.substr(0, fileName.length - 'Mutator.js'.length)); - - // Act - const actualMutators = testInjector.injector.injectFunction(typescriptMutatorFactory).mutators.map((m) => m.name); - - // Assert - expect(expectedMutatorNames).length.greaterThan(2); // sanity check - expectedMutatorNames.forEach((mutatorName) => expect(actualMutators).includes(mutatorName)); - }); - - describe('using 2 mutators', () => { - let file1: File; - let file2: File; - - beforeEach(() => { - sut = createSut(); - file1 = new File( - 'file1.ts', - `function add(n...: number[]) { - return n.sum(); - } - const a = add(1, 3, 4, 5);` - ); - file2 = new File( - 'file2.ts', - `function subtract(n...: numbers[]){ - return n[0] - n.slice(1).sum(); - } - const b = subtract(10, 3, 4);` - ); - }); - - it('should deliver 6 mutants', () => { - const mutants = sut.mutate([file1, file2]); - expect(mutants.filter((mutant) => mutant.mutatorName === 'SourceFileForTest')).lengthOf(2); - expect(mutants.filter((mutant) => mutant.mutatorName === 'FunctionDeclarationForTest')).lengthOf(4); - }); - - describe('declaration nodes', () => { - beforeEach(() => { - sut = createSut(); - }); - - it('should not skip a node when it does not have a declare modifier', () => { - // Arrange - file1 = new File('file1.ts', 'function mutated(a: number, b: number);'); - - // Act - const mutants = sut.mutate([file1]); - - // Assert - expect(mutants).to.deep.equal([ - { - fileName: 'file1.ts', - mutatorName: 'SourceFileForTest', - range: [0, 39], - replacement: '"stryker was here"', - }, - { - fileName: 'file1.ts', - mutatorName: 'FunctionDeclarationForTest', - range: [0, 39], - replacement: '// Function declaration removed', - }, - { - fileName: 'file1.ts', - mutatorName: 'FunctionDeclarationForTest', - range: [0, 39], - replacement: 'changedToOtherCall()', - }, - ]); - }); - - it('should skip a node when it has a declare modifier', () => { - // Arrange - file1 = new File('file1.ts', 'declare function notMutated(a: number, b: number);'); - - // Act - const mutants = sut.mutate([file1]); - - // Assert - expect(mutants).to.deep.equal([ - { - fileName: 'file1.ts', - mutatorName: 'SourceFileForTest', - range: [0, 50], - replacement: '"stryker was here"', - }, - ]); - }); - - it('should skip a node when it is an interface', () => { - // Arrange - file1 = new File( - 'file1.ts', - `interface Hello { - value: string; - sortable?: true; - }` - ); - - // Act - const mutants = sut.mutate([file1]); - - // Assert - expect(mutants).to.deep.equal([ - { - fileName: 'file1.ts', - mutatorName: 'SourceFileForTest', - range: [0, 85], - replacement: '"stryker was here"', - }, - ]); - }); - }); - }); -}); diff --git a/packages/typescript/test/unit/TypescriptOptionsEditor.spec.ts b/packages/typescript/test/unit/TypescriptOptionsEditor.spec.ts deleted file mode 100644 index 511aabf052..0000000000 --- a/packages/typescript/test/unit/TypescriptOptionsEditor.spec.ts +++ /dev/null @@ -1,101 +0,0 @@ -import * as fs from 'fs'; -import * as path from 'path'; - -import sinon = require('sinon'); -import { expect } from 'chai'; -import * as ts from 'typescript'; -import { testInjector, factory } from '@stryker-mutator/test-helpers'; -import { match, SinonStub } from 'sinon'; - -import { TypescriptWithStrykerOptions } from '../../src/TypescriptWithStrykerOptions'; - -import TypescriptOptionsEditor from './../../src/TypescriptOptionsEditor'; - -describe(TypescriptOptionsEditor.name, () => { - let readFileSyncStub: SinonStub; - let options: TypescriptWithStrykerOptions; - let sut: TypescriptOptionsEditor; - - beforeEach(() => { - readFileSyncStub = sinon.stub(fs, 'readFileSync'); - options = factory.strykerOptions(); - sut = testInjector.injector.injectClass(TypescriptOptionsEditor); - }); - - it('should not load any config if "tsconfigFile" is not specified', () => { - sut.edit(options); - expect(options.tsconfigFile).undefined; - expect(testInjector.logger.debug).calledWith("No '%s' specified, not loading any config", 'tsconfigFile'); - }); - - it('should load the given tsconfig file', () => { - options.tsconfigFile = 'tsconfig.json'; - readFileSyncStub.returns(`{ - "compilerOptions": { - "module": "commonjs", - "noImplicitAny": true, - "removeComments": true, - "preserveConstEnums": true, - "sourceMap": true - }, - "exclude": [ - "node_modules", - "src/**/*.d.ts", - "test/**/*.d.ts", - "testResources" - ] - }`); - sut.edit(options, parseConfigHost()); - expect(fs.readFileSync).calledWith(path.resolve('tsconfig.json')); - expect(options.tsconfig!.options).include({ - configFilePath: path.resolve('tsconfig.json').replace(/\\/g, '/'), - module: ts.ModuleKind.CommonJS, - noImplicitAny: true, - preserveConstEnums: true, - project: path.resolve('.').replace(/\\/g, '/'), - removeComments: true, - sourceMap: true, - }); - expect(options.tsconfig!.fileNames).deep.eq(['file1.ts', 'file2.ts']); - }); - - it('should override quality options', () => { - options.tsconfigFile = 'tsconfig.json'; - readFileSyncStub.returns(`{ - "compilerOptions": { - "allowUnreachableCode": false, - "noUnusedLocals": true, - "noUnusedParameters": true - } - }`); - sut.edit(options, parseConfigHost()); - expect(options.tsconfig!.options).include({ - allowUnreachableCode: true, - noUnusedLocals: false, - noUnusedParameters: false, - }); - }); - - it('should log errors on failure during load', () => { - readFileSyncStub.returns('invalid json'); - options.tsconfigFile = 'tsconfig.json'; - expect(() => sut.edit(options)).throws("error TS1005: '{' expected."); - }); - - it('should log errors on failure during load of extending file', () => { - readFileSyncStub.returns('{ "extends": "./parent.tsconfig.json" }'); - options.tsconfigFile = 'tsconfig.json'; - sut.edit(options, parseConfigHost({ readFile: () => 'invalid json' })); - expect(testInjector.logger.error).calledWithMatch(match("error TS1005: '{' expected.")); - }); - - function parseConfigHost(overrides?: Partial): ts.ParseConfigHost { - const defaults: ts.ParseConfigHost = { - fileExists: () => true, - readDirectory: () => ['file1.ts', 'file2.ts'], - readFile: () => '', - useCaseSensitiveFileNames: true, - }; - return Object.assign({}, defaults, overrides); - } -}); diff --git a/packages/typescript/test/unit/TypescriptTranspiler.spec.ts b/packages/typescript/test/unit/TypescriptTranspiler.spec.ts deleted file mode 100644 index 2f0db27f80..0000000000 --- a/packages/typescript/test/unit/TypescriptTranspiler.spec.ts +++ /dev/null @@ -1,145 +0,0 @@ -import { File } from '@stryker-mutator/api/core'; -import { commonTokens } from '@stryker-mutator/api/plugin'; -import { testInjector } from '@stryker-mutator/test-helpers'; -import { expect } from 'chai'; -import { serialize } from 'surrial'; - -import sinon = require('sinon'); - -import TranspileFilter from '../../src/transpiler/TranspileFilter'; -import TranspilingLanguageService, * as transpilingLanguageService from '../../src/transpiler/TranspilingLanguageService'; -import { EmitOutput } from '../../src/transpiler/TranspilingLanguageService'; -import TypescriptTranspiler from '../../src/TypescriptTranspiler'; -import { TypescriptWithStrykerOptions } from '../../src/TypescriptWithStrykerOptions'; - -describe(TypescriptTranspiler.name, () => { - let languageService: sinon.SinonStubbedInstance; - let sut: TypescriptTranspiler; - let transpileFilterMock: sinon.SinonStubbedInstance; - - beforeEach(() => { - languageService = sinon.createStubInstance(TranspilingLanguageService); - transpileFilterMock = { - // Cannot use `mock` as it is an abstract class - isIncluded: sinon.stub(), - }; - sinon.stub(TranspileFilter, 'create').returns(transpileFilterMock); - sinon.stub(transpilingLanguageService, 'default').returns(languageService); - }); - - describe('transpile', () => { - beforeEach(() => { - languageService.getSemanticDiagnostics.returns([]); // no errors by default - sut = testInjector.injector.provideValue(commonTokens.produceSourceMaps, true).injectClass(TypescriptTranspiler); - }); - - it('should transpile given files', async () => { - // Arrange - const expected = [new File('foo.js', 'foo'), new File('bar.js', 'bar')]; - arrangeIncludedFiles(); - languageService.emit.withArgs('foo.ts').returns(multiResult(expected[0])).withArgs('bar.ts').returns(multiResult(expected[1])); - - // Act - const outputFiles = await sut.transpile([new File('foo.ts', ''), new File('bar.ts', '')]); - - // Assert - expectFilesEqual(outputFiles, expected); - }); - - it('should keep file order', async () => { - // Arrange - const input = [new File('file1.js', ''), new File('file2.ts', ''), new File('file4.ts', '')]; - arrangeIncludedFiles(input.slice(1)); - languageService.emit - .withArgs('file2.ts') - .returns(multiResult(new File('file2.js', 'file2'))) - .withArgs('file4.ts') - .returns(multiResult(new File('file4.js', 'file4'))); - - // Act - const outputFiles = await sut.transpile(input); - - // Assert - expectFilesEqual(outputFiles, [input[0], new File('file2.js', 'file2'), new File('file4.js', 'file4')]); - }); - - it('should not transform declaration files', async () => { - // Arrange - const input = [new File('file1.ts', ''), new File('file2.d.ts', '')]; - arrangeIncludedFiles(); - languageService.emit.returns(multiResult(new File('file1.js', ''))); - - // Act - const outputFiles = await sut.transpile(input); - - // Assert - expectFilesEqual(outputFiles, [new File('file1.js', ''), input[1]]); - expect(languageService.emit).calledOnce; - expect(languageService.emit).calledWith('file1.ts'); - }); - - it("should not transform json files that don't have output", async () => { - // Arrange - (testInjector.options as TypescriptWithStrykerOptions).tsconfig = { - options: { - // no outDir - }, - }; - const input = [new File('file1.json', '')]; - arrangeIncludedFiles(); - - // Act - const outputFiles = await sut.transpile(input); - - // Assert - expectFilesEqual(outputFiles, [new File('file1.json', ''), input[0]]); - expect(languageService.emit).not.called; - }); - - it('should remove duplicate files (issue 1318)', async () => { - // Arrange - const inputFile = new File('file1.ts', 'const foo: number = 42;'); - const expectedOutputFile = new File('file1.js', 'const foo = 42;'); - arrangeIncludedFiles([inputFile]); - const input = [inputFile, new File('file1.js', 'js content')]; - languageService.emit.returns(multiResult(expectedOutputFile)); - - // Act - const outputFiles = await sut.transpile(input); - - // Assert - expect(outputFiles).lengthOf(1); - expect(outputFiles[0]).eq(expectedOutputFile); - }); - - it('should reject errors when there are diagnostic messages', async () => { - languageService.getSemanticDiagnostics.returns('foobar'); - arrangeIncludedFiles(); - const input = [new File('file1.ts', 'file1'), new File('file2.ts', 'file2')]; - return expect(sut.transpile(input)).rejectedWith('foobar'); - }); - }); - - function expectFilesEqual(actual: readonly File[], expected: readonly File[]) { - expect(serialize(orderByName(actual))).eq(serialize(orderByName(expected))); - } - - function orderByName(files: readonly File[]) { - files.slice().sort((a, b) => a.name.localeCompare(b.name)); - } - - function multiResult(file: File): EmitOutput { - return { - outputFiles: [file], - singleResult: false, - }; - } - - function arrangeIncludedFiles(files?: File[]) { - if (files) { - transpileFilterMock.isIncluded.callsFake((fileName: string) => files.some((file) => file.name === fileName)); - } else { - transpileFilterMock.isIncluded.returns(true); - } - } -}); diff --git a/packages/typescript/test/unit/helpers/tsHelpers.spec.ts b/packages/typescript/test/unit/helpers/tsHelpers.spec.ts deleted file mode 100644 index c09433116a..0000000000 --- a/packages/typescript/test/unit/helpers/tsHelpers.spec.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { File } from '@stryker-mutator/api/core'; -import { expect } from 'chai'; -import * as semver from 'semver'; -import * as ts from 'typescript'; - -import sinon = require('sinon'); - -import * as tsHelpers from '../../../src/helpers/tsHelpers'; - -describe('tsHelpers', () => { - let satisfiesStub: sinon.SinonStub; - - beforeEach(() => { - satisfiesStub = sinon.stub(semver, 'satisfies'); - }); - - describe('guardTypescriptVersion', () => { - it('should throw an error when installed typescript version does not satisfy >=2.4', () => { - satisfiesStub.returns(false); - expect(() => tsHelpers.guardTypescriptVersion()).throws( - `Installed typescript version ${ts.version} is not supported by stryker-typescript. Please install version 2.5 or higher (\`npm install typescript@^2.5\`).` - ); - expect(satisfiesStub).calledWith(ts.version, '>=2.4'); - }); - - it('should not throw an error if installed version satisfies >=2.4', () => { - satisfiesStub.returns(true); - expect(() => tsHelpers.guardTypescriptVersion()).not.throws(); - }); - }); - - describe('parseFile', () => { - it('should also set parent nodes', () => { - const input = new File('file.ts', 'const b: string = "hello world";'); - const actual = tsHelpers.parseFile(input, undefined); - ts.forEachChild(actual, (node) => { - expect(node.parent).ok; - }); - }); - }); -}); diff --git a/packages/typescript/test/unit/mutator/ArithmeticOperatorMutator.spec.ts b/packages/typescript/test/unit/mutator/ArithmeticOperatorMutator.spec.ts deleted file mode 100644 index e91229325d..0000000000 --- a/packages/typescript/test/unit/mutator/ArithmeticOperatorMutator.spec.ts +++ /dev/null @@ -1,7 +0,0 @@ -import ArithmeticOperatorMutatorSpec from '@stryker-mutator/mutator-specification/src/ArithmeticOperatorMutatorSpec'; - -import ArithmeticOperatorMutator from '../../../src/mutator/ArithmeticOperatorMutator'; - -import { verifySpecification } from './mutatorAssertions'; - -verifySpecification(ArithmeticOperatorMutatorSpec, ArithmeticOperatorMutator); diff --git a/packages/typescript/test/unit/mutator/ArrayDeclarationMutator.spec.ts b/packages/typescript/test/unit/mutator/ArrayDeclarationMutator.spec.ts deleted file mode 100644 index c205b16337..0000000000 --- a/packages/typescript/test/unit/mutator/ArrayDeclarationMutator.spec.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { ArrayDeclarationMutatorSpec } from '@stryker-mutator/mutator-specification'; - -import ArrayDeclarationMutator from '../../../src/mutator/ArrayDeclarationMutator'; - -import { verifySpecification } from './mutatorAssertions'; - -verifySpecification(ArrayDeclarationMutatorSpec, ArrayDeclarationMutator); diff --git a/packages/typescript/test/unit/mutator/ArrowFunctionMutator.spec.ts b/packages/typescript/test/unit/mutator/ArrowFunctionMutator.spec.ts deleted file mode 100644 index 0c4c1ccb75..0000000000 --- a/packages/typescript/test/unit/mutator/ArrowFunctionMutator.spec.ts +++ /dev/null @@ -1,7 +0,0 @@ -import ArrowFunctionMutatorSpec from '@stryker-mutator/mutator-specification/src/ArrowFunctionMutatorSpec'; - -import ArrowFunctionMutator from '../../../src/mutator/ArrowFunctionMutator'; - -import { verifySpecification } from './mutatorAssertions'; - -verifySpecification(ArrowFunctionMutatorSpec, ArrowFunctionMutator); diff --git a/packages/typescript/test/unit/mutator/BlockStatementMutator.spec.ts b/packages/typescript/test/unit/mutator/BlockStatementMutator.spec.ts deleted file mode 100644 index e1d04fcb58..0000000000 --- a/packages/typescript/test/unit/mutator/BlockStatementMutator.spec.ts +++ /dev/null @@ -1,7 +0,0 @@ -import BlockStatementMutatorSpec from '@stryker-mutator/mutator-specification/src/BlockStatementMutatorSpec'; - -import BlockStatementMutator from '../../../src/mutator/BlockStatementMutator'; - -import { verifySpecification } from './mutatorAssertions'; - -verifySpecification(BlockStatementMutatorSpec, BlockStatementMutator); diff --git a/packages/typescript/test/unit/mutator/BooleanLiteralMutator.spec.ts b/packages/typescript/test/unit/mutator/BooleanLiteralMutator.spec.ts deleted file mode 100644 index 2cdffa0b11..0000000000 --- a/packages/typescript/test/unit/mutator/BooleanLiteralMutator.spec.ts +++ /dev/null @@ -1,7 +0,0 @@ -import BooleanLiteralMutatorSpec from '@stryker-mutator/mutator-specification/src/BooleanLiteralMutatorSpec'; - -import BooleanLiteralMutator from '../../../src/mutator/BooleanLiteralMutator'; - -import { verifySpecification } from './mutatorAssertions'; - -verifySpecification(BooleanLiteralMutatorSpec, BooleanLiteralMutator); diff --git a/packages/typescript/test/unit/mutator/ConditionalExpressionMutator.spec.ts b/packages/typescript/test/unit/mutator/ConditionalExpressionMutator.spec.ts deleted file mode 100644 index b1ec23f131..0000000000 --- a/packages/typescript/test/unit/mutator/ConditionalExpressionMutator.spec.ts +++ /dev/null @@ -1,7 +0,0 @@ -import ConditionalExpressionMutatorSpec from '@stryker-mutator/mutator-specification/src/ConditionalExpressionMutatorSpec'; - -import ConditionalExpressionMutator from '../../../src/mutator/ConditionalExpressionMutator'; - -import { verifySpecification } from './mutatorAssertions'; - -verifySpecification(ConditionalExpressionMutatorSpec, ConditionalExpressionMutator); diff --git a/packages/typescript/test/unit/mutator/EqualityOperatorMutator.spec.ts b/packages/typescript/test/unit/mutator/EqualityOperatorMutator.spec.ts deleted file mode 100644 index bd428923ec..0000000000 --- a/packages/typescript/test/unit/mutator/EqualityOperatorMutator.spec.ts +++ /dev/null @@ -1,7 +0,0 @@ -import EqualityOperatorMutatorSpec from '@stryker-mutator/mutator-specification/src/EqualityOperatorMutatorSpec'; - -import EqualityOperatorMutator from '../../../src/mutator/EqualityOperatorMutator'; - -import { verifySpecification } from './mutatorAssertions'; - -verifySpecification(EqualityOperatorMutatorSpec, EqualityOperatorMutator); diff --git a/packages/typescript/test/unit/mutator/LogicalOperatorMutator.spec.ts b/packages/typescript/test/unit/mutator/LogicalOperatorMutator.spec.ts deleted file mode 100644 index 75fc7dd215..0000000000 --- a/packages/typescript/test/unit/mutator/LogicalOperatorMutator.spec.ts +++ /dev/null @@ -1,7 +0,0 @@ -import LogicalOperatorMutatorSpec from '@stryker-mutator/mutator-specification/src/LogicalOperatorMutatorSpec'; - -import LogicalOperatorMutator from '../../../src/mutator/LogicalOperatorMutator'; - -import { verifySpecification } from './mutatorAssertions'; - -verifySpecification(LogicalOperatorMutatorSpec, LogicalOperatorMutator); diff --git a/packages/typescript/test/unit/mutator/ObjectLiteralMutator.spec.ts b/packages/typescript/test/unit/mutator/ObjectLiteralMutator.spec.ts deleted file mode 100644 index 9b8a42d277..0000000000 --- a/packages/typescript/test/unit/mutator/ObjectLiteralMutator.spec.ts +++ /dev/null @@ -1,7 +0,0 @@ -import ObjectLiteralMutatorSpec from '@stryker-mutator/mutator-specification/src/ObjectLiteralMutatorSpec'; - -import ObjectLiteralMutator from '../../../src/mutator/ObjectLiteralMutator'; - -import { verifySpecification } from './mutatorAssertions'; - -verifySpecification(ObjectLiteralMutatorSpec, ObjectLiteralMutator); diff --git a/packages/typescript/test/unit/mutator/StringLiteralMutator.spec.ts b/packages/typescript/test/unit/mutator/StringLiteralMutator.spec.ts deleted file mode 100644 index 1d4fdf28f1..0000000000 --- a/packages/typescript/test/unit/mutator/StringLiteralMutator.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import StringLiteralMutatorSpec from '@stryker-mutator/mutator-specification/src/StringLiteralMutatorSpec'; - -import NodeMutator from '../../../src/mutator/NodeMutator'; -import StringLiteralMutator from '../../../src/mutator/StringLiteralMutator'; - -import { expectMutation, verifySpecification } from './mutatorAssertions'; - -verifySpecification(StringLiteralMutatorSpec, StringLiteralMutator); - -describe('StringLiteralMutator - Extras', () => { - let mutator: NodeMutator; - before(() => { - mutator = new StringLiteralMutator(); - }); - - it('should not mutate module declarations', () => { - expectMutation(mutator, 'declare module "new-foo-module";'); - expectMutation(mutator, 'declare module "*!foo" { }'); - }); - - it('should not mutate `import = require()` statements', () => { - expectMutation(mutator, 'import foo = require("foo");'); - }); -}); diff --git a/packages/typescript/test/unit/mutator/UnaryOperatorMutator.spec.ts b/packages/typescript/test/unit/mutator/UnaryOperatorMutator.spec.ts deleted file mode 100644 index aa30c7bbea..0000000000 --- a/packages/typescript/test/unit/mutator/UnaryOperatorMutator.spec.ts +++ /dev/null @@ -1,7 +0,0 @@ -import UnaryOperatorMutatorSpec from '@stryker-mutator/mutator-specification/src/UnaryOperatorMutatorSpec'; - -import UnaryOperatorMutator from '../../../src/mutator/UnaryOperatorMutator'; - -import { verifySpecification } from './mutatorAssertions'; - -verifySpecification(UnaryOperatorMutatorSpec, UnaryOperatorMutator); diff --git a/packages/typescript/test/unit/mutator/UpdateOperatorMutator.spec.ts b/packages/typescript/test/unit/mutator/UpdateOperatorMutator.spec.ts deleted file mode 100644 index 55ed753770..0000000000 --- a/packages/typescript/test/unit/mutator/UpdateOperatorMutator.spec.ts +++ /dev/null @@ -1,7 +0,0 @@ -import UpdateOperatorMutatorSpec from '@stryker-mutator/mutator-specification/src/UpdateOperatorMutatorSpec'; - -import UpdateOperatorMutator from '../../../src/mutator/UpdateOperatorMutator'; - -import { verifySpecification } from './mutatorAssertions'; - -verifySpecification(UpdateOperatorMutatorSpec, UpdateOperatorMutator); diff --git a/packages/typescript/test/unit/mutator/mutatorAssertions.ts b/packages/typescript/test/unit/mutator/mutatorAssertions.ts deleted file mode 100644 index 80d3581803..0000000000 --- a/packages/typescript/test/unit/mutator/mutatorAssertions.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { File } from '@stryker-mutator/api/core'; -import { Mutant } from '@stryker-mutator/api/mutant'; -import ExpectMutation from '@stryker-mutator/mutator-specification/src/ExpectMutation'; -import { expect } from 'chai'; -import * as ts from 'typescript'; - -import { parseFile } from '../../../src/helpers/tsHelpers'; -import NodeMutator from '../../../src/mutator/NodeMutator'; - -export type MutatorConstructor = new () => NodeMutator; - -export function verifySpecification(specification: (name: string, expectMutation: ExpectMutation) => void, MutatorClass: MutatorConstructor): void { - specification(new MutatorClass().name, (actual: string, ...expected: string[]) => expectMutation(new MutatorClass(), actual, ...expected)); -} - -export function expectMutation(mutator: NodeMutator, sourceText: string, ...expectedTexts: string[]) { - const tsFile = new File('file1.tsx', sourceText); - const sourceFile = parseFile(tsFile, undefined); - const mutants = mutate(mutator, sourceFile, sourceFile); - expect(mutants).lengthOf(expectedTexts.length); - const actualMutantTexts = mutants.map((mutant) => mutantToString(mutant, sourceText)).map(format); - expectedTexts.forEach((expected) => { - expect(actualMutantTexts, `was: ${actualMutantTexts.join(',')}`).to.include(format(expected)); - }); -} - -function format(code: string) { - const ast = parseFile(new File('file1.tsx', code), undefined); - return ts.createPrinter().printFile(ast); -} - -function mutate(mutator: NodeMutator, node: ts.Node, sourceFile: ts.SourceFile): Mutant[] { - const mutants: Mutant[] = []; - if (mutator.guard(node)) { - mutants.push(...mutator.mutate(node, sourceFile)); - } - node.forEachChild((child) => { - mutants.push(...mutate(mutator, child, sourceFile)); - }); - return mutants; -} - -function mutantToString(mutant: Mutant, sourceText: string) { - return sourceText.substr(0, mutant.range[0]) + mutant.replacement + sourceText.substr(mutant.range[1]); -} diff --git a/packages/typescript/test/unit/transpile/TranspileFilter.spec.ts b/packages/typescript/test/unit/transpile/TranspileFilter.spec.ts deleted file mode 100644 index 58ad0a1a20..0000000000 --- a/packages/typescript/test/unit/transpile/TranspileFilter.spec.ts +++ /dev/null @@ -1,40 +0,0 @@ -import * as path from 'path'; - -import { expect } from 'chai'; -import { factory } from '@stryker-mutator/test-helpers'; - -import TranspileFilter, { DefaultFilter, TSConfigFilter } from '../../../src/transpiler/TranspileFilter'; - -describe('TranspileFilter', () => { - describe('create', () => { - it('should result in the default filter tsconfig is undefined', () => { - const options = factory.strykerOptions(); - options.tsconfig = undefined; - expect(TranspileFilter.create(options)).instanceof(DefaultFilter); - }); - it('should result in the tsconfig filter if tsconfig is present with files', () => { - const config = factory.strykerOptions(); - config.tsconfig = { fileNames: [] }; - expect(TranspileFilter.create(config)).instanceof(TSConfigFilter); - }); - }); -}); - -describe('DefaultFilter', () => { - it('should only include known typescript extensions', () => { - const sut = new DefaultFilter(); - expect(sut.isIncluded('file1.ts')).eq(true); - expect(sut.isIncluded('file2.bin')).eq(false); - expect(sut.isIncluded('file3.d.ts')).eq(true); - expect(sut.isIncluded('file5.tsx')).eq(true); - }); -}); - -describe('TSConfigFilter', () => { - it('should only include known files', () => { - const sut = new TSConfigFilter({ fileNames: ['include/this.file', 'foobar.ts'] }); - expect(sut.isIncluded(path.normalize('include/this.file'))).eq(true); - expect(sut.isIncluded('foobar.ts')).eq(true); - expect(sut.isIncluded('baz.ts')).eq(false); - }); -}); diff --git a/packages/typescript/testResources/allowJS/math.js b/packages/typescript/testResources/allowJS/math.js deleted file mode 100644 index f489b29c0b..0000000000 --- a/packages/typescript/testResources/allowJS/math.js +++ /dev/null @@ -1,10 +0,0 @@ -"use strict"; -exports.__esModule = true; -function add(a, b) { - return a + b; -} -exports.add = add; -function concat(a, b) { - return a + b; -} -exports.concat = concat; diff --git a/packages/typescript/testResources/allowJS/math.ts b/packages/typescript/testResources/allowJS/math.ts deleted file mode 100644 index e750db4ef8..0000000000 --- a/packages/typescript/testResources/allowJS/math.ts +++ /dev/null @@ -1,7 +0,0 @@ -export function add(a: number, b: number) { - return a + b; -} - -export function concat(a: string, b: string) { - return a + b; -} diff --git a/packages/typescript/testResources/allowJS/tsconfig.json b/packages/typescript/testResources/allowJS/tsconfig.json deleted file mode 100644 index d8363c3676..0000000000 --- a/packages/typescript/testResources/allowJS/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "compilerOptions": { - "strict": true, - "module": "commonjs", - "allowJs": true, - "outDir": "dist" - } -} \ No newline at end of file diff --git a/packages/typescript/testResources/allowJS/useMath.js b/packages/typescript/testResources/allowJS/useMath.js deleted file mode 100644 index 40a0f4e1db..0000000000 --- a/packages/typescript/testResources/allowJS/useMath.js +++ /dev/null @@ -1,5 +0,0 @@ -const math = require('./math'); - -const a = 42; -const b = 31; -console.log(`a + b `, math.add(a, b)); \ No newline at end of file diff --git a/packages/typescript/testResources/allowJsonFiles/index.ts b/packages/typescript/testResources/allowJsonFiles/index.ts deleted file mode 100644 index 940639e41b..0000000000 --- a/packages/typescript/testResources/allowJsonFiles/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -import json from './json.json'; -console.log(json); diff --git a/packages/typescript/testResources/allowJsonFiles/tsconfig.json b/packages/typescript/testResources/allowJsonFiles/tsconfig.json deleted file mode 100644 index ac78c58209..0000000000 --- a/packages/typescript/testResources/allowJsonFiles/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "compilerOptions": { - "resolveJsonModule": true, - "esModuleInterop": true - }, - "files": [ - "index.ts", - "json.json" - ] -} diff --git a/packages/typescript/testResources/sampleProject/.gitignore b/packages/typescript/testResources/sampleProject/.gitignore deleted file mode 100644 index d591cdfd50..0000000000 --- a/packages/typescript/testResources/sampleProject/.gitignore +++ /dev/null @@ -1 +0,0 @@ -!/node_modules \ No newline at end of file diff --git a/packages/typescript/testResources/sampleProject/math.ts b/packages/typescript/testResources/sampleProject/math.ts deleted file mode 100644 index e750db4ef8..0000000000 --- a/packages/typescript/testResources/sampleProject/math.ts +++ /dev/null @@ -1,7 +0,0 @@ -export function add(a: number, b: number) { - return a + b; -} - -export function concat(a: string, b: string) { - return a + b; -} diff --git a/packages/typescript/testResources/sampleProject/tsconfig.json b/packages/typescript/testResources/sampleProject/tsconfig.json deleted file mode 100644 index 2f5ce907e8..0000000000 --- a/packages/typescript/testResources/sampleProject/tsconfig.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "compilerOptions": { - "strict": true, - "module": "amd" - } -} \ No newline at end of file diff --git a/packages/typescript/testResources/sampleProject/useMath.ts b/packages/typescript/testResources/sampleProject/useMath.ts deleted file mode 100644 index 4ff313c854..0000000000 --- a/packages/typescript/testResources/sampleProject/useMath.ts +++ /dev/null @@ -1,5 +0,0 @@ -import * as math from './math'; - -const a = 42; -const b = 31; -console.log(`a + b `, math.add(a, b)); diff --git a/packages/typescript/testResources/useHeaderFile/globals.d.ts b/packages/typescript/testResources/useHeaderFile/globals.d.ts deleted file mode 100644 index bf343d7d00..0000000000 --- a/packages/typescript/testResources/useHeaderFile/globals.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -declare const sandbox: sinon.SinonSandbox; -declare namespace NodeJS { - export interface Global { - foo: string; - } -} \ No newline at end of file diff --git a/packages/typescript/testResources/useHeaderFile/tsconfig.json b/packages/typescript/testResources/useHeaderFile/tsconfig.json deleted file mode 100644 index d0023391b2..0000000000 --- a/packages/typescript/testResources/useHeaderFile/tsconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compilerOptions": { - "strict": true - } -} \ No newline at end of file diff --git a/packages/typescript/testResources/useHeaderFile/useGlobal.ts b/packages/typescript/testResources/useHeaderFile/useGlobal.ts deleted file mode 100644 index cb08cec9fa..0000000000 --- a/packages/typescript/testResources/useHeaderFile/useGlobal.ts +++ /dev/null @@ -1,3 +0,0 @@ -// global.foo is defined in 'globals.d.ts' next to this file - -global.foo = 'bar'; diff --git a/packages/typescript/tsconfig.src.json b/packages/typescript/tsconfig.src.json index 35cdab44c7..fcd64d3f35 100644 --- a/packages/typescript/tsconfig.src.json +++ b/packages/typescript/tsconfig.src.json @@ -11,9 +11,6 @@ "references": [ { "path": "../api/tsconfig.src.json" - }, - { - "path": "../mutator-specification/tsconfig.src.json" } ] } diff --git a/packages/typescript/tsconfig.stryker.json b/packages/typescript/tsconfig.stryker.json deleted file mode 100644 index b69cba5bc1..0000000000 --- a/packages/typescript/tsconfig.stryker.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "./tsconfig.test.json", - "include": [ - "src", - "src-generated", - "schema/*.json", - "test" - ], -} diff --git a/packages/util/.mocharc.jsonc b/packages/util/.mocharc.jsonc new file mode 100644 index 0000000000..7aa86ca6b3 --- /dev/null +++ b/packages/util/.mocharc.jsonc @@ -0,0 +1,3 @@ +{ + "require": ["test/setup.js"] +} diff --git a/packages/util/.nycrc.json b/packages/util/.nycrc.json new file mode 100644 index 0000000000..3ca3a4de49 --- /dev/null +++ b/packages/util/.nycrc.json @@ -0,0 +1,13 @@ +{ + "lines": 95, + "statements": 95, + "functions": 95, + "branches": 90, + "excludeAfterRemap": false, + "checkCoverage": true, + "reporter": "html", + "reportDir": "reports/coverage", + "include": [ + "src/**/*.js" + ] +} diff --git a/packages/util/CHANGELOG.md b/packages/util/CHANGELOG.md index 1794be3e44..dfb39ec422 100644 --- a/packages/util/CHANGELOG.md +++ b/packages/util/CHANGELOG.md @@ -3,6 +3,117 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [4.0.0-beta.10](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.9...v4.0.0-beta.10) (2020-10-05) + +**Note:** Version bump only for package @stryker-mutator/util + + + + + +# [4.0.0-beta.9](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.8...v4.0.0-beta.9) (2020-09-30) + + +### Bug Fixes + +* **mutate config:** don't warn about files not existing at the default mutate location ([#2509](https://github.com/stryker-mutator/stryker/issues/2509)) ([66c2444](https://github.com/stryker-mutator/stryker/commit/66c24447e28c4218d3e58b945b1bcc5891855097)), closes [#2455](https://github.com/stryker-mutator/stryker/issues/2455) + + + + + +# [4.0.0-beta.8](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.7...v4.0.0-beta.8) (2020-09-22) + +**Note:** Version bump only for package @stryker-mutator/util + + + + + +# [4.0.0-beta.7](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.6...v4.0.0-beta.7) (2020-09-17) + +**Note:** Version bump only for package @stryker-mutator/util + + + + + +# [4.0.0-beta.6](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.5...v4.0.0-beta.6) (2020-09-10) + +**Note:** Version bump only for package @stryker-mutator/util + + + + + +# [4.0.0-beta.5](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.4...v4.0.0-beta.5) (2020-09-09) + + +### Bug Fixes + +* **mocha-runner:** fix memory leaks ([23eede2](https://github.com/stryker-mutator/stryker/commit/23eede22036c9efa502af8016e530af780a7cebb)) + + +### Features + +* **typescript:** Disable type checking ([#2446](https://github.com/stryker-mutator/stryker/issues/2446)) ([3ff996b](https://github.com/stryker-mutator/stryker/commit/3ff996b7516b7782434d86aa9aecbee334978a7f)), closes [#2438](https://github.com/stryker-mutator/stryker/issues/2438) + + + + + +# [4.0.0-beta.4](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.3...v4.0.0-beta.4) (2020-08-29) + +**Note:** Version bump only for package @stryker-mutator/util + + + + + +# [4.0.0-beta.3](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.2...v4.0.0-beta.3) (2020-08-19) + + +### Features + +* **test runner api:** remove `sandboxFileNames` injectable values ([#2369](https://github.com/stryker-mutator/stryker/issues/2369)) ([92f3bf5](https://github.com/stryker-mutator/stryker/commit/92f3bf528d0b01be1f6c219b37a5f90da0431686)), closes [#2351](https://github.com/stryker-mutator/stryker/issues/2351) + + + + + +# [4.0.0-beta.2](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.1...v4.0.0-beta.2) (2020-08-07) + +**Note:** Version bump only for package @stryker-mutator/util + + + + + +# [4.0.0-beta.1](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.0...v4.0.0-beta.1) (2020-07-17) + +**Note:** Version bump only for package @stryker-mutator/util + + + + + +# [4.0.0-beta.0](https://github.com/stryker-mutator/stryker/compare/v3.3.1...v4.0.0-beta.0) (2020-07-10) + + +### Bug Fixes + +* **karma-runner:** mocha filtering with `/` ([#2290](https://github.com/stryker-mutator/stryker/issues/2290)) ([3918633](https://github.com/stryker-mutator/stryker/commit/3918633b21ff37d2e950df2cc14b8557ee7eb6b3)) + + +### Features + +* **instrumenter:** add parsers ([#2222](https://github.com/stryker-mutator/stryker/issues/2222)) ([3b57ef2](https://github.com/stryker-mutator/stryker/commit/3b57ef23dd5b348dcdff205600989aea2c7fbcf0)) +* **instrumenter:** add transformers ([#2234](https://github.com/stryker-mutator/stryker/issues/2234)) ([61c8fe6](https://github.com/stryker-mutator/stryker/commit/61c8fe65e35bb95b786a0e2bebbe57166ffbc480)) + + + + + ## [3.3.1](https://github.com/stryker-mutator/stryker/compare/v3.3.0...v3.3.1) (2020-07-04) **Note:** Version bump only for package @stryker-mutator/util diff --git a/packages/util/package.json b/packages/util/package.json index d5dc94d84f..402ad2056d 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,11 +1,11 @@ { "name": "@stryker-mutator/util", - "version": "3.3.1", + "version": "4.0.0-beta.10", "description": "Contains utilities for Stryker, the mutation testing framework for JavaScript and friends", "main": "src/index.js", "scripts": { - "test": "nyc --exclude-after-remap=false --check-coverage --reporter=html --report-dir=reports/coverage --lines 90 --functions 95 --branches 75 npm run mocha", - "mocha": "mocha \"test/helpers/**/*.js\" \"test/unit/**/*.js\" \"test/integration/**/*.js\"", + "test": "nyc npm run test:unit", + "test:unit": "mocha \"test/unit/**/*.js\"", "stryker": "node ../core/bin/stryker run" }, "repository": { @@ -26,6 +26,10 @@ }, "homepage": "https://github.com/stryker-mutator/stryker/tree/master/packages/util#readme", "devDependencies": { + "@types/lodash.flatmap": "~4.5.6", "@types/node": "^14.0.1" + }, + "dependencies": { + "lodash.flatmap": "~4.5.0" } } diff --git a/packages/util/src/DirectoryRequireCache.ts b/packages/util/src/DirectoryRequireCache.ts new file mode 100644 index 0000000000..458f9a8aa8 --- /dev/null +++ b/packages/util/src/DirectoryRequireCache.ts @@ -0,0 +1,48 @@ +import path = require('path'); + +/** + * A helper class that can be used by test runners. + * The first time you call `record`, it will fill the internal registry with the files required in the current working directory (excluding node_modules) + * Then each time you call `clear` it will clear those files from the require cache + * + * It will also delete the `module.children` property of the root module. + * @see https://github.com/stryker-mutator/stryker/issues/2461 + */ +export class DirectoryRequireCache { + private cache: Set; + private initFiles?: readonly string[]; + private rootModuleId: string; + + public init({ initFiles, rootModuleId }: { initFiles: readonly string[]; rootModuleId: string }) { + this.initFiles = initFiles; + this.rootModuleId = rootModuleId; + } + + /** + * Records the files required in the current working directory (excluding node_modules) + * Only does so the first time, any subsequent calls will be ignored + */ + public record() { + if (!this.cache) { + const cwd = process.cwd(); + this.cache = new Set(this.initFiles); + Object.keys(require.cache) + .filter((fileName) => fileName.startsWith(`${cwd}${path.sep}`) && !fileName.startsWith(path.join(cwd, 'node_modules'))) + .forEach((file) => this.cache.add(file)); + } + } + + public clear() { + if (this.cache) { + if (this.rootModuleId) { + const rootModule = require.cache[this.rootModuleId]; + if (rootModule) { + rootModule.children = rootModule.children.filter((childModule) => !this.cache.has(childModule.id)); + } else { + throw new Error(`Could not find "${this.rootModuleId}" in require cache.`); + } + } + this.cache.forEach((fileName) => delete require.cache[fileName]); + } + } +} diff --git a/packages/util/src/I.ts b/packages/util/src/I.ts new file mode 100644 index 0000000000..d858ef8a63 --- /dev/null +++ b/packages/util/src/I.ts @@ -0,0 +1,7 @@ +/** + * A small mapped type that extracts only the public interface + * from a type. + */ +export type I = { + [K in keyof T]: T[K]; +}; diff --git a/packages/util/src/Immutable.ts b/packages/util/src/Immutable.ts index dbe7938a8d..201bb98ce2 100644 --- a/packages/util/src/Immutable.ts +++ b/packages/util/src/Immutable.ts @@ -1,4 +1,4 @@ -type ImmutablePrimitive = undefined | null | boolean | string | number | Function; +type ImmutablePrimitive = undefined | null | boolean | string | number | ((...args: any[]) => any); export type Immutable = T extends ImmutablePrimitive ? T diff --git a/packages/util/src/Task.ts b/packages/util/src/Task.ts new file mode 100644 index 0000000000..4a8bddcfd3 --- /dev/null +++ b/packages/util/src/Task.ts @@ -0,0 +1,62 @@ +/** + * Wraps a promise in a Task api for convenience. + */ +export class Task { + protected _promise: Promise; + private resolveFn: (value?: T | PromiseLike) => void; + private rejectFn: (reason: any) => void; + private _isCompleted = false; + + constructor() { + this._promise = new Promise((resolve, reject) => { + this.resolveFn = resolve; + this.rejectFn = reject; + }); + } + + public get promise() { + return this._promise; + } + + public get isCompleted() { + return this._isCompleted; + } + + public resolve = (result: T | PromiseLike): void => { + this._isCompleted = true; + this.resolveFn(result); + }; + + public reject = (reason: any): void => { + this._isCompleted = true; + this.rejectFn(reason); + }; +} + +/** + * A task that can expire after the given time. + */ +export class ExpirableTask extends Task { + public static readonly TimeoutExpired: unique symbol = Symbol('TimeoutExpired'); + + constructor(timeoutMS: number) { + super(); + this._promise = ExpirableTask.timeout(this._promise, timeoutMS); + } + + public static timeout(promise: Promise, ms: number): Promise { + const sleep = new Promise((res, rej) => { + const timer = setTimeout(() => res(ExpirableTask.TimeoutExpired), ms); + promise + .then((result) => { + clearTimeout(timer); + res(result); + }) + .catch((error) => { + clearTimeout(timer); + rej(error); + }); + }); + return sleep; + } +} diff --git a/packages/util/src/deepMerge.ts b/packages/util/src/deepMerge.ts index 55dfab62dd..9e174d5ecb 100644 --- a/packages/util/src/deepMerge.ts +++ b/packages/util/src/deepMerge.ts @@ -1,5 +1,5 @@ export type DeepPartial = { - [P in keyof T]?: T[P] extends object ? DeepPartial : T[P]; + [P in keyof T]?: T[P] extends Record ? DeepPartial : T[P]; }; /** @@ -12,7 +12,7 @@ export function deepMerge(defaults: T, overrides: DeepPartial): void { const defaultValue = (defaults as any)[key]; const overrideValue = (overrides as any)[key]; if (overrideValue !== undefined) { - if (defaultValue === undefined || typeof defaultValue !== 'object' || typeof overrideValue !== 'object') { + if (defaultValue === undefined || typeof defaultValue !== 'object' || typeof overrideValue !== 'object' || Array.isArray(defaultValue)) { (defaults as any)[key] = overrideValue; } else { deepMerge(defaultValue, overrideValue); diff --git a/packages/util/src/flatMap.ts b/packages/util/src/flatMap.ts new file mode 100644 index 0000000000..da1829fdea --- /dev/null +++ b/packages/util/src/flatMap.ts @@ -0,0 +1,7 @@ +import flatMap = require('lodash.flatmap'); + +/** + * `Array.prototype.flatMap`, but also works on node 10 + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flatMap + */ +export { flatMap }; diff --git a/packages/util/src/index.ts b/packages/util/src/index.ts index e8939d0a89..9dd46472aa 100644 --- a/packages/util/src/index.ts +++ b/packages/util/src/index.ts @@ -6,3 +6,7 @@ export * from './KnownKeys'; export * from './stringUtils'; export * from './noopLogger'; export * from './notEmpty'; +export * from './flatMap'; +export * from './I'; +export * from './Task'; +export * from './DirectoryRequireCache'; diff --git a/packages/util/src/stringUtils.ts b/packages/util/src/stringUtils.ts index 9f95ad978c..31d57d553d 100644 --- a/packages/util/src/stringUtils.ts +++ b/packages/util/src/stringUtils.ts @@ -1,4 +1,3 @@ -import { notEmpty } from './notEmpty'; import { KnownKeys } from './KnownKeys'; /** @@ -10,10 +9,56 @@ export function normalizeWhitespaces(str: string) { } /** - * Given a base type, allows type safe access to the name (or deep path) of a property. - * @param prop The first property key - * @param prop2 The optional second property key. Add prop3, prop4, etc to this method signature when needed. + * Given a base type, allows type safe access to the name of a property. + * @param prop The property name */ -export function propertyPath(prop: keyof Pick>, prop2?: keyof Pick>[typeof prop]): string { - return [prop, prop2].filter(notEmpty).join('.'); +export function propertyPath(prop: keyof Pick>): string { + return prop.toString(); +} + +/** + * A helper class to allow you to get type safe access to the name of a deep property of `T` + * @example + * ```ts + * PropertyPathBuilder('warnings').prop('unknownOptions').build() + * ``` + */ +export class PropertyPathBuilder { + constructor(private readonly pathSoFar: string[]) {} + + public prop>(prop: TProp) { + return new PropertyPathBuilder>[TProp]>([...this.pathSoFar, prop.toString()]); + } + + /** + * Build the (deep) path to the property name + */ + public build(): string { + return this.pathSoFar.join('.'); + } + + /** + * Creates a new `PropertyPathBuilder` for type T + */ + public static create() { + return new PropertyPathBuilder([]); + } + + public toString(): string { + return this.build(); + } +} + +/** + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#Escaping + */ +export function escapeRegExpLiteral(input: string) { + return input.replace(/[.*+\-?^${}()|[\]\\/]/g, '\\$&'); // $& means the whole matched string +} + +/** + * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#Escaping + */ +export function escapeRegExp(input: string) { + return input.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string } diff --git a/packages/util/stryker.conf.js b/packages/util/stryker.conf.js index fa5a53f3c4..305c428237 100644 --- a/packages/util/stryker.conf.js +++ b/packages/util/stryker.conf.js @@ -1,5 +1,6 @@ const path = require('path'); const settings = require('../../stryker.parent.conf'); const moduleName = __dirname.split(path.sep).pop(); +settings.plugins = settings.plugins.map(p => path.resolve(p)); settings.dashboard.module = moduleName; module.exports = settings; diff --git a/packages/util/test/helpers/initChai.ts b/packages/util/test/helpers/initChai.ts deleted file mode 100644 index 514154da42..0000000000 --- a/packages/util/test/helpers/initChai.ts +++ /dev/null @@ -1,6 +0,0 @@ -import * as chai from 'chai'; -import * as chaiAsPromised from 'chai-as-promised'; -import * as sinonChai from 'sinon-chai'; - -chai.use(sinonChai); -chai.use(chaiAsPromised); diff --git a/packages/util/test/helpers/initSinon.ts b/packages/util/test/helpers/initSinon.ts deleted file mode 100644 index b168594f22..0000000000 --- a/packages/util/test/helpers/initSinon.ts +++ /dev/null @@ -1,5 +0,0 @@ -import * as sinon from 'sinon'; - -afterEach(() => { - sinon.restore(); -}); diff --git a/packages/util/test/helpers/initSourceMaps.ts b/packages/util/test/helpers/initSourceMaps.ts deleted file mode 100644 index fcfbfda16c..0000000000 --- a/packages/util/test/helpers/initSourceMaps.ts +++ /dev/null @@ -1 +0,0 @@ -import 'source-map-support/register'; diff --git a/packages/util/test/setup.ts b/packages/util/test/setup.ts new file mode 100644 index 0000000000..ca7bc2aaa8 --- /dev/null +++ b/packages/util/test/setup.ts @@ -0,0 +1,14 @@ +import 'source-map-support/register'; +import * as chai from 'chai'; +import * as chaiAsPromised from 'chai-as-promised'; +import * as sinonChai from 'sinon-chai'; +import * as sinon from 'sinon'; + +chai.use(sinonChai); +chai.use(chaiAsPromised); + +export const mochaHooks = { + afterEach() { + sinon.restore(); + }, +}; diff --git a/packages/util/test/unit/DirectoryRequireCache.spec.ts b/packages/util/test/unit/DirectoryRequireCache.spec.ts new file mode 100644 index 0000000000..09613cdaeb --- /dev/null +++ b/packages/util/test/unit/DirectoryRequireCache.spec.ts @@ -0,0 +1,139 @@ +import path = require('path'); + +import sinon = require('sinon'); + +import { expect } from 'chai'; + +import { DirectoryRequireCache } from '../../src'; + +describe(DirectoryRequireCache.name, () => { + let workingDirectory: string; + let sut: DirectoryRequireCache; + let loadedFiles: Map; + let rootModule: NodeModule; + + beforeEach(() => { + loadedFiles = new Map(); + workingDirectory = path.join('stub', 'working', 'dir'); + const cwdStub = sinon.stub(process, 'cwd').returns(workingDirectory); + cwdStub.returns(workingDirectory); + sut = new DirectoryRequireCache(); + rootModule = createModule('root', 'root'); + require.cache['root'] = rootModule; + }); + + afterEach(() => { + for (const fileName of loadedFiles.keys()) { + delete require.cache[fileName]; + } + }); + + function fakeRequireFile(fileName: string, content = fileName, requiredBy = rootModule) { + loadedFiles.set(fileName, content); + const child = createModule(content, fileName); + require.cache[fileName] = child; + requiredBy.children.push(child); + } + + describe(DirectoryRequireCache.prototype.clear.name, () => { + it('should clear the init files', () => { + // Arrange + const dir2 = path.join('stub', 'working', 'dir2'); + const fooFileName = path.join(dir2, 'foo.js'); + const barFileName = path.join(dir2, 'bar.js'); + const bazFileName = path.join(dir2, 'baz.js'); + fakeRequireFile(fooFileName, 'foo'); + fakeRequireFile(barFileName, 'foo'); + fakeRequireFile(bazFileName, 'baz'); + sut.init({ initFiles: [fooFileName, barFileName], rootModuleId: 'root' }); + sut.record(); + + // Act + sut.clear(); + + // Assert + expect(require.cache[fooFileName]).undefined; + expect(require.cache[barFileName]).undefined; + expect(require.cache[bazFileName]?.exports).eq('baz'); + }); + + it('should clear recorded files', () => { + // Arrange + const dir2 = path.join('stub', 'working', 'dir2'); + const fooFileName = path.join(workingDirectory, 'foo.js'); + const barFileName = path.join(workingDirectory, 'bar.js'); + const bazFileName = path.join(dir2, 'baz.js'); + fakeRequireFile(fooFileName, 'foo'); + fakeRequireFile(barFileName, 'foo'); + fakeRequireFile(bazFileName, 'baz'); + sut.record(); + + // Act + sut.clear(); + + // Assert + expect(require.cache[fooFileName]).undefined; + expect(require.cache[barFileName]).undefined; + expect(require.cache[bazFileName]?.exports).eq('baz'); + }); + + it('should clear recorded children from the root', () => { + // Arrange + const dir2 = path.join('stub', 'working', 'dir2'); + const fooFileName = path.join(workingDirectory, 'foo.js'); + const barFileName = path.join(workingDirectory, 'bar.js'); + const bazFileName = path.join(dir2, 'baz.js'); + fakeRequireFile(fooFileName, 'foo'); + fakeRequireFile(barFileName, 'foo'); + fakeRequireFile(bazFileName, 'baz'); + expect(rootModule.children).lengthOf(3); + sut.init({ initFiles: [], rootModuleId: 'root' }); + sut.record(); + + // Act + sut.clear(); + + // Assert + expect(rootModule.children).lengthOf(1); + expect(rootModule.children[0].filename).eq(bazFileName); + }); + + it("should throw when the root module wasn't loaded", () => { + // Arrange + sut.init({ initFiles: [], rootModuleId: 'not-exists' }); + sut.record(); + + // Act + expect(() => sut.clear()).throws('Could not find "not-exists" in require cache.'); + }); + + it('should not clear files from node_modules', () => { + // Arrange + const fooFileName = path.join(workingDirectory, 'foo.js'); + const bazFileName = path.join(workingDirectory, 'node_modules', 'baz.js'); + fakeRequireFile(fooFileName, 'foo'); + fakeRequireFile(bazFileName, 'baz'); + sut.record(); + + // Act + sut.clear(); + + // Assert + expect(require.cache[fooFileName]).undefined; + expect(require.cache[bazFileName]?.exports).eq('baz'); + }); + }); +}); +function createModule(content: string, fileName: string): NodeModule { + return { + exports: content, + children: [], + filename: fileName, + id: fileName, + loaded: true, + parent: null, + paths: [], + require, + path: '', + }; +} diff --git a/packages/util/test/unit/Task.spec.ts b/packages/util/test/unit/Task.spec.ts new file mode 100644 index 0000000000..5cc8bcf3dd --- /dev/null +++ b/packages/util/test/unit/Task.spec.ts @@ -0,0 +1,86 @@ +import { expect } from 'chai'; + +import sinon = require('sinon'); + +import { Task, ExpirableTask } from '../../src'; + +describe(Task.name, () => { + it('should give access to underlying promise', () => { + const sut = new Task(); + expect(sut.promise).instanceOf(Promise); + sut.resolve(); + }); + + it('should be able to resolve the underlying promise', async () => { + const sut = new Task(); + sut.resolve('resolved'); + const result = await sut.promise; + expect(result).eq('resolved'); + }); + + it('should be able to reject the underlying promise', async () => { + const sut = new Task(); + const expectedError = new Error('expected error'); + sut.reject(expectedError); + await expect(sut.promise).rejectedWith(expectedError); + }); + + it('should be able to know if it isCompleted', () => { + const sut = new Task(); + expect(sut.isCompleted).false; + sut.resolve(); + expect(sut.isCompleted).true; + }); +}); + +describe(ExpirableTask.name, () => { + describe('instance', () => { + it('should timeout after set period', async () => { + const task = new ExpirableTask(0); + const result = await task.promise; + expect(result).eq(ExpirableTask.TimeoutExpired); + }); + + it('should be able to resolve within time', async () => { + const task = new ExpirableTask(0); + task.resolve('in time'); + const result = await task.promise; + expect(result).eq('in time'); + }); + + it('should be able to reject within time', async () => { + const task = new ExpirableTask(0); + const expectedError = new Error('expected error'); + task.reject(expectedError); + await expect(task.promise).rejectedWith(expectedError); + }); + }); + + describe('timeout', () => { + it('should timeout a promise after a set period', async () => { + const task = new Task(); + const actual = await ExpirableTask.timeout(task.promise, 0); + expect(actual).eq(ExpirableTask.TimeoutExpired); + task.resolve(undefined); + }); + + it('should remove any nodejs timers when promise resolves', async () => { + // Arrange + const expectedTimer = 234; + const setTimeoutStub = sinon.stub(global, 'setTimeout'); + const clearTimeoutStub = sinon.stub(global, 'clearTimeout'); + setTimeoutStub.returns(expectedTimer); + const expectedResult = 'expectedResult'; + const p = Promise.resolve(expectedResult); + const delay = 10; + + // Act + const result = await ExpirableTask.timeout(p, delay); + + // Assert + expect(result).eq(expectedResult); + expect(clearTimeoutStub).calledWith(expectedTimer); + expect(setTimeoutStub).calledWith(sinon.match.func, delay); + }); + }); +}); diff --git a/packages/util/test/unit/deepMerge.spec.ts b/packages/util/test/unit/deepMerge.spec.ts index 8fd0e7b818..a9a5f8ac38 100644 --- a/packages/util/test/unit/deepMerge.spec.ts +++ b/packages/util/test/unit/deepMerge.spec.ts @@ -37,14 +37,14 @@ describe(deepMerge.name, () => { it('should override arrays without merging them', () => { // Arrange - const foo: Foo = { qux: ['1'] }; - const baz = { qux: ['2'] }; + const foo: Foo = { qux: ['1', '2'] }; + const baz = { qux: ['3'] }; // Act deepMerge(foo, baz); // Assert - const expected: Foo = { qux: ['2'] }; + const expected: Foo = { qux: ['3'] }; expect(foo).deep.eq(expected); }); diff --git a/packages/util/test/unit/stringUtils.spec.ts b/packages/util/test/unit/stringUtils.spec.ts index cf8082102f..1b29eeec18 100644 --- a/packages/util/test/unit/stringUtils.spec.ts +++ b/packages/util/test/unit/stringUtils.spec.ts @@ -1,6 +1,6 @@ import { expect } from 'chai'; -import { normalizeWhitespaces, propertyPath } from '../../src'; +import { normalizeWhitespaces, propertyPath, escapeRegExpLiteral, escapeRegExp, PropertyPathBuilder } from '../../src'; describe('stringUtils', () => { describe(normalizeWhitespaces.name, () => { @@ -17,15 +17,56 @@ describe('stringUtils', () => { }); }); - describe(propertyPath.name, () => { + describe(PropertyPathBuilder.name, () => { interface Foo { bar: { baz: string; }; + qux: { + quux: string; + }; } it('should be able to point to a path', () => { - expect(propertyPath('bar', 'baz')).eq('bar.baz'); + expect(PropertyPathBuilder.create().prop('bar').prop('baz').build()).eq('bar.baz'); + }); + }); + + describe(propertyPath.name, () => { + interface Foo { + bar: string; + } + + it('should be able to point to a path', () => { + expect(propertyPath('bar')).eq('bar'); + }); + }); + + describe(escapeRegExpLiteral.name, () => { + it('should return input if no special chars are found', () => { + expect(escapeRegExpLiteral('something normal')).eq('something normal'); }); + + for (const letter of '.*+-?^${}()|[]\\/') { + it(`should escape "${letter}"`, () => { + expect(escapeRegExpLiteral(letter)).eq(`\\${letter}`); + }); + } + }); + + describe(escapeRegExp.name, () => { + it('should return input if no special chars are found', () => { + expect(escapeRegExp('something normal')).eq('something normal'); + }); + + it("should not escape `/` (that's only needed for regex literals)", () => { + expect(escapeRegExp('n/a')).eq('n/a'); + }); + + for (const letter of '.*+-?^${}()|[]\\') { + it(`should escape "${letter}"`, () => { + expect(escapeRegExp(letter)).eq(`\\${letter}`); + }); + } }); }); diff --git a/packages/util/tsconfig.stryker.json b/packages/util/tsconfig.stryker.json deleted file mode 100644 index 0f7ed99680..0000000000 --- a/packages/util/tsconfig.stryker.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": "./tsconfig.test.json", - "include": [ - "src", - "test" - ], -} diff --git a/packages/vue-mutator/CHANGELOG.md b/packages/vue-mutator/CHANGELOG.md index 65e2752e4f..b7ca3f962b 100644 --- a/packages/vue-mutator/CHANGELOG.md +++ b/packages/vue-mutator/CHANGELOG.md @@ -3,6 +3,100 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [4.0.0-beta.10](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.9...v4.0.0-beta.10) (2020-10-05) + +**Note:** Version bump only for package @stryker-mutator/vue-mutator + + + + + +# [4.0.0-beta.9](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.8...v4.0.0-beta.9) (2020-09-30) + +**Note:** Version bump only for package @stryker-mutator/vue-mutator + + + + + +# [4.0.0-beta.8](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.7...v4.0.0-beta.8) (2020-09-22) + +**Note:** Version bump only for package @stryker-mutator/vue-mutator + + + + + +# [4.0.0-beta.7](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.6...v4.0.0-beta.7) (2020-09-17) + +**Note:** Version bump only for package @stryker-mutator/vue-mutator + + + + + +# [4.0.0-beta.6](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.5...v4.0.0-beta.6) (2020-09-10) + +**Note:** Version bump only for package @stryker-mutator/vue-mutator + + + + + +# [4.0.0-beta.5](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.4...v4.0.0-beta.5) (2020-09-09) + +**Note:** Version bump only for package @stryker-mutator/vue-mutator + + + + + +# [4.0.0-beta.4](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.3...v4.0.0-beta.4) (2020-08-29) + +**Note:** Version bump only for package @stryker-mutator/vue-mutator + + + + + +# [4.0.0-beta.3](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.2...v4.0.0-beta.3) (2020-08-19) + +**Note:** Version bump only for package @stryker-mutator/vue-mutator + + + + + +# [4.0.0-beta.2](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.1...v4.0.0-beta.2) (2020-08-07) + +**Note:** Version bump only for package @stryker-mutator/vue-mutator + + + + + +# [4.0.0-beta.1](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.0...v4.0.0-beta.1) (2020-07-17) + +**Note:** Version bump only for package @stryker-mutator/vue-mutator + + + + + +# [4.0.0-beta.0](https://github.com/stryker-mutator/stryker/compare/v3.3.1...v4.0.0-beta.0) (2020-07-10) + + +### Features + +* **api:** add id to Mutant interface ([#2255](https://github.com/stryker-mutator/stryker/issues/2255)) ([cfc9053](https://github.com/stryker-mutator/stryker/commit/cfc90537d0b9815cba2b44b9681d171ca602766e)) +* **checker:** add checker api ([#2240](https://github.com/stryker-mutator/stryker/issues/2240)) ([d463f86](https://github.com/stryker-mutator/stryker/commit/d463f8639437c114da4fe30115652e8a470dd179)), closes [#1514](https://github.com/stryker-mutator/stryker/issues/1514) [#1980](https://github.com/stryker-mutator/stryker/issues/1980) +* **mutator:** remove `Mutator` API ([3ca89cf](https://github.com/stryker-mutator/stryker/commit/3ca89cf7e23af70f83e0c0ac02ab5241fc0790ff)) +* **tsconfig:** rewrite tsconfig references ([#2292](https://github.com/stryker-mutator/stryker/issues/2292)) ([4ee4950](https://github.com/stryker-mutator/stryker/commit/4ee4950bebd8db9c2f5a514edee57de55c040526)), closes [#2276](https://github.com/stryker-mutator/stryker/issues/2276) + + + + + ## [3.3.1](https://github.com/stryker-mutator/stryker/compare/v3.3.0...v3.3.1) (2020-07-04) **Note:** Version bump only for package @stryker-mutator/vue-mutator diff --git a/packages/vue-mutator/package.json b/packages/vue-mutator/package.json index b778b8782e..a2c40cdf1a 100644 --- a/packages/vue-mutator/package.json +++ b/packages/vue-mutator/package.json @@ -1,13 +1,9 @@ { "name": "@stryker-mutator/vue-mutator", - "version": "3.3.1", + "version": "4.0.0-beta.10", "description": "A plugin for VueJS projects using Stryker", "main": "src/index.js", - "scripts": { - "test": "nyc --exclude-after-remap=false --check-coverage --reporter=html --report-dir=reports/coverage --lines 85 --functions 90 --branches 60 npm run mocha", - "mocha": "mocha \"test/helpers/**/*.js\" \"test/unit/**/*.js\" \"test/integration/**/*.js\"", - "stryker": "node ../core/bin/stryker run" - }, + "scripts": {}, "repository": { "type": "git", "url": "https://github.com/stryker-mutator/stryker" @@ -16,9 +12,7 @@ "node": ">=10" }, "keywords": [ - "stryker", - "vuejs", - "@stryker-mutator/mutator-plugin" + "stryker" ], "publishConfig": { "access": "public" @@ -31,19 +25,5 @@ "Nico Jansen " ], "homepage": "https://github.com/stryker-mutator/stryker/tree/master/packages/vue-mutator#readme", - "license": "Apache-2.0", - "devDependencies": { - "@stryker-mutator/javascript-mutator": "^3.3.1", - "@stryker-mutator/test-helpers": "^3.3.1", - "@stryker-mutator/typescript": "^3.3.1", - "@types/node": "^14.0.1", - "vue-template-compiler": "^2.0.0" - }, - "dependencies": { - "@stryker-mutator/api": "^3.3.1" - }, - "peerDependencies": { - "@stryker-mutator/core": "^3.0.0", - "vue-template-compiler": "^2.0.0" - } + "license": "Apache-2.0" } diff --git a/packages/vue-mutator/src/VueMutator.ts b/packages/vue-mutator/src/VueMutator.ts deleted file mode 100644 index 9840b068c3..0000000000 --- a/packages/vue-mutator/src/VueMutator.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { File } from '@stryker-mutator/api/core'; -import { Mutant, Mutator } from '@stryker-mutator/api/mutant'; -import { tokens } from '@stryker-mutator/api/plugin'; - -import { MUTATORS_TOKEN } from './helpers/MutatorHelpers'; - -const compiler = require('vue-template-compiler'); - -export default class VueMutator implements Mutator { - private readonly javascriptMutatorName = 'javascript'; - private readonly typescriptMutatorName = 'typescript'; - - constructor(private readonly mutators: { [name: string]: Mutator }) {} - public static inject = tokens(MUTATORS_TOKEN); - - public mutate(inputFiles: File[]): Mutant[] { - const mutants: Mutant[] = []; - - inputFiles.forEach((file) => { - if (file.name.endsWith('.vue')) { - const script = compiler.parseComponent(file.textContent).script; - if (script) { - // Vue file must have tag to be mutated - const { mutator, extension } = this.getVueScriptMutatorAndExtension(script); - const vueFile = new File(file.name + extension, file.textContent.substring(script.start, script.end)); - const vueMutants = mutator.mutate([vueFile]); - vueMutants.forEach((mutant) => { - mutant.fileName = file.name; - mutant.range[0] += script.start; - mutant.range[1] += script.start; - }); - mutants.push(...vueMutants); - } - } else { - const mutator = this.getMutator(file); - mutants.push(...mutator.mutate([file])); - } - }); - - return mutants; - } - - private getVueScriptMutatorAndExtension(script: any): { mutator: Mutator; extension: string } { - const lang: string | undefined = script.attrs.lang; - let mutatorName: string; - let extension: string; - switch (lang) { - case undefined: - case 'js': - case 'javascript': - mutatorName = this.javascriptMutatorName; - extension = '.js'; - break; - case 'ts': - case 'typescript': - mutatorName = this.typescriptMutatorName; - extension = '.ts'; - break; - default: - throw new Error(`Found unsupported language attribute 'lang="${lang}"' on a - - - #app { - text-align: center; - } - `; - const jsCode = `"use strict"; - var fs = require('fs'); - function checkAge(user) { - return user.age >= 18; - }`; - const files = [new File('AppComponent.vue', vueCode), new File('age.js', jsCode)]; - const sut = createSut(); - - const mutants = sut.mutate(files); - - expect(mutants.filter((m) => m.mutatorName === 'StringLiteral').length).to.equal(2); - expect(mutants.filter((m) => m.mutatorName === 'BlockStatement').length).to.equal(3); - expect(mutants.filter((m) => m.mutatorName === 'EqualityOperator').length).to.equal(2); - expect(mutants.filter((m) => m.mutatorName === 'ArithmeticOperator').length).to.equal(1); - }); - }); - - describe('TypeScript project', () => { - it('should generate mutants', () => { - testInjector.pluginResolver.resolveAll.returns([typescriptMutatorPlugin]); - const vueCode = ` - - - - - #app { - text-align: center; - } - `; - const jsCode = `import * as fs from 'fs'; - function checkAge(user: { age: number } ): boolean { - return user.age >= 18; - }`; - const files = [new File('AppComponent.vue', vueCode), new File('age.ts', jsCode)]; - const sut = createSut(); - - const mutants = sut.mutate(files); - - expect(mutants.filter((m) => m.mutatorName === 'StringLiteral').length).to.equal(1); - expect(mutants.filter((m) => m.mutatorName === 'BlockStatement').length).to.equal(3); - expect(mutants.filter((m) => m.mutatorName === 'EqualityOperator').length).to.equal(2); - expect(mutants.filter((m) => m.mutatorName === 'ArithmeticOperator').length).to.equal(1); - }); - }); -}); diff --git a/packages/vue-mutator/test/unit/VueMutator.spec.ts b/packages/vue-mutator/test/unit/VueMutator.spec.ts deleted file mode 100644 index f1b0ccb12c..0000000000 --- a/packages/vue-mutator/test/unit/VueMutator.spec.ts +++ /dev/null @@ -1,371 +0,0 @@ -import { File } from '@stryker-mutator/api/core'; -import { Mutant, Mutator } from '@stryker-mutator/api/mutant'; -import { testInjector } from '@stryker-mutator/test-helpers'; -import { expect } from 'chai'; -import { SinonStubbedInstance } from 'sinon'; -import * as sinon from 'sinon'; - -import * as MutatorHelpers from '../../src/helpers/MutatorHelpers'; -import VueMutator from '../../src/VueMutator'; - -describe('VueMutator', () => { - let stubJavaScriptMutator: SinonStubbedInstance; - let stubTypeScriptMutator: SinonStubbedInstance; - let mutators: { [name: string]: Mutator }; - - beforeEach(() => { - mutators = {}; - stubJavaScriptMutator = sinon.createStubInstance(VueMutator); - stubJavaScriptMutator.mutate.returns([]); - stubTypeScriptMutator = sinon.createStubInstance(VueMutator); - stubTypeScriptMutator.mutate.returns([]); - }); - - function createSut() { - return testInjector.injector.provideValue(MutatorHelpers.MUTATORS_TOKEN, mutators).injectClass(VueMutator); - } - - describe('with JavaScript', () => { - it('should throw an error if no JavaScript mutator is installed', () => { - mutators = {}; - const vueFile = new File( - 'Component.vue', - ` - ` - ); - - const files = [vueFile]; - const sut = createSut(); - - expect(() => sut.mutate(files)).throws( - "The 'javascript' mutator is required to mutate a ` - ); - const jsFile = new File('index.js', 'var name = "MyApp";'); - - const files = [jsFile, vueFile]; - const sut = createSut(); - - expect(() => sut.mutate(files)).throws( - `Unable to mutate file "${jsFile.name}" because neither the typescript or the javascript mutator was installed. Please read the README of this package for information on configuration.` - ); - }); - - it('should pass Vue script blocks to the JavaScript mutator', () => { - mutators = { javascript: stubJavaScriptMutator }; - const script = `export default { - data () { - return { - message: 'hello!' - } - } - }`; - const vueFile = new File( - 'Component.vue', - ` - ` - ); - const files = [vueFile]; - const sut = createSut(); - - sut.mutate(files); - - expect(stubJavaScriptMutator.mutate).calledWith([new File(`${vueFile.name}.js`, script)]); - }); - - it('should pass Vue script blocks with lang="js" to the JavaScript mutator', () => { - mutators = { javascript: stubJavaScriptMutator }; - const script = `export default { - data () { - return { - message: 'hello!' - } - } - }`; - const vueFile = new File( - 'Component.vue', - ` - ` - ); - const files = [vueFile]; - const sut = createSut(); - - sut.mutate(files); - - expect(stubJavaScriptMutator.mutate).calledWith([new File(`${vueFile.name}.js`, script)]); - }); - - it('should pass Vue script blocks with lang="javascript" to the JavaScript mutator', () => { - mutators = { javascript: stubJavaScriptMutator }; - const script = `export default { - data () { - return { - message: 'hello!' - } - } - }`; - const vueFile = new File( - 'Component.vue', - ` - ` - ); - const files = [vueFile]; - const sut = createSut(); - - sut.mutate(files); - - expect(stubJavaScriptMutator.mutate).calledWith([new File(`${vueFile.name}.js`, script)]); - }); - - it('should pass regular files to the TypeScript mutator, even if the JavaScript mutator is installed', () => { - mutators = { javascript: stubJavaScriptMutator, typescript: stubTypeScriptMutator }; - const jsFile = new File('index.js', 'var name = "MyApp";'); - const files = [jsFile]; - const sut = createSut(); - - sut.mutate(files); - - expect(stubTypeScriptMutator.mutate).calledWith([jsFile]); - expect(stubJavaScriptMutator.mutate).not.called; - }); - - it('should pass regular files to the JavaScript mutator', () => { - mutators = { javascript: stubJavaScriptMutator }; - const jsFile = new File('index.js', 'var name = "MyApp";'); - const files = [jsFile]; - const sut = createSut(); - - sut.mutate(files); - - expect(stubJavaScriptMutator.mutate).calledWith([jsFile]); - }); - }); - - describe('with TypeScript', () => { - it('should throw an error if no TypeScript mutator is installed', () => { - mutators = {}; - const vueFile = new File( - 'Component.vue', - ` - ` - ); - - const files = [vueFile]; - const sut = createSut(); - - expect(() => sut.mutate(files)).throws( - "The 'typescript' mutator is required to mutate a ` - ); - const jsFile = new File('index.js', 'var name = "MyApp";'); - - const files = [jsFile, vueFile]; - const sut = createSut(); - - expect(() => sut.mutate(files)).throws( - `Unable to mutate file "${jsFile.name}" because neither the typescript or the javascript mutator was installed. Please read the README of this package for information on configuration.` - ); - }); - - it('should pass Vue script blocks with lang="ts" to the TypeScript mutator', () => { - mutators = { typescript: stubTypeScriptMutator }; - const script = `export default { - data () { - return { - message: 'hello!' - } - } - }`; - const vueFile = new File( - 'Component.vue', - ` - ` - ); - const files = [vueFile]; - const sut = createSut(); - - sut.mutate(files); - - expect(stubTypeScriptMutator.mutate).calledWith([new File(`${vueFile.name}.ts`, script)]); - }); - - it('should pass Vue script blocks with lang="typescript" to the TypeScript mutator', () => { - mutators = { typescript: stubTypeScriptMutator }; - const script = `export default { - data () { - return { - message: 'hello!' - } - } - }`; - const vueFile = new File( - 'Component.vue', - ` - ` - ); - const files = [vueFile]; - const sut = createSut(); - - sut.mutate(files); - - expect(stubTypeScriptMutator.mutate).calledWith([new File(`${vueFile.name}.ts`, script)]); - }); - - it('should pass regular files to the TypeScript mutator', () => { - mutators = { typescript: stubTypeScriptMutator }; - const jsFile = new File('index.js', 'var name = "MyApp";'); - const files = [jsFile]; - const sut = createSut(); - - sut.mutate(files); - - expect(stubTypeScriptMutator.mutate).calledWith([jsFile]); - }); - }); - - it('should throw an error when a Vue script block has an unknown lang attribute', () => { - mutators = {}; - const script = `export default { - data () { - return { - message: 'hello!' - } - } - }`; - const vueFile = new File( - 'Component.vue', - ` - ` - ); - const files = [vueFile]; - const sut = createSut(); - - expect(() => sut.mutate(files)).throws('Found unsupported language attribute \'lang="coffeescript"\' on a ` - ); - const files = [vueFile]; - const jsMutant: Mutant = { - fileName: `${vueFile.name}.js`, - mutatorName: 'StringLiteral', - range: [script.indexOf(codeToMutate), script.indexOf(codeToMutate) + codeToMutate.length], - replacement: '', - }; - stubJavaScriptMutator.mutate.returns([jsMutant]); - const sut = createSut(); - - const mutants = sut.mutate(files); - const generatedMutant = mutants[0]; - - expect(mutants.length).to.equal(1); - expect(generatedMutant.mutatorName).to.equal(jsMutant.mutatorName); - expect(generatedMutant.fileName).to.equal(vueFile.name); - expect(generatedMutant.range).to.deep.equal([ - vueFile.textContent.indexOf(codeToMutate), - vueFile.textContent.indexOf(codeToMutate) + codeToMutate.length, - ]); - expect(generatedMutant.replacement).to.equal(jsMutant.replacement); - }); -}); diff --git a/packages/vue-mutator/tsconfig.src.json b/packages/vue-mutator/tsconfig.src.json index 08a0b4851f..59c77122f1 100644 --- a/packages/vue-mutator/tsconfig.src.json +++ b/packages/vue-mutator/tsconfig.src.json @@ -6,15 +6,5 @@ "include": [ "src" ], - "references": [ - { - "path": "../api/tsconfig.src.json" - }, - { - "path": "../typescript/tsconfig.src.json" - }, - { - "path": "../javascript-mutator/tsconfig.src.json" - } - ] -} \ No newline at end of file + "references": [] +} diff --git a/packages/vue-mutator/tsconfig.stryker.json b/packages/vue-mutator/tsconfig.stryker.json deleted file mode 100644 index 0f7ed99680..0000000000 --- a/packages/vue-mutator/tsconfig.stryker.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": "./tsconfig.test.json", - "include": [ - "src", - "test" - ], -} diff --git a/packages/vue-mutator/tsconfig.test.json b/packages/vue-mutator/tsconfig.test.json index 7a5d9c0200..23cd9cf90e 100644 --- a/packages/vue-mutator/tsconfig.test.json +++ b/packages/vue-mutator/tsconfig.test.json @@ -10,12 +10,5 @@ "include": [ "test" ], - "references": [ - { - "path": "tsconfig.src.json" - }, - { - "path": "../test-helpers/tsconfig.src.json" - } - ] -} \ No newline at end of file + "references": [] +} diff --git a/packages/wct-runner/CHANGELOG.md b/packages/wct-runner/CHANGELOG.md index ac384ea8db..fbaa315287 100644 --- a/packages/wct-runner/CHANGELOG.md +++ b/packages/wct-runner/CHANGELOG.md @@ -3,6 +3,102 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [4.0.0-beta.10](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.9...v4.0.0-beta.10) (2020-10-05) + +**Note:** Version bump only for package @stryker-mutator/wct-runner + + + + + +# [4.0.0-beta.9](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.8...v4.0.0-beta.9) (2020-09-30) + +**Note:** Version bump only for package @stryker-mutator/wct-runner + + + + + +# [4.0.0-beta.8](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.7...v4.0.0-beta.8) (2020-09-22) + +**Note:** Version bump only for package @stryker-mutator/wct-runner + + + + + +# [4.0.0-beta.7](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.6...v4.0.0-beta.7) (2020-09-17) + +**Note:** Version bump only for package @stryker-mutator/wct-runner + + + + + +# [4.0.0-beta.6](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.5...v4.0.0-beta.6) (2020-09-10) + +**Note:** Version bump only for package @stryker-mutator/wct-runner + + + + + +# [4.0.0-beta.5](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.4...v4.0.0-beta.5) (2020-09-09) + +**Note:** Version bump only for package @stryker-mutator/wct-runner + + + + + +# [4.0.0-beta.4](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.3...v4.0.0-beta.4) (2020-08-29) + + +### Features + +* **wct-runner:** drop support for wct ([#2440](https://github.com/stryker-mutator/stryker/issues/2440)) ([7c55424](https://github.com/stryker-mutator/stryker/commit/7c55424a6deca5301af50206ea93905faaa0056b)) + + +### BREAKING CHANGES + +* **wct-runner:** The @stryker-mutator/wct-runner package is dropped in Stryker 4.0. Please see https://github.com/stryker-mutator/stryker/issues/2386 for more details. Feel free to keep using @stryker-mutator/wct-runner@3 or start a community fork. Note that [support for the web-component-tester itself is minimal](https://github.com/Polymer/tools/issues/3398), you might want to consider switching to a different test runner. Stryker still supports Mocha, Jest, Jasmine and Karma. + + + + + +# [4.0.0-beta.3](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.2...v4.0.0-beta.3) (2020-08-19) + +**Note:** Version bump only for package @stryker-mutator/wct-runner + + + + + +# [4.0.0-beta.2](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.1...v4.0.0-beta.2) (2020-08-07) + +**Note:** Version bump only for package @stryker-mutator/wct-runner + + + + + +# [4.0.0-beta.1](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.0...v4.0.0-beta.1) (2020-07-17) + +**Note:** Version bump only for package @stryker-mutator/wct-runner + + + + + +# [4.0.0-beta.0](https://github.com/stryker-mutator/stryker/compare/v3.3.1...v4.0.0-beta.0) (2020-07-10) + +**Note:** Version bump only for package @stryker-mutator/wct-runner + + + + + ## [3.3.1](https://github.com/stryker-mutator/stryker/compare/v3.3.0...v3.3.1) (2020-07-04) **Note:** Version bump only for package @stryker-mutator/wct-runner diff --git a/packages/wct-runner/README.md b/packages/wct-runner/README.md index 953f2e0bef..760823bc11 100644 --- a/packages/wct-runner/README.md +++ b/packages/wct-runner/README.md @@ -36,7 +36,7 @@ Make sure you set the `testRunner` option to "wct" and set `coverageAnalysis` to { testRunner: 'wct' coverageAnalysis: 'off', // coverage analysis is not supported yet for the @stryker-mutator/wct-runner. - maxConcurrentTestRunners: 4, // A maximum of half your CPU's is recommended + concurrency: 4, // A maximum of half your CPU's is recommended timeoutMS: 10000 // A higher timeout is recommended to allow for browser startup } ``` diff --git a/packages/wct-runner/package.json b/packages/wct-runner/package.json index 3c7a4334a9..a9306d1c59 100644 --- a/packages/wct-runner/package.json +++ b/packages/wct-runner/package.json @@ -1,43 +1,17 @@ { "name": "@stryker-mutator/wct-runner", - "version": "3.3.1", - "description": "A plugin to use web component tester as a test runner for Stryker, the mutation testing framework for JavaScript and friends", + "version": "4.0.0-beta.10", + "description": "This was a plugin to use web component tester as a test runner for Stryker, the mutation testing framework for JavaScript and friends. However support was dropped in Stryker v4", "main": "src/index.js", - "scripts": { - "test": "cross-env LAUNCHPAD_BROWSERS=chrome nyc --reporter=html --report-dir=reports/coverage --lines 95 --functions 95 --branches 95 npm run mocha", - "mocha": "mocha \"test/helpers/**/*.js\" \"test/unit/**/*.js\" && mocha --timeout 120000 --exit \"test/helpers/**/*.js\" \"test/integration/**/*.js\"", - "stryker": "node ../core/bin/stryker run" - }, + "scripts": {}, "repository": { "type": "git", "url": "git+https://github.com/stryker-mutator/stryker.git" }, - "keywords": [ - "stryker", - "web-component-tester", - "wct", - "@stryker-mutator/test-runner-plugin" - ], + "keywords": [], "publishConfig": { "access": "public" }, - "dependencies": { - "@stryker-mutator/api": "^3.3.1", - "@stryker-mutator/util": "^3.3.1" - }, - "devDependencies": { - "@stryker-mutator/test-helpers": "^3.3.1", - "@types/node": "^14.0.1", - "@types/socket.io": "^2.1.0", - "chai": "~4.2.0", - "mocha": "~5.2.0", - "sinon": "^9.0.0", - "web-component-tester": "~6.9.2" - }, - "peerDependencies": { - "@stryker-mutator/core": "^3.0.0", - "web-component-tester": "^6.9.0" - }, "author": "Nico Jansen ", "license": "Apache-2.0", "bugs": { @@ -46,7 +20,7 @@ "homepage": "https://github.com/stryker-mutator/stryker/tree/master/packages/wct-runner#readme", "initStrykerConfig": { "timeoutMS": 10000, - "maxConcurrentTestRunners": 4, + "concurrency": 4, "coverageAnalysis": "off" }, "engines": { diff --git a/packages/wct-runner/schema/wct-runner-options.json b/packages/wct-runner/schema/wct-runner-options.json deleted file mode 100644 index b4f9d47404..0000000000 --- a/packages/wct-runner/schema/wct-runner-options.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema", - "title": "WctRunnerOptions", - "type": "object", - "additionalProperties": false, - "properties": { - "wct": { - "description": "Configuration for the @stryker-mutator/wct-runner. For more information about the available wct options, please see [wct's config.ts file](https://github.com/Polymer/tools/blob/master/packages/web-component-tester/runner/config.ts#L36).", - "type": "object", - "properties": { - "configFile": { - "description": "Location of the 'wct.conf.json' file.", - "type": "string" - }, - "verbose": { - "description": "Enable/disable verbose WCT logging. WCT can be noisy. By default, Stryker will swallow any wct log messages. Enabling this option will forward any wct log messages to Stryker logging. Don't forget to set `logLevel` (or `fileLogLevel`) to `'debug'` in your Stryker configuration to get the most logging out of WCT.", - "type": "boolean", - "default": false - }, - "npm": { - "description": "Use WCT with the `--npm` flag. This will allow web-components installed via npm, instead of bower.", - "type": "boolean", - "default": false - } - } - } - } -} diff --git a/packages/wct-runner/src/WctLogger.ts b/packages/wct-runner/src/WctLogger.ts deleted file mode 100644 index 3a8ed40c2e..0000000000 --- a/packages/wct-runner/src/WctLogger.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { EventEmitter } from 'events'; - -import { Logger } from '@stryker-mutator/api/logging'; - -export default class WctLogger { - private readonly logProxy = { - ['log:debug']: this.log.debug.bind(this.log), - ['log:error']: this.log.error.bind(this.log), - ['log:info']: this.log.info.bind(this.log), - ['log:warn']: this.log.warn.bind(this.log), - }; - - constructor(private readonly context: EventEmitter, verbose: boolean, private readonly log: Logger) { - if (verbose) { - Object.keys(this.logProxy).forEach((logEvent) => context.on(logEvent, (this.logProxy as any)[logEvent])); - } else { - this.log.debug('Keeping wct quiet. To enable wct logging, set `wct.verbose` to `true` in your Stryker configuration file.'); - } - } - - public dispose() { - Object.keys(this.logProxy).forEach((logEvent) => this.context.removeListener(logEvent, (this.logProxy as any)[logEvent])); - } -} diff --git a/packages/wct-runner/src/WctReporter.ts b/packages/wct-runner/src/WctReporter.ts deleted file mode 100644 index 6055ce92d3..0000000000 --- a/packages/wct-runner/src/WctReporter.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { EventEmitter } from 'events'; - -import { TestResult, TestStatus } from '@stryker-mutator/api/test_runner'; -import { BrowserDef } from 'web-component-tester/runner/browserrunner'; -import { CompletedState, TestEndData } from 'web-component-tester/runner/clireporter'; - -const TEST_START_EVENT = 'test-start'; -const TEST_END_EVENT = 'test-end'; - -export default class WctReporter { - public results: TestResult[] = []; - private before = new Date(); - - constructor(private readonly context: EventEmitter) { - context.on(TEST_START_EVENT, this.testStart); - context.on(TEST_END_EVENT, this.testEnd); - } - - public dispose() { - this.context.removeListener(TEST_START_EVENT, this.testStart); - this.context.removeListener(TEST_END_EVENT, this.testEnd); - } - - // Both testStart and testEnd are properties here, rather than methods. This is deliberate to allow for `this` pointer to work - private readonly testStart = () => { - this.before = new Date(); - }; - - private readonly testEnd = (_browser: BrowserDef, result: TestEndData) => { - this.results.push({ - failureMessages: this.toFailureMessages(result.error), - name: this.testNamePartsToString(result.test), - status: this.toTestResultStatus(result.state), - timeSpentMs: new Date().getTime() - this.before.getTime(), - }); - }; - - private toFailureMessages(error: any): string[] | undefined { - switch (typeof error) { - case 'undefined': - return undefined; - case 'string': - return [error]; - case 'object': - if (error) { - if (error.stack) { - return [error.stack]; - } else { - return [JSON.stringify(error)]; - } - } else { - return undefined; - } - default: - return [error.toString()]; - } - } - - private testNamePartsToString(testNameParts: string[]): string { - // First part is the file name - return testNameParts.splice(1).join(' ').trim(); - } - - private toTestResultStatus(state: CompletedState): TestStatus { - switch (state) { - case 'failing': - return TestStatus.Failed; - case 'passing': - return TestStatus.Success; - default: - return TestStatus.Skipped; - } - } -} diff --git a/packages/wct-runner/src/WctTestRunner.ts b/packages/wct-runner/src/WctTestRunner.ts deleted file mode 100644 index 23395a00e6..0000000000 --- a/packages/wct-runner/src/WctTestRunner.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { StrykerOptions } from '@stryker-mutator/api/core'; -import { Logger } from '@stryker-mutator/api/logging'; -import { commonTokens, tokens } from '@stryker-mutator/api/plugin'; -import { RunResult, RunStatus, TestRunner } from '@stryker-mutator/api/test_runner'; -import { steps } from 'web-component-tester'; -import { Context } from 'web-component-tester/runner/context'; - -import WctLogger from './WctLogger'; -import WctReporter from './WctReporter'; - -const WCT_PACKAGE = 'web-component-tester'; -const FORCED_WCT_OPTIONS = Object.freeze({ - persistent: false, -}); - -export default class WctTestRunner implements TestRunner { - private readonly reporter: WctReporter; - private readonly context: Context; - private readonly logger: WctLogger; - - public static inject = tokens(commonTokens.logger, commonTokens.options); - constructor(private readonly log: Logger, options: StrykerOptions) { - if (options.coverageAnalysis !== 'off') { - throw new Error( - `Coverage analysis "${options.coverageAnalysis}" is not (yet) supported by the WCT test runner plugin. Please set \`coverageAnalysis: "off"\` in your config file.` - ); - } - this.log.debug('Running wct version %s from %s', require(`${WCT_PACKAGE}/package.json`).version, require.resolve(WCT_PACKAGE)); - this.context = this.loadContext(options); - this.logger = new WctLogger(this.context, this.context.options.verbose || false, this.log); - this.reporter = new WctReporter(this.context); - } - - private loadContext(options: StrykerOptions) { - const context = new Context(Object.assign({}, options.wct, FORCED_WCT_OPTIONS)); - if (this.log.isDebugEnabled()) { - this.log.debug('WCT options: %s', JSON.stringify(this.context.options)); - } - return context; - } - - public async init(): Promise { - await steps.setupOverrides(this.context); - await steps.loadPlugins(this.context); - await steps.configure(this.context); - await steps.prepare(this.context); - } - - public async run(): Promise { - this.reporter.results = []; - try { - await steps.runTests(this.context).catch(WctTestRunner.ignoreFailedTests); - return { - status: RunStatus.Complete, - tests: this.reporter.results, - }; - } catch (error) { - return { - errorMessages: [error.stack], - status: RunStatus.Error, - tests: [], - }; - } - } - - public dispose() { - this.reporter.dispose(); - this.logger.dispose(); - } - - private static ignoreFailedTests(error: Error) { - if (!/\d+ failed tests?/.exec(error.message)) { - throw error; - } - } -} diff --git a/packages/wct-runner/src/index.ts b/packages/wct-runner/src/index.ts index 71068a1661..2e6e11ef6a 100644 --- a/packages/wct-runner/src/index.ts +++ b/packages/wct-runner/src/index.ts @@ -1,9 +1,5 @@ -import { declareClassPlugin, PluginKind } from '@stryker-mutator/api/plugin'; - -import * as strykerValidationSchema from '../schema/wct-runner-options.json'; - -import WctTestRunner from './WctTestRunner'; - -export const strykerPlugins = [declareClassPlugin(PluginKind.TestRunner, 'wct', WctTestRunner)]; - -export { strykerValidationSchema }; +console.warn( + `The @stryker-mutator/wct-runner package is dropped in Stryker 4.0. Please see https://github.com/stryker-mutator/stryker/issues/2386 for more details. Feel free to keep using @stryker-mutator/wct-runner@3 or start a community fork. + Note that [support for the web-component-tester itself is minimal](https://github.com/Polymer/tools/issues/3398), you might want to consider switching to a different test runner. + Stryker still supports Mocha, Jest, Jasmine and Karma.` +); diff --git a/packages/wct-runner/stryker.conf.js b/packages/wct-runner/stryker.conf.js deleted file mode 100644 index 5f801069f7..0000000000 --- a/packages/wct-runner/stryker.conf.js +++ /dev/null @@ -1,6 +0,0 @@ -const path = require('path'); -const settings = require('../../stryker.parent.conf'); -const moduleName = __dirname.split(path.sep).pop(); -settings.dashboard.module = moduleName; -settings.coverageAnalysis = 'off'; -module.exports = settings; diff --git a/packages/wct-runner/test/helpers/consoleLoggerFactory.ts b/packages/wct-runner/test/helpers/consoleLoggerFactory.ts deleted file mode 100644 index fc984dc459..0000000000 --- a/packages/wct-runner/test/helpers/consoleLoggerFactory.ts +++ /dev/null @@ -1,16 +0,0 @@ -export default function consoleLoggerFactory(category: string) { - return { - debug: console.log.bind(console, category, 'DEBUG'), - error: console.log.bind(console, category, 'ERROR'), - fatal: console.log.bind(console, category, 'FATAL'), - info: console.log.bind(console, category, 'INFO'), - isDebugEnabled: () => true, - isErrorEnabled: () => true, - isFatalEnabled: () => true, - isInfoEnabled: () => true, - isTraceEnabled: () => true, - isWarnEnabled: () => true, - trace: console.log.bind(console, category, 'TRACE'), - warn: console.log.bind(console, category, 'WARNING'), - }; -} diff --git a/packages/wct-runner/test/helpers/initChai.ts b/packages/wct-runner/test/helpers/initChai.ts deleted file mode 100644 index 514154da42..0000000000 --- a/packages/wct-runner/test/helpers/initChai.ts +++ /dev/null @@ -1,6 +0,0 @@ -import * as chai from 'chai'; -import * as chaiAsPromised from 'chai-as-promised'; -import * as sinonChai from 'sinon-chai'; - -chai.use(sinonChai); -chai.use(chaiAsPromised); diff --git a/packages/wct-runner/test/helpers/initSinon.ts b/packages/wct-runner/test/helpers/initSinon.ts deleted file mode 100644 index b168594f22..0000000000 --- a/packages/wct-runner/test/helpers/initSinon.ts +++ /dev/null @@ -1,5 +0,0 @@ -import * as sinon from 'sinon'; - -afterEach(() => { - sinon.restore(); -}); diff --git a/packages/wct-runner/test/helpers/initSourceMaps.ts b/packages/wct-runner/test/helpers/initSourceMaps.ts deleted file mode 100644 index fcfbfda16c..0000000000 --- a/packages/wct-runner/test/helpers/initSourceMaps.ts +++ /dev/null @@ -1 +0,0 @@ -import 'source-map-support/register'; diff --git a/packages/wct-runner/test/integration/WctTestRunner.it.spec.ts b/packages/wct-runner/test/integration/WctTestRunner.it.spec.ts deleted file mode 100644 index 2484d8d949..0000000000 --- a/packages/wct-runner/test/integration/WctTestRunner.it.spec.ts +++ /dev/null @@ -1,151 +0,0 @@ -import * as path from 'path'; - -import { RunResult, RunStatus, TestResult, TestStatus } from '@stryker-mutator/api/test_runner'; -import { testInjector } from '@stryker-mutator/test-helpers'; -import { normalizeWhitespaces } from '@stryker-mutator/util'; -import { expect } from 'chai'; - -import WctTestRunner from '../../src/WctTestRunner'; - -type TimelessRunResult = { - [K in keyof RunResult]: RunResult[K] extends TestResult[] ? TimelessTestResult[] : RunResult[K]; -}; - -type TimelessTestResult = Pick>; - -describe('WctTestRunner integration', () => { - // The "root" wct configuration option is always loaded from the current directory. - // In order to test it properly, we need to grab it before- and reset it after each test. - let cwd: string; - const root = path.resolve(__dirname, '..', '..'); - - function createSut(): WctTestRunner { - return testInjector.injector.injectClass(WctTestRunner); - } - - const expectedHtmlSuiteResult: TimelessRunResult = { - status: RunStatus.Complete, - tests: [ - { name: ' is awesome', status: TestStatus.Success, failureMessages: undefined }, - { name: ' is failing', status: TestStatus.Failed, failureMessages: ['expected true to be false'] }, - { - name: ' is throwing', - status: TestStatus.Failed, - failureMessages: [ - 'This element is failing HTMLElement.throw at /components/@stryker-mutator/wct-runner/testResources/htmlTestSuite/src/failing-element.js:11', - ], - }, - ], - }; - // To enable console logging: LoggerFactory.setLogImplementation(consoleLoggerFactory); - - beforeEach(() => { - cwd = process.cwd(); - testInjector.options.coverageAnalysis = 'off'; - }); - - afterEach(() => { - process.chdir(cwd); - }); - - it('should run in an html suite with root configuration option', async () => { - // Arrange - const wctConfigFile = path.resolve(__dirname, '..', '..', 'testResources', 'htmlTestSuite', 'wct.conf.json'); - testInjector.options.wct = { - configFile: wctConfigFile, - persistent: true, // should be forced to false - root, - }; - const sut = createSut(); - - // Act - await sut.init(); - const result = await sut.run(); - - // Assert - assertRunResult(expectedHtmlSuiteResult, result); - }); - - it('should be able to run twice in quick succession (with cwd)', async () => { - // Arrange - process.chdir(path.resolve(__dirname, '..', '..', 'testResources', 'htmlTestSuite')); - const sut = createSut(); - - // Act - await sut.init(); - await sut.run(); - const result = await sut.run(); - - // Assert - assertRunResult(expectedHtmlSuiteResult, result); - }); - - it('should run in a js suite', async () => { - // Arrange - const wctConfigFile = path.resolve(__dirname, '..', '..', 'testResources', 'jsTestSuite', 'wct.conf.json'); - testInjector.options.wct = { - configFile: wctConfigFile, - root, - }; - const sut = createSut(); - const expectedResult: TimelessRunResult = { - status: RunStatus.Complete, - tests: [{ name: 'AwesomeLib is awesome', status: TestStatus.Success, failureMessages: undefined }], - }; - - // Act - await sut.init(); - const result = await sut.run(); - - // Assert - assertRunResult(expectedResult, result); - }); - - it('should fail with ~~error~~ _failed_ if a suite is garbage', async () => { - // Arrange - const wctConfigFile = path.resolve(__dirname, '..', '..', 'testResources', 'garbage', 'wct.conf.json'); - testInjector.options.wct = { - configFile: wctConfigFile, - root, - }; - const sut = createSut(); - const expectedResult: TimelessRunResult = { - status: RunStatus.Complete, // We want to actually expect an error here, but wct doesn't let is. - tests: [ - { - name: '', - status: TestStatus.Failed, - failureMessages: ['Random error at /components/@stryker-mutator/wct-runner/testResources/garbage/test/gargbage-tests.js:1'], - }, - ], - }; - - // Act - await sut.init(); - const result = await sut.run(); - - // Assert - assertRunResult(expectedResult, result); - }); - - function assertRunResult(expected: TimelessRunResult, actual: RunResult) { - expect(actual.errorMessages).eq(expected.errorMessages); - expect(actual.status).eq(expected.status); - const actualTestIterator = actual.tests[Symbol.iterator](); - for (const expectedTest of expected.tests) { - const actualTest = actualTestIterator.next().value; - expect(expectedTest.name).eq(actualTest.name); - expect(expectedTest.status).eq(actualTest.status); - if (expectedTest.failureMessages) { - expect(actualTest.failureMessages).ok; - if (actualTest.failureMessages) { - const actualFailureMessagesIterator = actualTest.failureMessages[Symbol.iterator](); - for (const expectedFailureMessage of expectedTest.failureMessages) { - const actualFailureMessage = actualFailureMessagesIterator.next().value; - expect(normalizeWhitespaces(actualFailureMessage)).contains(expectedFailureMessage); - } - } - } - } - } -}); diff --git a/packages/wct-runner/test/unit/WctLogger.spec.ts b/packages/wct-runner/test/unit/WctLogger.spec.ts deleted file mode 100644 index d1d0cd5566..0000000000 --- a/packages/wct-runner/test/unit/WctLogger.spec.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { EventEmitter } from 'events'; - -import { testInjector } from '@stryker-mutator/test-helpers'; -import { expect } from 'chai'; - -import WctLogger from '../../src/WctLogger'; - -describe(WctLogger.name, () => { - let context: EventEmitter; - let sut: WctLogger; - - beforeEach(() => { - context = new EventEmitter(); - }); - - afterEach(() => { - sut.dispose(); - expect(context.listenerCount('log:debug')).eq(0); - expect(context.listenerCount('log:error')).eq(0); - expect(context.listenerCount('log:info')).eq(0); - expect(context.listenerCount('log:warn')).eq(0); - }); - - it('should not forward logging when verbose = false', () => { - sut = new WctLogger(context, false, testInjector.logger); - emitAllLogEvents(); - expect(testInjector.logger.debug).calledWith( - 'Keeping wct quiet. To enable wct logging, set `wct.verbose` to `true` in your Stryker configuration file.' - ); - expect(testInjector.logger.info).not.called; - expect(testInjector.logger.warn).not.called; - expect(testInjector.logger.error).not.called; - }); - - it('should forward all logging when verbose = true', () => { - sut = new WctLogger(context, true, testInjector.logger); - emitAllLogEvents(); - expect(testInjector.logger.debug).calledWith('debug'); - expect(testInjector.logger.info).calledWith('info'); - expect(testInjector.logger.warn).calledWith('warn'); - expect(testInjector.logger.error).calledWith('error'); - }); - - function emitAllLogEvents() { - ['debug', 'info', 'warn', 'error'].forEach((logEvent) => { - context.emit(`log:${logEvent}`, logEvent); - }); - } -}); diff --git a/packages/wct-runner/test/unit/WctReporter.spec.ts b/packages/wct-runner/test/unit/WctReporter.spec.ts deleted file mode 100644 index 82c2d98dd5..0000000000 --- a/packages/wct-runner/test/unit/WctReporter.spec.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { EventEmitter } from 'events'; - -import { TestResult, TestStatus } from '@stryker-mutator/api/test_runner'; -import { expect } from 'chai'; -import * as sinon from 'sinon'; -import { TestEndData } from 'web-component-tester/runner/clireporter'; - -import WctReporter from '../../src/WctReporter'; - -describe(WctReporter.name, () => { - let context: EventEmitter; - let sut: WctReporter; - - beforeEach(() => { - context = new EventEmitter(); - sinon.useFakeTimers(); - sut = new WctReporter(context); - }); - - afterEach(() => { - sut.dispose(); - expect(context.listenerCount('test-end')).eq(0); - expect(context.listenerCount('test-start')).eq(0); - }); - - it('should report no tests', () => { - expect(sut.results).lengthOf(0); - expect(context.listenerCount('test-end')).eq(1); - expect(context.listenerCount('test-start')).eq(1); - }); - - it('should report a passing test', () => { - actAssertReportTest( - { - duration: 2, - error: null, - state: 'passing', - test: ['fooSpec.js', 'Foo', 'bar()', 'should baz'], - }, - 10, - { name: 'Foo bar() should baz', status: TestStatus.Success, timeSpentMs: 10, failureMessages: undefined } - ); - }); - - it('should report a failing test with error as string', () => { - actAssertReportTest({ duration: 2, error: 'fooError', state: 'failing', test: ['fooSpec.js', 'true should be false'] }, 40, { - failureMessages: ['fooError'], - name: 'true should be false', - status: TestStatus.Failed, - timeSpentMs: 40, - }); - }); - - it('should report a failing test with error as serialized error', () => { - actAssertReportTest({ duration: 2, error: { stack: 'fooError' }, state: 'failing', test: ['fooSpec.js', 'true should be false'] }, 40, { - failureMessages: ['fooError'], - name: 'true should be false', - status: TestStatus.Failed, - timeSpentMs: 40, - }); - }); - - it('should report a failing test with error as object', () => { - actAssertReportTest({ duration: 2, error: { a: 'fooError' }, state: 'failing', test: ['fooSpec.js', 'true should be false'] }, 40, { - failureMessages: ['{"a":"fooError"}'], - name: 'true should be false', - status: TestStatus.Failed, - timeSpentMs: 40, - }); - }); - - it('should report a failing test with error as number', () => { - actAssertReportTest({ duration: 2, error: 42, state: 'failing', test: ['fooSpec.js', 'true should be false'] }, 40, { - failureMessages: ['42'], - name: 'true should be false', - status: TestStatus.Failed, - timeSpentMs: 40, - }); - }); - - it('should report a failing test with error as string', () => { - actAssertReportTest({ duration: 2, error: 'fooError', state: 'failing', test: ['fooSpec.js', 'true should be false'] }, 40, { - failureMessages: ['fooError'], - name: 'true should be false', - status: TestStatus.Failed, - timeSpentMs: 40, - }); - }); - - it('should report a skipped test', () => { - actAssertReportTest({ duration: 2, error: undefined, state: 'pending', test: ['fooSpec.js', 'true should be false'] }, 40, { - failureMessages: undefined, - name: 'true should be false', - status: TestStatus.Skipped, - timeSpentMs: 40, - }); - }); - - function actAssertReportTest(actualTestData: TestEndData, actualTimeSpent: number, expectedTestResult: TestResult) { - // Act - raiseTestStarted(); - sinon.clock.tick(actualTimeSpent); - raiseTestEnded(actualTestData); - - // Assert - const expectedTestResults: TestResult[] = [expectedTestResult]; - expect(sut.results).deep.eq(expectedTestResults); - } - - function raiseTestEnded(testEndData: TestEndData) { - context.emit('test-end', null, testEndData); - } - - function raiseTestStarted() { - context.emit('test-start'); - } -}); diff --git a/packages/wct-runner/test/unit/WctTestRunner.spec.ts b/packages/wct-runner/test/unit/WctTestRunner.spec.ts deleted file mode 100644 index 59b784c567..0000000000 --- a/packages/wct-runner/test/unit/WctTestRunner.spec.ts +++ /dev/null @@ -1,134 +0,0 @@ -import { RunResult, RunStatus, TestStatus } from '@stryker-mutator/api/test_runner'; -import { testInjector } from '@stryker-mutator/test-helpers'; -import { expect } from 'chai'; -import * as sinon from 'sinon'; -import { steps } from 'web-component-tester'; -import * as wctModule from 'web-component-tester'; -import * as contextModule from 'web-component-tester/runner/context'; - -import WctLogger, * as wctLoggerModule from '../../src/WctLogger'; -import WctReporter, * as wctReporterModule from '../../src/WctReporter'; -import WctTestRunner from '../../src/WctTestRunner'; - -describe(WctTestRunner.name, () => { - let contextMock: sinon.SinonStubbedInstance; - let wctLoggerMock: sinon.SinonStubbedInstance; - let wctReporterMock: sinon.SinonStubbedInstance; - let stepsMock: sinon.SinonStubbedInstance; - - function createSut(): WctTestRunner { - return testInjector.injector.injectClass(WctTestRunner); - } - - beforeEach(() => { - contextMock = sinon.createStubInstance(contextModule.Context); - stepsMock = { - cancelTests: sinon.stub(), - configure: sinon.stub(), - loadPlugins: sinon.stub(), - prepare: sinon.stub(), - runTests: sinon.stub(), - setupOverrides: sinon.stub(), - }; - testInjector.options.coverageAnalysis = 'off'; - contextMock.options = {}; - wctLoggerMock = sinon.createStubInstance(WctLogger); - wctReporterMock = sinon.createStubInstance(WctReporter); - sinon.stub(contextModule, 'Context').returns(contextMock); - sinon.stub(wctLoggerModule, 'default').returns(wctLoggerMock); - sinon.stub(wctReporterModule, 'default').returns(wctReporterMock); - sinon.stub(wctModule, 'steps').value(stepsMock); - }); - - it('should create a context using wct options, with `persistent = false`', () => { - const wctOptions = { foo: 'bar', persistent: true }; - const expectedWctOptions = { foo: 'bar', persistent: false }; - testInjector.options.wct = wctOptions; - createSut(); - expect(contextModule.Context).calledWithNew; - expect(contextModule.Context).calledWith(expectedWctOptions); - }); - - it('should create a reporter', () => { - createSut(); - expect(wctReporterModule.default).calledWithNew; - expect(wctReporterModule.default).calledWith(contextMock); - }); - - it('should create a logger', () => { - contextMock.options.verbose = true; - createSut(); - expect(wctLoggerModule.default).calledWithNew; - expect(wctLoggerModule.default).calledWith(contextMock, true); - }); - - it('should throw when coverageAnalysis != "off"', () => { - testInjector.options.coverageAnalysis = 'all'; - const expectedError = - 'Coverage analysis "all" is not (yet) supported by the WCT test runner plugin. Please set `coverageAnalysis: "off"` in your config file.'; - expect(() => createSut()).throws(expectedError); - }); - - describe('init', () => { - it('should run initialization steps', async () => { - const sut = createSut(); - await sut.init(); - expect(stepsMock.setupOverrides).calledBefore(stepsMock.loadPlugins); - expect(stepsMock.loadPlugins).calledBefore(stepsMock.configure); - expect(stepsMock.configure).calledBefore(stepsMock.prepare); - expect(stepsMock.setupOverrides).calledWith(contextMock); - expect(stepsMock.loadPlugins).calledWith(contextMock); - expect(stepsMock.configure).calledWith(contextMock); - expect(stepsMock.prepare).calledWith(contextMock); - }); - }); - - describe('dispose', () => { - it('should run dispose the logger and reporter', () => { - const sut = createSut(); - sut.dispose(); - expect(wctLoggerMock.dispose).called; - expect(wctReporterMock.dispose).called; - }); - }); - - describe('run', () => { - it('should run clear tests', async () => { - stepsMock.runTests.resolves(); - const sut = createSut(); - wctReporterMock.results = [{ name: 'foobar', status: TestStatus.Success, timeSpentMs: 4 }]; - const actual = await sut.run(); - const expectedRunResult: RunResult = { status: RunStatus.Complete, tests: [] }; - expect(actual).deep.eq(expectedRunResult); - }); - - it('should run tests', async () => { - stepsMock.runTests.resolves(); - const sut = createSut(); - const runPromise = sut.run(); - const expectedTests = (wctReporterMock.results = [{ name: 'foobar', status: TestStatus.Success, timeSpentMs: 4 }]); - const actual = await runPromise; - const expectedRunResult: RunResult = { status: RunStatus.Complete, tests: expectedTests }; - expect(actual).deep.eq(expectedRunResult); - }); - - it('should ignore errors from failed tests', async () => { - stepsMock.runTests.rejects(new Error('23 failed tests')); - const sut = createSut(); - const runPromise = sut.run(); - const expectedTests = (wctReporterMock.results = [{ name: 'foobar', status: TestStatus.Failed, timeSpentMs: 4 }]); - const actual = await runPromise; - const expectedRunResult: RunResult = { status: RunStatus.Complete, tests: expectedTests }; - expect(actual).deep.eq(expectedRunResult); - }); - - it('should not ignore other errors', async () => { - const expectedError = new Error('Foobar Error'); - stepsMock.runTests.rejects(expectedError); - const sut = createSut(); - const actualResult = await sut.run(); - expect(actualResult.status).eq(RunStatus.Error); - expect(actualResult.errorMessages).deep.eq([expectedError.stack]); - }); - }); -}); diff --git a/packages/wct-runner/testResources/garbage/test/gargbage-tests.js b/packages/wct-runner/testResources/garbage/test/gargbage-tests.js deleted file mode 100644 index 88606ded92..0000000000 --- a/packages/wct-runner/testResources/garbage/test/gargbage-tests.js +++ /dev/null @@ -1 +0,0 @@ -throw new Error('Random error'); \ No newline at end of file diff --git a/packages/wct-runner/testResources/garbage/wct.conf.json b/packages/wct-runner/testResources/garbage/wct.conf.json deleted file mode 100644 index 7881715d64..0000000000 --- a/packages/wct-runner/testResources/garbage/wct.conf.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "verbose": true, - "suites": ["testResources/garbage/test"], - "plugins": { - "local": { - "browsers": ["chrome"], - "skipSeleniumInstall": true, - "browserOptions": { - "chrome": ["window-size=1920,1080", "headless", "disable-gpu"], - "firefox": ["--headless"] - } - } - }, - "npm": true, - "root": "../../.." -} \ No newline at end of file diff --git a/packages/wct-runner/testResources/htmlTestSuite/src/awesome-element.js b/packages/wct-runner/testResources/htmlTestSuite/src/awesome-element.js deleted file mode 100644 index 61d83f0d2a..0000000000 --- a/packages/wct-runner/testResources/htmlTestSuite/src/awesome-element.js +++ /dev/null @@ -1,9 +0,0 @@ -class AwesomeElement extends HTMLElement { - static get is() { - return 'awesome-element'; - } - get isAwesome() { - return true; - } -} -window.customElements.define(AwesomeElement.is, AwesomeElement); \ No newline at end of file diff --git a/packages/wct-runner/testResources/htmlTestSuite/src/failing-element.js b/packages/wct-runner/testResources/htmlTestSuite/src/failing-element.js deleted file mode 100644 index 7727f73d7a..0000000000 --- a/packages/wct-runner/testResources/htmlTestSuite/src/failing-element.js +++ /dev/null @@ -1,14 +0,0 @@ -class FailingElement extends HTMLElement { - static get is() { - return 'failing-element'; - } - - get isFailing() { - return true; - } - - throw() { - throw new Error('This element is failing') - } -} -window.customElements.define(FailingElement.is, FailingElement); \ No newline at end of file diff --git a/packages/wct-runner/testResources/htmlTestSuite/test/awesome-tests.html b/packages/wct-runner/testResources/htmlTestSuite/test/awesome-tests.html deleted file mode 100644 index e357f47195..0000000000 --- a/packages/wct-runner/testResources/htmlTestSuite/test/awesome-tests.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/wct-runner/testResources/htmlTestSuite/test/failing-tests.html b/packages/wct-runner/testResources/htmlTestSuite/test/failing-tests.html deleted file mode 100644 index ed781ca377..0000000000 --- a/packages/wct-runner/testResources/htmlTestSuite/test/failing-tests.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/packages/wct-runner/testResources/htmlTestSuite/wct.conf.json b/packages/wct-runner/testResources/htmlTestSuite/wct.conf.json deleted file mode 100644 index 48dd307a62..0000000000 --- a/packages/wct-runner/testResources/htmlTestSuite/wct.conf.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "verbose": true, - "suites": [ - "testResources/htmlTestSuite/test" - ], - "plugins": { - "local": { - "browsers": [ - "chrome" - ], - "skipSeleniumInstall": true, - "browserOptions": { - "chrome": ["window-size=1920,1080", "headless", "disable-gpu"], - "firefox": ["--headless"] - } - } - }, - "npm": true, - "root": "../.." -} \ No newline at end of file diff --git a/packages/wct-runner/testResources/jsTestSuite/test/awesome-tests.js b/packages/wct-runner/testResources/jsTestSuite/test/awesome-tests.js deleted file mode 100644 index d5ca7be9c1..0000000000 --- a/packages/wct-runner/testResources/jsTestSuite/test/awesome-tests.js +++ /dev/null @@ -1,6 +0,0 @@ - -suite('AwesomeLib', () => { - test('is awesome', () => { - assert.isTrue(true); - }); -}); \ No newline at end of file diff --git a/packages/wct-runner/testResources/jsTestSuite/wct.conf.json b/packages/wct-runner/testResources/jsTestSuite/wct.conf.json deleted file mode 100644 index ca700ee90d..0000000000 --- a/packages/wct-runner/testResources/jsTestSuite/wct.conf.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "verbose": true, - "suites": ["testResources/jsTestSuite/test"], - "plugins": { - "local": { - "browsers": ["chrome"], - "skipSeleniumInstall": true, - "browserOptions": { - "chrome": ["window-size=1920,1080", "headless", "disable-gpu"], - "firefox": ["--headless"] - } - } - }, - "npm": true, - "root": "../../.." -} \ No newline at end of file diff --git a/packages/wct-runner/tsconfig.stryker.json b/packages/wct-runner/tsconfig.stryker.json deleted file mode 100644 index ae424d3c8f..0000000000 --- a/packages/wct-runner/tsconfig.stryker.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "./tsconfig.test.json", - "include": [ - "src", - "src-generated", - "schema/*.json", - "test", - "typings" - ], -} diff --git a/packages/wct-runner/typings/wct.d.ts b/packages/wct-runner/typings/wct.d.ts deleted file mode 100644 index 53bdd188bf..0000000000 --- a/packages/wct-runner/typings/wct.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -declare module 'web-component-tester' { - const cli: typeof import('./web-component-tester/runner/cli'); - const config: typeof import('./web-component-tester/runner/config'); - const steps: typeof import('./web-component-tester/runner/steps'); - const test: typeof import('./web-component-tester/runner/test'); -} \ No newline at end of file diff --git a/packages/wct-runner/typings/wd.d.ts b/packages/wct-runner/typings/wd.d.ts deleted file mode 100644 index 84a444273f..0000000000 --- a/packages/wct-runner/typings/wd.d.ts +++ /dev/null @@ -1,61 +0,0 @@ - - -declare module 'wd' { - interface NodeCB { - (err: any, value: T): void; - } - export interface Browser { - configureHttp(options: { - retries: number - }): void; - attach(sessionId: string, callback: NodeCB): void; - init(capabilities: Capabilities, callback: NodeCB): void; - - get(url: string, callback: NodeCB): void; - quit(callback: NodeCB): void; - - on(eventName: string, handler: Function): void; - } - export interface Capabilities { - /** The name of the browser being used */ - browserName: 'android' | 'chrome' | 'firefox' | 'htmlunit' | 'internet explorer' | 'iPhone' | 'iPad' | 'opera' | 'safari'; - /** The browser version, or the empty string if unknown. */ - version: string; - /** A key specifying which platform the browser should be running on. */ - platform: 'WINDOWS' | 'XP' | 'VISTA' | 'MAC' | 'LINUX' | 'UNIX' | 'ANDROID' | 'ANY'; - - /** Whether the session can interact with modal popups, - * such as window.alert and window.confirm. */ - handlesAlerts: boolean; - /** Whether the session supports CSS selectors when searching for elements. */ - cssSelectorsEnabled: boolean; - - webdriver: { - remote: { - quietExceptions: boolean; - } - }; - - selenium: { - server: { - url: string; - } - }; - } - - export function remote( - hostnameOrUrl: string, port?: number, - username?: string, password?: string): Browser; - export function remote( - options: { - hostname: string, port?: number, - auth?: string, path?: string, - } - ): Browser; - export function remote( - options: { - host: string, port?: number, - username?: string, accesskey?: string, path?: string, - } - ): Browser; -} diff --git a/packages/wct-runner/typings/web-component-tester/runner/browserrunner.d.ts b/packages/wct-runner/typings/web-component-tester/runner/browserrunner.d.ts deleted file mode 100644 index 9ba7e7cd7a..0000000000 --- a/packages/wct-runner/typings/web-component-tester/runner/browserrunner.d.ts +++ /dev/null @@ -1,66 +0,0 @@ -/** - * @license - * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. - * This code may only be used under the BSD style license found at - * http://polymer.github.io/LICENSE.txt - * The complete set of authors may be found at - * http://polymer.github.io/AUTHORS.txt - * The complete set of contributors may be found at - * http://polymer.github.io/CONTRIBUTORS.txt - * Code distributed by Google as part of the polymer project is also - * subject to an additional IP rights grant found at - * http://polymer.github.io/PATENTS.txt - */ -/// -import * as wd from 'wd'; -import { Config } from './config'; -export interface Stats { - status: string; - passing?: number; - pending?: number; - failing?: number; -} -export interface BrowserDef extends wd.Capabilities { - id: number; - url: string; - sessionId: string; - deviceName?: string; - variant?: string; -} -export declare class BrowserRunner { - timeout: number; - browser: wd.Browser; - stats: Stats; - sessionId: string; - timeoutId: NodeJS.Timer; - emitter: NodeJS.EventEmitter; - def: BrowserDef; - options: Config; - donePromise: Promise; - /** - * The url of the initial page to load in the browser when starting tests. - */ - url: string; - private _resolve; - private _reject; - /** - * @param emitter The emitter to send updates about test progress to. - * @param def A BrowserDef describing and defining the browser to be run. - * Includes both metadata and a method for connecting/launching the - * browser. - * @param options WCT options. - * @param url The url of the generated index.html file that the browser should - * point at. - * @param waitFor Optional. If given, we won't try to start/connect to the - * browser until this promise resolves. Used for serializing access to - * Safari webdriver, which can only have one instance running at once. - */ - constructor(emitter: NodeJS.EventEmitter, def: BrowserDef, options: Config, url: string, waitFor?: Promise); - _init(error: any, sessionId: string): void; - startTest(): void; - onEvent(event: string, data: any): void; - done(error: any): void; - extendTimeout(): void; - quit(): void; - static BrowserRunner: typeof BrowserRunner; -} diff --git a/packages/wct-runner/typings/web-component-tester/runner/cli.d.ts b/packages/wct-runner/typings/web-component-tester/runner/cli.d.ts deleted file mode 100644 index af8cbd46d8..0000000000 --- a/packages/wct-runner/typings/web-component-tester/runner/cli.d.ts +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @license - * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. - * This code may only be used under the BSD style license found at - * http://polymer.github.io/LICENSE.txt - * The complete set of authors may be found at - * http://polymer.github.io/AUTHORS.txt - * The complete set of contributors may be found at - * http://polymer.github.io/CONTRIBUTORS.txt - * Code distributed by Google as part of the polymer project is also - * subject to an additional IP rights grant found at - * http://polymer.github.io/PATENTS.txt - */ -/// -/// -export declare function run(_env: any, args: string[], output: NodeJS.WritableStream): Promise; -export declare function runSauceTunnel(_env: any, args: string[], output: NodeJS.WritableStream): Promise; diff --git a/packages/wct-runner/typings/web-component-tester/runner/clireporter.d.ts b/packages/wct-runner/typings/web-component-tester/runner/clireporter.d.ts deleted file mode 100644 index c7fc1943b0..0000000000 --- a/packages/wct-runner/typings/web-component-tester/runner/clireporter.d.ts +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @license - * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. - * This code may only be used under the BSD style license found at - * http://polymer.github.io/LICENSE.txt - * The complete set of authors may be found at - * http://polymer.github.io/AUTHORS.txt - * The complete set of contributors may be found at - * http://polymer.github.io/CONTRIBUTORS.txt - * Code distributed by Google as part of the polymer project is also - * subject to an additional IP rights grant found at - * http://polymer.github.io/PATENTS.txt - */ -/// -/// -import * as events from 'events'; -import { BrowserDef, Stats } from './browserrunner'; -import * as config from './config'; -export declare type State = 'passing' | 'pending' | 'failing' | 'unknown' | 'error'; -export declare type CompletedState = 'passing' | 'failing' | 'pending' | 'unknown'; -export interface TestEndData { - state: CompletedState; - /** - * The titles of the tests that ran. - */ - test: string[]; - duration: number; - error: any; -} -export declare class CliReporter { - prettyBrowsers: { - [id: number]: string; - }; - browserStats: { - [id: number]: Stats; - }; - emitter: events.EventEmitter; - stream: NodeJS.WritableStream; - options: config.Config; - /** - * The number of lines written the last time writeLines was called. - */ - private linesWritten; - constructor(emitter: events.EventEmitter, stream: NodeJS.WritableStream, options: config.Config); - updateStatus(force?: boolean): void; - writeTestError(browser: BrowserDef, data: TestEndData): void; - stateIcon(state: State): string; - prettyTest(data: TestEndData): string; - prettyBrowser(browser: BrowserDef): any; - log(...values: any[]): void; - writeWrapped(blocks: string[], separator: string): void; - write(line: string): void; - writeLines(lines: string[]): void; - flush(): void; - static CliReporter: typeof CliReporter; -} diff --git a/packages/wct-runner/typings/web-component-tester/runner/config.d.ts b/packages/wct-runner/typings/web-component-tester/runner/config.d.ts deleted file mode 100644 index bf0fe7a133..0000000000 --- a/packages/wct-runner/typings/web-component-tester/runner/config.d.ts +++ /dev/null @@ -1,136 +0,0 @@ -/** - * @license - * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. - * This code may only be used under the BSD style license found at - * http://polymer.github.io/LICENSE.txt - * The complete set of authors may be found at - * http://polymer.github.io/AUTHORS.txt - * The complete set of contributors may be found at - * http://polymer.github.io/CONTRIBUTORS.txt - * Code distributed by Google as part of the polymer project is also - * subject to an additional IP rights grant found at - * http://polymer.github.io/PATENTS.txt - */ -/// -/// -import { Capabilities } from 'wd'; -import { BrowserDef } from './browserrunner'; -import { Context } from './context'; -export declare type Browser = string | { - browserName: string; - platform: string; -}; -export interface Config { - suites?: string[]; - output?: NodeJS.WritableStream; - ttyOutput?: boolean; - verbose?: boolean; - quiet?: boolean; - expanded?: boolean; - root?: string; - testTimeout?: number; - persistent?: boolean; - extraScripts?: string[]; - wctPackageName?: string; - clientOptions?: { - root?: string; - verbose?: boolean; - environmentScripts?: string[]; - }; - activeBrowsers?: BrowserDef[]; - browserOptions?: { - [name: string]: Capabilities; - }; - plugins?: (string | boolean)[] | { - [key: string]: ({ - disabled: boolean; - } | boolean); - }; - registerHooks?: (wct: Context) => void; - enforceJsonConf?: boolean; - webserver?: { - port: number; - hostname: string; - _generatedIndexContent?: string; - _servers?: { - variant: string; - url: string; - }[]; - }; - npm?: boolean; - moduleResolution?: 'none' | 'node'; - packageName?: string; - skipPlugins?: string[]; - sauce?: {}; - remote?: {}; - origSuites?: string[]; - compile?: 'auto' | 'always' | 'never'; - skipCleanup?: boolean; - simpleOutput?: boolean; - skipUpdateCheck?: boolean; - configFile?: string; - proxy?: { - path: string; - target: string; - }; - /** A deprecated option */ - browsers?: Browser[] | Browser; -} -/** - * Determines the package name by reading from the following sources: - * - * 1. `options.packageName` - * 2. bower.json or package.json, depending on options.npm - */ -export declare function getPackageName(options: Config): string | undefined; -export declare function defaults(): Config; -export interface PreparsedArgs { - plugins?: string[]; - skipPlugins?: string[]; - simpleOutput?: boolean; - skipUpdateCheck?: boolean; -} -/** - * Discovers appropriate config files (global, and for the project), merging - * them, and returning them. - * - * @param {string} matcher - * @param {string} root - * @return {!Object} The merged configuration. - */ -export declare function fromDisk(matcher: string, root?: string): Config; -/** - * Runs a simplified options parse over the command line arguments, extracting - * any values that are necessary for a full parse. - * - * See const: PREPARSE_ARGS for the values that are extracted. - * - * @param {!Array} args - * @return {!Object} - */ -export declare function preparseArgs(args: string[]): PreparsedArgs; -/** - * Runs a complete options parse over the args, respecting plugin options. - * - * @param {!Context} context The context, containing plugin state and any base - * options to merge into. - * @param {!Array} args The args to parse. - */ -export declare function parseArgs(context: Context, args: string[]): Promise; -/** - * @param {!Object...} configs Configuration objects to merge. - * @return {!Object} The merged configuration, where configuration objects - * specified later in the arguments list are given precedence. - */ -export declare function merge(...configs: Config[]): Config; -export declare function normalize(config: Config): Config; -/** - * Expands values within the configuration based on the current environment. - * - * @param {!Context} context The context for the current run. - */ -export declare function expand(context: Context): Promise; -/** - * @param {!Object} options The configuration to validate. - */ -export declare function validate(options: Config): Promise; diff --git a/packages/wct-runner/typings/web-component-tester/runner/context.d.ts b/packages/wct-runner/typings/web-component-tester/runner/context.d.ts deleted file mode 100644 index 06753ca4ca..0000000000 --- a/packages/wct-runner/typings/web-component-tester/runner/context.d.ts +++ /dev/null @@ -1,90 +0,0 @@ -/** - * @license - * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. - * This code may only be used under the BSD style license found at - * http://polymer.github.io/LICENSE.txt - * The complete set of authors may be found at - * http://polymer.github.io/AUTHORS.txt - * The complete set of contributors may be found at - * http://polymer.github.io/CONTRIBUTORS.txt - * Code distributed by Google as part of the polymer project is also - * subject to an additional IP rights grant found at - * http://polymer.github.io/PATENTS.txt - */ -/// -/// -/// -import * as events from 'events'; -import * as express from 'express'; -import { ServerOptions } from 'polyserve/lib/start_server'; -import * as http from 'spdy'; -import { BrowserRunner } from './browserrunner'; -import * as config from './config'; -import { Plugin } from './plugin'; -export declare type Handler = ((...args: any[]) => Promise) | ((done: (err?: any) => void) => void) | ((arg1: any, done: (err?: any) => void) => void) | ((arg1: any, arg2: any, done: (err?: any) => void) => void) | ((arg1: any, arg2: any, arg3: any, done: (err?: any) => void) => void); -/** - * Exposes the current state of a WCT run, and emits events/hooks for anyone - * downstream to listen to. - * - * TODO(rictic): break back-compat with plugins by moving hooks entirely away - * from callbacks to promises. Easiest way to do this would be to rename - * the hook-related methods on this object, so that downstream callers would - * break in obvious ways. - * - * @param {Object} options Any initially specified options. - */ -export declare class Context extends events.EventEmitter { - options: config.Config; - private _hookHandlers; - _socketIOServers: SocketIO.Server[]; - _httpServers: http.Server[]; - _testRunners: BrowserRunner[]; - constructor(options?: config.Config); - /** - * Registers a handler for a particular hook. Hooks are typically configured - * to run _before_ a particular behavior. - */ - hook(name: string, handler: Handler): void; - /** - * Registers a handler that will run after any handlers registered so far. - * - * @param {string} name - * @param {function(!Object, function(*))} handler - */ - hookLate(name: string, handler: Handler): void; - /** - * Once all registered handlers have run for the hook, your callback will be - * triggered. If any of the handlers indicates an error state, any subsequent - * handlers will be canceled, and the error will be passed to the callback for - * the hook. - * - * Any additional arguments passed between `name` and `done` will be passed to - * hooks (before the callback). - * - * @param {string} name - * @param {function(*)} done - * @return {!Context} - */ - emitHook(name: 'define:webserver', app: express.Express, mapper: (app: Express.Application) => void, options: ServerOptions, done?: (err?: any) => void): Promise; - emitHook(name: 'prepare:webserver', app: express.Express, done?: (err?: any) => void): Promise; - emitHook(name: 'configure', done?: (err?: any) => void): Promise; - emitHook(name: 'prepare', done?: (err?: any) => void): Promise; - emitHook(name: 'cleanup', done?: (err?: any) => void): Promise; - emitHook(name: string, done?: (err?: any) => void): Promise; - emitHook(name: string, ...args: any[]): Promise; - /** - * @param {function(*, Array)} done Asynchronously loads the plugins - * requested by `options.plugins`. - */ - plugins(): Promise; - /** - * @return {!Array} The names of enabled plugins. - */ - enabledPlugins(): string[]; - /** - * @param {string} name - * @return {!Object} - */ - pluginOptions(name: string): any; - static Context: typeof Context; -} diff --git a/packages/wct-runner/typings/web-component-tester/runner/httpbin.d.ts b/packages/wct-runner/typings/web-component-tester/runner/httpbin.d.ts deleted file mode 100644 index 97490b2c97..0000000000 --- a/packages/wct-runner/typings/web-component-tester/runner/httpbin.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -/** - * @license - * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. - * This code may only be used under the BSD style license found at - * http://polymer.github.io/LICENSE.txt - * The complete set of authors may be found at - * http://polymer.github.io/AUTHORS.txt - * The complete set of contributors may be found at - * http://polymer.github.io/CONTRIBUTORS.txt - * Code distributed by Google as part of the polymer project is also - * subject to an additional IP rights grant found at - * http://polymer.github.io/PATENTS.txt - */ -import { Router } from 'express'; -export { Router } from 'express'; -export declare const httpbin: Router; diff --git a/packages/wct-runner/typings/web-component-tester/runner/paths.d.ts b/packages/wct-runner/typings/web-component-tester/runner/paths.d.ts deleted file mode 100644 index 52c40e35e2..0000000000 --- a/packages/wct-runner/typings/web-component-tester/runner/paths.d.ts +++ /dev/null @@ -1,22 +0,0 @@ -/** - * @license - * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. - * This code may only be used under the BSD style license found at - * http://polymer.github.io/LICENSE.txt - * The complete set of authors may be found at - * http://polymer.github.io/AUTHORS.txt - * The complete set of contributors may be found at - * http://polymer.github.io/CONTRIBUTORS.txt - * Code distributed by Google as part of the polymer project is also - * subject to an additional IP rights grant found at - * http://polymer.github.io/PATENTS.txt - */ -/** - * Expands a series of path patterns (globs, files, directories) into a set of - * files that represent those patterns. - * - * @param baseDir The directory that patterns are relative to. - * @param patterns The patterns to expand. - * @returns The expanded paths. - */ -export declare function expand(baseDir: string, patterns: string[]): Promise; diff --git a/packages/wct-runner/typings/web-component-tester/runner/plugin.d.ts b/packages/wct-runner/typings/web-component-tester/runner/plugin.d.ts deleted file mode 100644 index 53dc12043e..0000000000 --- a/packages/wct-runner/typings/web-component-tester/runner/plugin.d.ts +++ /dev/null @@ -1,45 +0,0 @@ -/** - * @license - * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. - * This code may only be used under the BSD style license found at - * http://polymer.github.io/LICENSE.txt - * The complete set of authors may be found at - * http://polymer.github.io/AUTHORS.txt - * The complete set of contributors may be found at - * http://polymer.github.io/CONTRIBUTORS.txt - * Code distributed by Google as part of the polymer project is also - * subject to an additional IP rights grant found at - * http://polymer.github.io/PATENTS.txt - */ -import { Config } from './config'; -import { Context } from './context'; -export interface Metadata { -} -/** - * A WCT plugin. This constructor is private. Plugins can be retrieved via - * `Plugin.get`. - */ -export declare class Plugin { - name: string; - cliConfig: Config; - packageName: string; - metadata: Metadata; - constructor(packageName: string, metadata: Metadata); - /** - * @param {!Context} context The context that this plugin should be evaluated - * within. - */ - execute(context: Context): Promise; - /** - * Retrieves a plugin by shorthand or module name (loading it as necessary). - * - * @param {string} name - */ - static get(name: string): Promise; - /** - * @param {string} name - * @return {string} The short form of `name`. - */ - static shortName(name: string): string; - static Plugin: typeof Plugin; -} diff --git a/packages/wct-runner/typings/web-component-tester/runner/port-scanner.d.ts b/packages/wct-runner/typings/web-component-tester/runner/port-scanner.d.ts deleted file mode 100644 index 881c76d8b5..0000000000 --- a/packages/wct-runner/typings/web-component-tester/runner/port-scanner.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @license - * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. - * This code may only be used under the BSD style license found at - * http://polymer.github.io/LICENSE.txt - * The complete set of authors may be found at - * http://polymer.github.io/AUTHORS.txt - * The complete set of contributors may be found at - * http://polymer.github.io/CONTRIBUTORS.txt - * Code distributed by Google as part of the polymer project is also - * subject to an additional IP rights grant found at - * http://polymer.github.io/PATENTS.txt - */ -export declare function findPort(ports: number[]): Promise; diff --git a/packages/wct-runner/typings/web-component-tester/runner/steps.d.ts b/packages/wct-runner/typings/web-component-tester/runner/steps.d.ts deleted file mode 100644 index 1ed543d09f..0000000000 --- a/packages/wct-runner/typings/web-component-tester/runner/steps.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Context } from './context'; -import { Plugin } from './plugin'; -export declare function setupOverrides(context: Context): Promise; -export declare function loadPlugins(context: Context): Promise; -export declare function configure(context: Context): Promise; -/** - * The prepare step is where a lot of the runner's initialization occurs. This - * is also typically where a plugin will want to spin up any long-running - * process it requires. - * - * Note that some "plugins" are also built directly into WCT (webserver). - */ -export declare function prepare(context: Context): Promise; -export declare function runTests(context: Context): Promise; -export declare function cancelTests(context: Context): void; diff --git a/packages/wct-runner/typings/web-component-tester/runner/test.d.ts b/packages/wct-runner/typings/web-component-tester/runner/test.d.ts deleted file mode 100644 index ddf80521ae..0000000000 --- a/packages/wct-runner/typings/web-component-tester/runner/test.d.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { Config } from './config'; -import { Context } from './context'; -/** - * Runs a suite of web component tests. - * - * The returned Context (a kind of EventEmitter) fires various events to allow - * you to track the progress of the tests: - * - * Lifecycle Events: - * - * `run-start` - * WCT is ready to begin spinning up browsers. - * - * `browser-init` {browser} {stats} - * WCT is ready to begin spinning up browsers. - * - * `browser-start` {browser} {metadata} {stats} - * The browser has begun running tests. May fire multiple times (i.e. when - * manually refreshing the tests). - * - * `sub-suite-start` {browser} {sharedState} {stats} - * A suite file has begun running. - * - * `test-start` {browser} {test} {stats} - * A test has begun. - * - * `test-end` {browser} {test} {stats} - * A test has ended. - * - * `sub-suite-end` {browser} {sharedState} {stats} - * A suite file has finished running all of its tests. - * - * `browser-end` {browser} {error} {stats} - * The browser has completed, and it shutting down. - * - * `run-end` {error} - * WCT has run all browsers, and is shutting down. - * - * Generic Events: - * - * * log:debug - * * log:info - * * log:warn - * * log:error - * - * @param {!Config|!Context} options The configuration or an already formed - * `Context` object. - */ -export declare function test(options: Config | Context): Promise; diff --git a/packages/wct-runner/typings/web-component-tester/runner/webserver.d.ts b/packages/wct-runner/typings/web-component-tester/runner/webserver.d.ts deleted file mode 100644 index b85cbe7b9a..0000000000 --- a/packages/wct-runner/typings/web-component-tester/runner/webserver.d.ts +++ /dev/null @@ -1,22 +0,0 @@ -/** - * @license - * Copyright (c) 2014 The Polymer Project Authors. All rights reserved. - * This code may only be used under the BSD style license found at - * http://polymer.github.io/LICENSE.txt - * The complete set of authors may be found at - * http://polymer.github.io/AUTHORS.txt - * The complete set of contributors may be found at - * http://polymer.github.io/CONTRIBUTORS.txt - * Code distributed by Google as part of the polymer project is also - * subject to an additional IP rights grant found at - * http://polymer.github.io/PATENTS.txt - */ -import { Context } from './context'; -/** - * The webserver module is a quasi-plugin. This ensures that it is hooked in a - * sane way (for other plugins), and just follows the same flow. - * - * It provides a static HTTP server for serving the desired tests and WCT's - * `browser.js`/`environment.js`. - */ -export declare function webserver(wct: Context): void; diff --git a/packages/webpack-transpiler/CHANGELOG.md b/packages/webpack-transpiler/CHANGELOG.md index ecb645c9c2..ea6cd0740e 100644 --- a/packages/webpack-transpiler/CHANGELOG.md +++ b/packages/webpack-transpiler/CHANGELOG.md @@ -3,6 +3,97 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [4.0.0-beta.10](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.9...v4.0.0-beta.10) (2020-10-05) + +**Note:** Version bump only for package @stryker-mutator/webpack-transpiler + + + + + +# [4.0.0-beta.9](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.8...v4.0.0-beta.9) (2020-09-30) + +**Note:** Version bump only for package @stryker-mutator/webpack-transpiler + + + + + +# [4.0.0-beta.8](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.7...v4.0.0-beta.8) (2020-09-22) + +**Note:** Version bump only for package @stryker-mutator/webpack-transpiler + + + + + +# [4.0.0-beta.7](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.6...v4.0.0-beta.7) (2020-09-17) + +**Note:** Version bump only for package @stryker-mutator/webpack-transpiler + + + + + +# [4.0.0-beta.6](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.5...v4.0.0-beta.6) (2020-09-10) + +**Note:** Version bump only for package @stryker-mutator/webpack-transpiler + + + + + +# [4.0.0-beta.5](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.4...v4.0.0-beta.5) (2020-09-09) + +**Note:** Version bump only for package @stryker-mutator/webpack-transpiler + + + + + +# [4.0.0-beta.4](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.3...v4.0.0-beta.4) (2020-08-29) + +**Note:** Version bump only for package @stryker-mutator/webpack-transpiler + + + + + +# [4.0.0-beta.3](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.2...v4.0.0-beta.3) (2020-08-19) + +**Note:** Version bump only for package @stryker-mutator/webpack-transpiler + + + + + +# [4.0.0-beta.2](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.1...v4.0.0-beta.2) (2020-08-07) + +**Note:** Version bump only for package @stryker-mutator/webpack-transpiler + + + + + +# [4.0.0-beta.1](https://github.com/stryker-mutator/stryker/compare/v4.0.0-beta.0...v4.0.0-beta.1) (2020-07-17) + +**Note:** Version bump only for package @stryker-mutator/webpack-transpiler + + + + + +# [4.0.0-beta.0](https://github.com/stryker-mutator/stryker/compare/v3.3.1...v4.0.0-beta.0) (2020-07-10) + + +### Features + +* **transpiler:** remove `Transpiler` API ([06f668b](https://github.com/stryker-mutator/stryker/commit/06f668bf8660f78b12916b2236f3fd9bf86bf23b)) + + + + + ## [3.3.1](https://github.com/stryker-mutator/stryker/compare/v3.3.0...v3.3.1) (2020-07-04) **Note:** Version bump only for package @stryker-mutator/webpack-transpiler diff --git a/packages/webpack-transpiler/package.json b/packages/webpack-transpiler/package.json index 26be6360c0..323e87815f 100644 --- a/packages/webpack-transpiler/package.json +++ b/packages/webpack-transpiler/package.json @@ -1,13 +1,9 @@ { "name": "@stryker-mutator/webpack-transpiler", - "version": "3.3.1", + "version": "4.0.0-beta.10", "description": "A plugin for Webpack-based projects using Stryker", "main": "src/index.js", - "scripts": { - "test": "nyc --exclude-after-remap=false --check-coverage --reporter=html --report-dir=reports/coverage --lines 85 --functions 84 --branches 65 npm run mocha", - "mocha": "mocha \"test/helpers/**/*.js\" \"test/unit/**/*.js\" && mocha --timeout 20000 \"test/helpers/**/*.js\" \"test/integration/**/*.js\"", - "stryker": "node ../core/bin/stryker run" - }, + "scripts": {}, "repository": { "type": "git", "url": "https://github.com/stryker-mutator/stryker" @@ -18,8 +14,7 @@ "keywords": [ "stryker", "typescript", - "webpack", - "@stryker-mutator/transpiler-plugin" + "webpack" ], "publishConfig": { "access": "public" @@ -33,27 +28,5 @@ "bugs": { "url": "https://github.com/stryker-mutator/stryker/issues" }, - "homepage": "https://github.com/stryker-mutator/stryker/tree/master/packages/webpack-transpiler#readme", - "devDependencies": { - "@stryker-mutator/test-helpers": "^3.3.1", - "@types/node": "^14.0.1", - "@types/webpack": "~4.41.0", - "raw-loader": "~4.0.0", - "webpack": "~4.43.0" - }, - "peerDependencies": { - "@stryker-mutator/core": "^3.0.0", - "webpack": ">=2.0.0" - }, - "dependencies": { - "@stryker-mutator/api": "^3.3.1", - "enhanced-resolve": "~4.1.0", - "memfs": "^3.1.2" - }, - "initStrykerConfig": { - "webpack": { - "configFile": "webpack.config.js" - }, - "coverageAnalysis": "off" - } + "homepage": "https://github.com/stryker-mutator/stryker/tree/master/packages/webpack-transpiler#readme" } diff --git a/packages/webpack-transpiler/schema/webpack-transpiler-options.json b/packages/webpack-transpiler/schema/webpack-transpiler-options.json deleted file mode 100644 index c1561e26eb..0000000000 --- a/packages/webpack-transpiler/schema/webpack-transpiler-options.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema", - "title": "WebpackTranspilerOptions", - "additionalProperties": false, - "type": "object", - "properties": { - "webpack": { - "title": "WebpackOptions", - "description": "Configuration for @stryker-mutator/webpack-transpiler", - "type": "object", - "additionalProperties": false, - "default": {}, - "properties": { - "configFile": { - "description": "Location of your webpack config file", - "type": "string" - }, - "context": { - "description": "The [webpack context](https://webpack.js.org/configuration/entry-context/#context)", - "type": "string" - }, - "silent": { - "description": "Specify to remove the \"ProgressPlugin\" from your webpack config file (making the process silent)", - "type": "boolean", - "default": true - } - } - } - } -} diff --git a/packages/webpack-transpiler/src/WebpackTranspiler.ts b/packages/webpack-transpiler/src/WebpackTranspiler.ts deleted file mode 100644 index ce15d4e7b8..0000000000 --- a/packages/webpack-transpiler/src/WebpackTranspiler.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { File, StrykerOptions } from '@stryker-mutator/api/core'; -import { commonTokens, tokens } from '@stryker-mutator/api/plugin'; -import { Transpiler } from '@stryker-mutator/api/transpile'; - -import { WebpackOptions } from '../src-generated/webpack-transpiler-options'; - -import ConfigLoader from './compiler/ConfigLoader'; -import WebpackCompiler from './compiler/WebpackCompiler'; -import { pluginTokens } from './pluginTokens'; -import { WebpackTranspilerWithStrykerOptions } from './WebpackTranspilerWithStrykerOptions'; - -export default class WebpackTranspiler implements Transpiler { - private readonly config: WebpackOptions; - private webpackCompiler: WebpackCompiler; - - public static inject = tokens(commonTokens.options, commonTokens.produceSourceMaps, pluginTokens.configLoader); - constructor(options: StrykerOptions, produceSourceMaps: boolean, private readonly configLoader: ConfigLoader) { - if (produceSourceMaps) { - throw new Error( - `Invalid \`coverageAnalysis\` "${options.coverageAnalysis}" is not supported by the stryker-webpack-transpiler (yet). It is not able to produce source maps yet. Please set it "coverageAnalysis" to "off".` - ); - } - this.config = { - context: process.cwd(), - ...((options as unknown) as WebpackTranspilerWithStrykerOptions).webpack, - }; - } - - public async transpile(files: readonly File[]): Promise { - if (!this.webpackCompiler) { - // Initialize the webpack compiler with the current directory (process.cwd) - const config = await this.configLoader.load(this.config); - this.webpackCompiler = new WebpackCompiler(config); - } - - this.webpackCompiler.writeFilesToFs(files); - const outputFiles = await this.webpackCompiler.emit(); - return [...files, ...outputFiles]; - } -} diff --git a/packages/webpack-transpiler/src/WebpackTranspilerWithStrykerOptions.ts b/packages/webpack-transpiler/src/WebpackTranspilerWithStrykerOptions.ts deleted file mode 100644 index 64e868ee70..0000000000 --- a/packages/webpack-transpiler/src/WebpackTranspilerWithStrykerOptions.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { StrykerOptions } from '@stryker-mutator/api/core'; - -import { WebpackTranspilerOptions } from '../src-generated/webpack-transpiler-options'; - -export interface WebpackTranspilerWithStrykerOptions extends WebpackTranspilerOptions, StrykerOptions {} diff --git a/packages/webpack-transpiler/src/compiler/ConfigLoader.ts b/packages/webpack-transpiler/src/compiler/ConfigLoader.ts deleted file mode 100644 index e3ae27a692..0000000000 --- a/packages/webpack-transpiler/src/compiler/ConfigLoader.ts +++ /dev/null @@ -1,63 +0,0 @@ -import * as fs from 'fs'; -import * as path from 'path'; - -import { Logger } from '@stryker-mutator/api/logging'; -import { commonTokens, tokens } from '@stryker-mutator/api/plugin'; -import { Configuration } from 'webpack'; - -import { pluginTokens } from '../pluginTokens'; -import { WebpackOptions } from '../../src-generated/webpack-transpiler-options'; - -import { NodeRequireFunction } from './NodeRequireFunction'; - -const PROGRESS_PLUGIN_NAME = 'ProgressPlugin'; - -export default class ConfigLoader { - public static inject = tokens(commonTokens.logger, pluginTokens.require); - constructor(private readonly log: Logger, private readonly requireFn: NodeRequireFunction) {} - - public async load(config: WebpackOptions): Promise { - let webpackConfig: Configuration; - - if (config.configFile) { - webpackConfig = await this.loadWebpackConfigFromProjectRoot(config.configFile); - if (webpackConfig instanceof Function) { - webpackConfig = webpackConfig(); - } - if (config.silent) { - this.configureSilent(webpackConfig); - } - } else { - this.log.debug('Webpack config "%s" not found, trying Webpack 4 zero config', config.configFile); - webpackConfig = { context: config.context }; - } - - return webpackConfig; - } - - private loadWebpackConfigFromProjectRoot(configFileLocation: string) { - const resolvedName = path.resolve(configFileLocation); - - if (!fs.existsSync(resolvedName)) { - throw new Error(`Could not load webpack config at "${resolvedName}", file not found.`); - } - - return this.requireFn(resolvedName); - } - - private configureSilent(webpackConfig: Configuration) { - if (webpackConfig.plugins) { - webpackConfig.plugins = webpackConfig.plugins.filter((plugin) => { - if (plugin.constructor && plugin.constructor.name === PROGRESS_PLUGIN_NAME) { - this.log.debug( - 'Removing webpack plugin "%s" to keep webpack bundling silent. Set `webpack: { silent: false }` in your config file to disable this feature.', - PROGRESS_PLUGIN_NAME - ); - return false; - } else { - return true; - } - }); - } - } -} diff --git a/packages/webpack-transpiler/src/compiler/NodeRequireFunction.ts b/packages/webpack-transpiler/src/compiler/NodeRequireFunction.ts deleted file mode 100644 index aa9eff6637..0000000000 --- a/packages/webpack-transpiler/src/compiler/NodeRequireFunction.ts +++ /dev/null @@ -1 +0,0 @@ -export type NodeRequireFunction = (moduleName: string) => any; diff --git a/packages/webpack-transpiler/src/compiler/Webpack.ts b/packages/webpack-transpiler/src/compiler/Webpack.ts deleted file mode 100644 index dd6b315f99..0000000000 --- a/packages/webpack-transpiler/src/compiler/Webpack.ts +++ /dev/null @@ -1,4 +0,0 @@ -import * as webpack from 'webpack'; - -// Used to mock away webpack during unit-testing -export default webpack; diff --git a/packages/webpack-transpiler/src/compiler/WebpackCompiler.ts b/packages/webpack-transpiler/src/compiler/WebpackCompiler.ts deleted file mode 100644 index 20470aa227..0000000000 --- a/packages/webpack-transpiler/src/compiler/WebpackCompiler.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { File } from '@stryker-mutator/api/core'; -import { Compiler, Configuration } from 'webpack'; - -import InputFileSystem from '../fs/InputFileSystem'; -import OutputFileSystem from '../fs/OutputFileSystem'; - -import webpack from './Webpack'; - -export default class WebpackCompiler { - private readonly _compiler: Compiler; - - constructor(webpackConfig: Configuration, private readonly _inputFS = new InputFileSystem(), private readonly _outputFS = new OutputFileSystem()) { - this._compiler = this.createCompiler(webpackConfig); - } - - private createCompiler(webpackConfig: Configuration): Compiler { - const compiler = webpack(webpackConfig); - // Setting filesystem to provided fs so compilation can be done in memory - (compiler as any).inputFileSystem = this._inputFS; - compiler.outputFileSystem = this._outputFS; - (compiler as any).resolvers.normal.fileSystem = this._inputFS; - (compiler as any).resolvers.context.fileSystem = this._inputFS; - - return compiler; - } - - public writeFilesToFs(files: readonly File[]): void { - files.forEach((file) => this.writeToFs(file)); - } - - private writeToFs(file: File): void { - this._inputFS.writeFileSync(file.name, file.content); - } - - public emit(): Promise { - return this.compile().then(() => { - const outputFiles = this._outputFS.collectFiles(); - this._outputFS.purge(); - return outputFiles; - }); - } - - private compile(): Promise { - return new Promise((resolve, reject) => { - this._compiler.run((err, stats) => { - if (err) { - reject(err); - } else if (stats.hasErrors()) { - reject(Error(stats.toString('errors-only'))); - } else { - resolve(stats); - } - }); - }); - } -} diff --git a/packages/webpack-transpiler/src/fs/InputFileSystem.ts b/packages/webpack-transpiler/src/fs/InputFileSystem.ts deleted file mode 100644 index ee01bcb70d..0000000000 --- a/packages/webpack-transpiler/src/fs/InputFileSystem.ts +++ /dev/null @@ -1,68 +0,0 @@ -import * as fs from 'fs'; -import { dirname } from 'path'; - -import { CachedInputFileSystem, NodeJsInputFileSystem, Stats } from 'enhanced-resolve'; -import { IFs } from 'memfs'; - -import { Callback, webpack } from '../types'; - -import memFS from './memory-fs'; - -// Cache duration is same as webpack has -// => https://github.com/webpack/webpack/blob/efc576c8b744e7a015ab26f1f46932ba3ca7d4f1/lib/node/NodeEnvironmentPlugin.js#L14 -const CACHE_DURATION = 60000; - -export default class InputFileSystem extends CachedInputFileSystem implements webpack.InputFileSystem { - constructor(innerFS = new NodeJsInputFileSystem(), private readonly memoryFS: IFs = memFS) { - super(innerFS, CACHE_DURATION); - } - - public writeFileSync(name: string, content: string | Buffer) { - this.memoryFS.mkdirpSync(dirname(name)); - if (content === '') { - // The in-memory fs doesn't like empty strings. - content = ' '; - } - this.memoryFS.writeFileSync(name, content); - } - - public stat(path: string, callback: Callback): void { - this.memoryFS.stat(path, (err?: Error | null, stats?: any) => { - if (err) { - super.stat(path, callback as Callback); - } else { - callback(err, stats); - } - }); - } - - public readFile(...args: any[]) { - const originalCallback = args[args.length - 1]; - const newCallback = (error: NodeJS.ErrnoException, content: any) => { - if (error) { - super.readFile.apply(this, args); - } else { - originalCallback(error, content); - } - }; - const memoryFSArgs = args.slice(0, args.length - 1); - memoryFSArgs.push(newCallback); - this.memoryFS.readFile.apply(this.memoryFS, memoryFSArgs); - } - - public readFileSync(path: string, encoding?: string) { - try { - return this.memoryFS.readFileSync(path, encoding); - } catch (err) { - return super.readFileSync(path, encoding); - } - } - - public statSync(path: string): Stats { - try { - return this.memoryFS.statSync(path); - } catch (err) { - return super.statSync(path); - } - } -} diff --git a/packages/webpack-transpiler/src/fs/OutputFileSystem.ts b/packages/webpack-transpiler/src/fs/OutputFileSystem.ts deleted file mode 100644 index 238d58b065..0000000000 --- a/packages/webpack-transpiler/src/fs/OutputFileSystem.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { PathLike } from 'fs'; -import * as path from 'path'; - -import { File } from '@stryker-mutator/api/core'; - -import { Callback, EmptyCallback, webpack } from '../types'; - -export default class OutputFileSystem implements webpack.OutputFileSystem { - private _files: { - [name: string]: string | Buffer; - }; - - constructor() { - this.purge(); - } - - public purge() { - this._files = Object.create(null); - } - - public collectFiles(): File[] { - return Object.keys(this._files).map((fileName) => new File(fileName, this._files[fileName])); - } - - public mkdirp(_dir: string, opts: any, cb?: Callback): void { - const callback: Callback = cb || opts; - callback(null); - } - - public rmdir(_name: PathLike, callback: EmptyCallback): void { - callback(); - } - - public mkdir(_name: PathLike, callback: EmptyCallback): void { - callback(); - } - - public unlink(name: PathLike, callback: EmptyCallback): void { - const fullName = path.resolve(name.toString()); - delete this._files[fullName]; - callback(); - } - - public writeFile(name: PathLike | number, data: any, options: any, cb?: EmptyCallback): void { - const callback: EmptyCallback = cb || options; - this._files[path.resolve(name.toString())] = data; - callback(); - } - - public join(...paths: string[]): string { - return path.join(...paths); - } -} diff --git a/packages/webpack-transpiler/src/fs/memory-fs.ts b/packages/webpack-transpiler/src/fs/memory-fs.ts deleted file mode 100644 index 4ca6ea69f0..0000000000 --- a/packages/webpack-transpiler/src/fs/memory-fs.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { fs } from 'memfs'; - -/** - * Wrapper file for testability - */ -export default fs; diff --git a/packages/webpack-transpiler/src/index.ts b/packages/webpack-transpiler/src/index.ts index 8b70690a63..2bb347929f 100644 --- a/packages/webpack-transpiler/src/index.ts +++ b/packages/webpack-transpiler/src/index.ts @@ -1,16 +1,3 @@ -import { commonTokens, declareFactoryPlugin, Injector, PluginKind, tokens, TranspilerPluginContext } from '@stryker-mutator/api/plugin'; - -import * as strykerValidationSchema from '../schema/webpack-transpiler-options.json'; - -import ConfigLoader from './compiler/ConfigLoader'; -import { pluginTokens } from './pluginTokens'; -import WebpackTranspiler from './WebpackTranspiler'; - -export const strykerPlugins = [declareFactoryPlugin(PluginKind.Transpiler, 'webpack', webpackTranspilerFactory)]; - -function webpackTranspilerFactory(injector: Injector) { - return injector.provideValue(pluginTokens.require, require).provideClass(pluginTokens.configLoader, ConfigLoader).injectClass(WebpackTranspiler); -} -webpackTranspilerFactory.inject = tokens(commonTokens.injector); - -export { strykerValidationSchema }; +console.warn( + 'Transpiler plugins are no longer supported since Stryker 4.0. Please use `"buildCommand": "webpack --config webpack.conf.js"` instead. You can remove "@stryker-mutator/webpack-transpiler" from your devDependencies.' +); diff --git a/packages/webpack-transpiler/src/pluginTokens.ts b/packages/webpack-transpiler/src/pluginTokens.ts deleted file mode 100644 index f466b23720..0000000000 --- a/packages/webpack-transpiler/src/pluginTokens.ts +++ /dev/null @@ -1,8 +0,0 @@ -function stringLiteral(literal: T) { - return literal; -} - -export const pluginTokens = Object.freeze({ - configLoader: stringLiteral('configLoader'), - require: stringLiteral('require'), -}); diff --git a/packages/webpack-transpiler/src/types.ts b/packages/webpack-transpiler/src/types.ts deleted file mode 100644 index 4e247195d1..0000000000 --- a/packages/webpack-transpiler/src/types.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { Stats } from 'enhanced-resolve'; - -export type EmptyCallback = (err?: NodeJS.ErrnoException | null) => void; - -export type Callback = (err: NodeJS.ErrnoException | null | undefined, arg?: T) => void; - -export declare namespace webpack { - /** - * Grabbed from https://github.com/webpack/enhanced-resolve/blob/4a9488d1f0954351cbbee80fbf395688f853ef1f/lib/NodeJsInputFileSystem.js - */ - interface InputFileSystem { - stat(path: string, callback: Callback): void; - readdir(path: string, callback: Callback): void; - - readFile(path: string, options: { encoding: string; flag?: string } | string, callback: Callback): void; - readFile(path: string, options: { encoding?: null; flag?: string } | undefined | null, callback: Callback): void; - readFile( - path: string, - options: { encoding?: string | null; flag?: string } | string | undefined | null, - callback: Callback - ): void; - readFile(path: string, callback: Callback): void; - - readlink(path: string, callback: Callback): void; - - statSync(path: string): Stats; - readdirSync(path: string): string[]; - - readFileSync(path: string, encoding?: string): string | Buffer; - readlinkSync(path: string): string; - } - - /** - * Grabbed from https://github.com/webpack/webpack/blob/d18607395713ba08b2f562356375726030bbdd19/lib/node/NodeOutputFileSystem.js - */ - interface OutputFileSystem { - mkdirp(dir: string, opts: any, callback: Callback): void; - mkdirp(dir: string, callback: Callback): void; - rmdir(name: string, callback: EmptyCallback): void; - mkdir(name: string, callback: EmptyCallback): void; - unlink(name: string, callback: EmptyCallback): void; - writeFile(path: string, data: any, callback: EmptyCallback): void; - writeFile( - path: string, - data: any, - options: { encoding?: string | null; mode?: number | string; flag?: string } | string | undefined | null, - callback: EmptyCallback - ): void; - join(...paths: string[]): string; - } -} diff --git a/packages/webpack-transpiler/test/helpers/initChai.ts b/packages/webpack-transpiler/test/helpers/initChai.ts deleted file mode 100644 index 514154da42..0000000000 --- a/packages/webpack-transpiler/test/helpers/initChai.ts +++ /dev/null @@ -1,6 +0,0 @@ -import * as chai from 'chai'; -import * as chaiAsPromised from 'chai-as-promised'; -import * as sinonChai from 'sinon-chai'; - -chai.use(sinonChai); -chai.use(chaiAsPromised); diff --git a/packages/webpack-transpiler/test/helpers/initSinon.ts b/packages/webpack-transpiler/test/helpers/initSinon.ts deleted file mode 100644 index 96cb3f7e59..0000000000 --- a/packages/webpack-transpiler/test/helpers/initSinon.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { testInjector } from '@stryker-mutator/test-helpers'; -import * as sinon from 'sinon'; - -afterEach(() => { - sinon.restore(); - testInjector.reset(); -}); diff --git a/packages/webpack-transpiler/test/helpers/initSourceMaps.ts b/packages/webpack-transpiler/test/helpers/initSourceMaps.ts deleted file mode 100644 index fcfbfda16c..0000000000 --- a/packages/webpack-transpiler/test/helpers/initSourceMaps.ts +++ /dev/null @@ -1 +0,0 @@ -import 'source-map-support/register'; diff --git a/packages/webpack-transpiler/test/helpers/mockInterfaces.ts b/packages/webpack-transpiler/test/helpers/mockInterfaces.ts deleted file mode 100644 index 9032425015..0000000000 --- a/packages/webpack-transpiler/test/helpers/mockInterfaces.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Stats } from 'webpack'; - -export interface WebpackCompilerMock { - run(callback: (err: Error, stats: Stats) => void): void; - inputFileSystem: { fileSystem: any }; - outputFileSystem: { fileSystem: any }; - resolvers: { normal: { fileSystem: any }; context: { fileSystem: any } }; -} diff --git a/packages/webpack-transpiler/test/helpers/producers.ts b/packages/webpack-transpiler/test/helpers/producers.ts deleted file mode 100644 index d505f538af..0000000000 --- a/packages/webpack-transpiler/test/helpers/producers.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { File } from '@stryker-mutator/api/core'; -import * as sinon from 'sinon'; -import { Configuration } from 'webpack'; - -import { WebpackOptions } from '../../src-generated/webpack-transpiler-options'; - -import { WebpackCompilerMock } from './mockInterfaces'; - -export type Mock = { [K in keyof T]: sinon.SinonStub }; - -export type Constructor = new (...args: any[]) => T; - -export function createMockInstance(type: Constructor) { - return sinon.createStubInstance(type) as Mock; -} - -export function createFakeWebpackConfig(): Configuration { - return { - entry: ['index.js'], - output: { - filename: 'bundle.js', - path: '/out', - }, - }; -} - -export function createTextFile(name: string): File { - return new File(name, 'c = a^2 + b^2'); -} - -function createFactory(defaultFn: () => T): (overrides?: Partial) => T { - return (overrides) => Object.assign(defaultFn(), overrides); -} - -export const createWebpackOptions = createFactory(() => ({ - context: '/path/to/project/root', - silent: true, -})); - -export function createWebpackMock(): WebpackCompilerMock { - return { - inputFileSystem: { fileSystem: {} }, - outputFileSystem: { fileSystem: {} }, - resolvers: { - context: { fileSystem: {} }, - normal: { fileSystem: {} }, - }, - run: () => {}, - }; -} diff --git a/packages/webpack-transpiler/test/integration/inputFS.it.spec.ts b/packages/webpack-transpiler/test/integration/inputFS.it.spec.ts deleted file mode 100644 index b8ed125596..0000000000 --- a/packages/webpack-transpiler/test/integration/inputFS.it.spec.ts +++ /dev/null @@ -1,46 +0,0 @@ -import * as path from 'path'; - -import { expect } from 'chai'; - -import InputFileSystem from '../../src/fs/InputFileSystem'; - -function testResourcePath(...pathSegments: string[]) { - return path.resolve(__dirname, '..', '..', 'testResources', ...pathSegments); -} - -describe('InputFileSystem integration', () => { - let sut: InputFileSystem; - - beforeEach(() => { - sut = new InputFileSystem(); - }); - - it('should be able to list all physical directories', (done) => { - const tempFile = testResourcePath('inputFileSystem', 'dir1', 'tempFile'); - sut.writeFileSync(tempFile, 'some content'); - sut.readdir(testResourcePath('inputFileSystem'), (err, dirs) => { - if (err) { - done(err); - } else if (!dirs) { - done('no dirs'); - } else { - // eslint-disable-next-line @typescript-eslint/require-array-sort-compare - dirs.sort(); - expect(dirs).deep.eq(['dir1', 'dir2', 'dir3']); - done(); - } - }); - - it('should be able to stat a dir', (done) => { - testResourcePath('inputFileSystem', 'dir1', 'tempFile'); - sut.stat(testResourcePath('inputFileSystem', 'dir2'), (err, stats: any) => { - if (err) { - done(err); - } else { - expect(stats.isDirectory()).ok; - done(); - } - }); - }); - }); -}); diff --git a/packages/webpack-transpiler/test/integration/transpiler.it.spec.ts b/packages/webpack-transpiler/test/integration/transpiler.it.spec.ts deleted file mode 100644 index 429a575668..0000000000 --- a/packages/webpack-transpiler/test/integration/transpiler.it.spec.ts +++ /dev/null @@ -1,63 +0,0 @@ -import * as fs from 'fs'; -import * as path from 'path'; - -import { File } from '@stryker-mutator/api/core'; -import { commonTokens } from '@stryker-mutator/api/plugin'; -import { testInjector } from '@stryker-mutator/test-helpers'; -import { expect } from 'chai'; - -import ConfigLoader from '../../src/compiler/ConfigLoader'; -import { pluginTokens } from '../../src/pluginTokens'; -import WebpackTranspiler from '../../src/WebpackTranspiler'; -import { WebpackTranspilerWithStrykerOptions } from '../../src/WebpackTranspilerWithStrykerOptions'; - -describe('Webpack transpiler', () => { - let options: WebpackTranspilerWithStrykerOptions; - - beforeEach(() => { - options = (testInjector.options as unknown) as WebpackTranspilerWithStrykerOptions; - options.webpack = { - configFile: 'webpack.conf.js', - silent: true, - }; - }); - - it('should be able to transpile the "gettingStarted" sample', async () => { - options.webpack.configFile = path.join(getProjectRoot('gettingStarted'), 'webpack.config.js'); - const sut = createSut(); - const files = readFiles(); - - const transpiledFiles = await sut.transpile(files); - const bundleFile = transpiledFiles.filter((file) => file.name.includes('my-first-webpack.bundle.js'))[0]; - expect(transpiledFiles).lengthOf(3); // input + output - expect(bundleFile.textContent).include('Hello world!'); // input + output - }); - - it('should be able to transpile "zeroConfig" sample without a Webpack config file', async () => { - options.webpack.context = getProjectRoot('zeroConfig'); - delete options.webpack.configFile; - const sut = createSut(); - const files = readFiles(); - - const transpiledFiles = await sut.transpile(files); - expect(transpiledFiles).lengthOf(3); // input + output - }); -}); - -function createSut() { - return testInjector.injector - .provideValue(commonTokens.produceSourceMaps, false) - .provideValue(pluginTokens.require, require) - .provideClass(pluginTokens.configLoader, ConfigLoader) - .injectClass(WebpackTranspiler); -} - -function getProjectRoot(testResourceProjectName: string) { - return path.resolve(__dirname, '..', '..', 'testResources', testResourceProjectName); -} - -function readFiles(): File[] { - const dir = path.resolve(__dirname, '..', '..', 'testResources', 'gettingStarted', 'src'); - const files = fs.readdirSync(dir); - return files.map((fileName) => new File(path.resolve(dir, fileName), fs.readFileSync(path.resolve(dir, fileName)))); -} diff --git a/packages/webpack-transpiler/test/unit/WebpackTranspiler.spec.ts b/packages/webpack-transpiler/test/unit/WebpackTranspiler.spec.ts deleted file mode 100644 index fbf8ae455f..0000000000 --- a/packages/webpack-transpiler/test/unit/WebpackTranspiler.spec.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { File } from '@stryker-mutator/api/core'; -import { commonTokens } from '@stryker-mutator/api/plugin'; -import { factory, testInjector } from '@stryker-mutator/test-helpers'; -import { expect } from 'chai'; -import * as sinon from 'sinon'; -import { Configuration } from 'webpack'; - -import ConfigLoader from '../../src/compiler/ConfigLoader'; -import WebpackCompiler, * as webpackCompilerModule from '../../src/compiler/WebpackCompiler'; -import WebpackTranspiler from '../../src/WebpackTranspiler'; -import { createMockInstance, createTextFile, Mock, createWebpackOptions } from '../helpers/producers'; - -describe('WebpackTranspiler', () => { - let webpackTranspiler: WebpackTranspiler; - - // Stubs - let configLoaderStub: Mock; - let webpackCompilerStub: Mock; - - const exampleBundleFile: File = createTextFile('bundle.js'); - let webpackConfig: Configuration; - - beforeEach(() => { - webpackCompilerStub = createMockInstance(WebpackCompiler); - webpackCompilerStub.emit.returns([exampleBundleFile]); - - webpackConfig = { entry: './main.js' }; - configLoaderStub = createMockInstance(ConfigLoader); - configLoaderStub.load.returns(webpackConfig); - - sinon.stub(webpackCompilerModule, 'default').returns(webpackCompilerStub); - - testInjector.options.webpack = createWebpackOptions({ context: '/path/to/project/root' }); - }); - - it('should only create the compiler once', async () => { - webpackTranspiler = createSut(); - await webpackTranspiler.transpile([]); - await webpackTranspiler.transpile([]); - - expect(webpackCompilerModule.default).calledOnce; - expect(webpackCompilerModule.default).calledWithNew; - expect(configLoaderStub.load).calledOnce; - expect(configLoaderStub.load).calledWith(createWebpackOptions()); - }); - - it('should throw an error if `produceSourceMaps` is `true`', () => { - testInjector.options.coverageAnalysis = 'perTest'; - expect( - () => new WebpackTranspiler(factory.strykerOptions({ coverageAnalysis: 'perTest' }), true, (configLoaderStub as unknown) as ConfigLoader) - ).throws( - 'Invalid `coverageAnalysis` "perTest" is not supported by the stryker-webpack-transpiler (yet). It is not able to produce source maps yet. Please set it "coverageAnalysis" to "off"' - ); - }); - - it('should call the webpackCompiler.writeFilesToFs function with the given files', async () => { - webpackTranspiler = createSut(); - const files = [createTextFile('main.js'), createTextFile('sum.js'), createTextFile('divide.js')]; - - await webpackTranspiler.transpile(files); - - expect(webpackCompilerStub.writeFilesToFs).calledWith(files); - }); - - it('should call the webpackCompiler.emit function to get the new bundled files', async () => { - webpackTranspiler = createSut(); - await webpackTranspiler.transpile([]); - - expect(webpackCompilerStub.emit).called; - expect(webpackCompilerStub.emit).calledOnce; - }); - - it('should return all files (input and output) on success', async () => { - webpackTranspiler = createSut(); - const input = new File('input.js', ''); - const transpiledFiles = await webpackTranspiler.transpile([input]); - expect(transpiledFiles).to.deep.equal([input, exampleBundleFile]); - }); - - it('should return a error result when an error occurred', async () => { - webpackTranspiler = createSut(); - const fakeError = new Error('compiler could not compile input files'); - webpackCompilerStub.emit.throwsException(fakeError); - expect(webpackTranspiler.transpile([])).rejectedWith(fakeError); - }); - - function createSut() { - return testInjector.injector - .provideValue(commonTokens.produceSourceMaps, false) - .provideValue('configLoader', (configLoaderStub as unknown) as ConfigLoader) - .injectClass(WebpackTranspiler); - } -}); diff --git a/packages/webpack-transpiler/test/unit/compiler/ConfigLoader.spec.ts b/packages/webpack-transpiler/test/unit/compiler/ConfigLoader.spec.ts deleted file mode 100644 index 506f665d55..0000000000 --- a/packages/webpack-transpiler/test/unit/compiler/ConfigLoader.spec.ts +++ /dev/null @@ -1,131 +0,0 @@ -import * as fs from 'fs'; -import * as path from 'path'; - -import { testInjector } from '@stryker-mutator/test-helpers'; -import { expect } from 'chai'; -import * as sinon from 'sinon'; -import { Configuration, Plugin } from 'webpack'; - -import ConfigLoader from '../../../src/compiler/ConfigLoader'; -import { pluginTokens } from '../../../src/pluginTokens'; -import { createWebpackOptions } from '../../helpers/producers'; - -class FooPlugin implements Plugin { - public foo = true; - public apply() {} -} -class ProgressPlugin implements Plugin { - public apply() {} -} -class BarPlugin implements Plugin { - public bar = true; - public apply() {} -} - -describe('ConfigLoader', () => { - let sut: ConfigLoader; - let requireStub: sinon.SinonStub; - let existsSyncStub: sinon.SinonStub; - - beforeEach(() => { - requireStub = sinon.stub(); - existsSyncStub = sinon.stub(fs, 'existsSync'); - - sut = testInjector.injector.provideValue(pluginTokens.require, requireStub).injectClass(ConfigLoader); - }); - - it('should load webpack config from given location', async () => { - requireStub.returns('resolved'); - existsSyncStub.returns(true); - - const result = await sut.load(createWebpackOptions({ configFile: 'webpack.foo.config.js' })); - expect(result).eq('resolved'); - expect(requireStub).calledWith(path.resolve('webpack.foo.config.js')); - }); - - it('should call function if webpack config file exports a function', async () => { - const configFunctionStub = sinon.stub(); - configFunctionStub.returns('webpackconfig'); - requireStub.returns(configFunctionStub); - existsSyncStub.returns(true); - - const result = await sut.load(createWebpackOptions({ configFile: 'webpack.foo.config.js' })); - expect(result).eq('webpackconfig'); - expect(requireStub).calledWith(path.resolve('webpack.foo.config.js')); - expect(configFunctionStub).called; - }); - - it('should remove "ProgressPlugin" if silent is `true`', async () => { - // Arrange - const bazPlugin = { baz: true, apply() {} }; - const webpackConfig: Configuration = { - plugins: [new FooPlugin(), new ProgressPlugin(), new BarPlugin(), bazPlugin], - }; - - requireStub.returns(webpackConfig); - existsSyncStub.returns(true); - - // Act - const result = await sut.load(createWebpackOptions({ configFile: 'webpack.config.js', silent: true })); - - // Assert - expect(result.plugins).to.be.an('array').that.does.not.deep.include(new ProgressPlugin()); - expect(result.plugins).to.be.an('array').that.deep.equals([new FooPlugin(), new BarPlugin(), bazPlugin]); - expect(testInjector.logger.debug).calledWith( - 'Removing webpack plugin "%s" to keep webpack bundling silent. Set `webpack: { silent: false }` in your config file to disable this feature.', - 'ProgressPlugin' - ); - }); - - it('should not remove "ProgressPlugin" if silent is `false`', async () => { - const webpackConfig: Configuration = { - plugins: [new ProgressPlugin(), new BarPlugin()], - }; - - requireStub.returns(webpackConfig); - existsSyncStub.returns(true); - - const result = await sut.load(createWebpackOptions({ configFile: 'webpack.config.js', silent: false })); - expect(result.plugins).to.be.an('array').that.does.deep.include(new ProgressPlugin()); - }); - - it('should return an object with the context property pointing to the projectRoot when webpack.config.js does not exist', async () => { - const contextPath: string = '/path/to/project/root'; - - existsSyncStub.returns(false); - - const result = await sut.load(createWebpackOptions({ context: contextPath })); - - expect(result).to.deep.equal({ context: contextPath }); - }); - - it('should report an error when a non-existent webpack config file location is provided by the user', async () => { - const configFile = 'non-existent.webpack.config.js'; - - existsSyncStub.returns(false); - - return expect(sut.load(createWebpackOptions({ configFile }))).rejectedWith( - `Could not load webpack config at "${path.resolve(configFile)}", file not found.` - ); - }); - - it("should log a debug message when the Webpack configuration is not found and it's trying webpack 4 zero config instead", async () => { - const contextPath: string = '/path/to/project/root'; - - existsSyncStub.returns(false); - - await sut.load(createWebpackOptions({ context: contextPath })); - - expect(testInjector.logger.debug).calledWith('Webpack config "%s" not found, trying Webpack 4 zero config'); - }); - - it('should be able to load a webpack configuration asynchonously via a promise', async () => { - requireStub.returns(Promise.resolve('resolved')); - existsSyncStub.returns(true); - - const result = await sut.load(createWebpackOptions({ configFile: 'webpack.foo.config.js' })); - - expect(result).eq('resolved'); - expect(requireStub).calledWith(path.resolve('webpack.foo.config.js')); - }); -}); diff --git a/packages/webpack-transpiler/test/unit/compiler/WebpackCompiler.spec.ts b/packages/webpack-transpiler/test/unit/compiler/WebpackCompiler.spec.ts deleted file mode 100644 index 32907a3268..0000000000 --- a/packages/webpack-transpiler/test/unit/compiler/WebpackCompiler.spec.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { File } from '@stryker-mutator/api/core'; -import { expect } from 'chai'; -import * as sinon from 'sinon'; -import { Configuration } from 'webpack'; - -import * as webpack from '../../../src/compiler/Webpack'; -import WebpackCompiler from '../../../src/compiler/WebpackCompiler'; -import InputFileSystem from '../../../src/fs/InputFileSystem'; -import OutputFileSystem from '../../../src/fs/OutputFileSystem'; -import { WebpackCompilerMock } from '../../helpers/mockInterfaces'; -import { createFakeWebpackConfig, createMockInstance, createTextFile, createWebpackMock, Mock } from '../../helpers/producers'; - -describe('WebpackCompiler', () => { - let sut: WebpackCompiler; - let inputFileSystemMock: Mock; - let outputFileSystemMock: Mock; - let webpackCompilerMock: WebpackCompilerMock; - let fakeWebpackConfig: Configuration; - - beforeEach(() => { - inputFileSystemMock = createMockInstance(InputFileSystem); - outputFileSystemMock = createMockInstance(OutputFileSystem); - webpackCompilerMock = createWebpackMock(); - fakeWebpackConfig = createFakeWebpackConfig(); - sinon.stub(webpack, 'default').returns(webpackCompilerMock); - }); - - describe('writeFilesToFs', () => { - beforeEach(() => { - sut = new WebpackCompiler(fakeWebpackConfig, inputFileSystemMock as any, outputFileSystemMock as any); - }); - - it('should call the writeFile function on the inputFS with the given file', () => { - const textFiles = createFakeTextFileArray(); - sut.writeFilesToFs(textFiles); - - textFiles.forEach((textFile) => { - expect(inputFileSystemMock.writeFileSync).calledWith(textFile.name); - }); - }); - }); - - describe('emit', () => { - let webpackRunStub: sinon.SinonStub; - - beforeEach(() => { - sut = new WebpackCompiler(fakeWebpackConfig, inputFileSystemMock as any, outputFileSystemMock as any); - webpackRunStub = sinon.stub(webpackCompilerMock, 'run').callsArgWith(0, null, { hasErrors: () => false }); - }); - - it('should call the run function on the webpack compiler', async () => { - outputFileSystemMock.collectFiles.returns([]); - await sut.emit(); - expect(webpackRunStub).calledOnce; - }); - - it('should collect files from the outputFS', async () => { - const expectedFiles = [{ name: 'foobar' }]; - outputFileSystemMock.collectFiles.returns(expectedFiles); - const actualResult = await sut.emit(); - - expect(actualResult).eq(expectedFiles); - expect(outputFileSystemMock.collectFiles).calledWith(); - }); - - it('should return an error when the webpack compiler fails to compile', async () => { - const fakeError: string = 'fakeError'; - webpackRunStub.callsArgWith(0, new Error(fakeError)); - - try { - await sut.emit(); - - expect.fail('Function should throw an error!'); - } catch (err) { - expect(err.name).to.equal('Error'); - expect(err.message).to.equal(fakeError); - } - }); - - it('should return a string representation of the error when the compiler has errors', async () => { - const fakeError: string = 'fakeError'; - webpackRunStub.callsArgWith(0, null, { - hasErrors: () => true, - toString: () => fakeError, - }); - - try { - await sut.emit(); - expect.fail(null, null, 'Function should throw an error!'); - } catch (err) { - expect(err.name).to.equal('Error'); - expect(err.message).to.equal(fakeError); - } - }); - }); - - function createFakeTextFileArray(): File[] { - return [ - createTextFile('path/to/awesome/directory/file1'), - createTextFile('path/to/awesome/directory/file2'), - createTextFile('path/to/awesome/directory/file3'), - createTextFile('path/to/awesome/directory/file4'), - ]; - } -}); diff --git a/packages/webpack-transpiler/test/unit/fs/InputFileSystem.spec.ts b/packages/webpack-transpiler/test/unit/fs/InputFileSystem.spec.ts deleted file mode 100644 index 6af3afb513..0000000000 --- a/packages/webpack-transpiler/test/unit/fs/InputFileSystem.spec.ts +++ /dev/null @@ -1,141 +0,0 @@ -import { expect } from 'chai'; -import { CachedInputFileSystem } from 'enhanced-resolve'; -import * as sinon from 'sinon'; -import { IFs } from 'memfs'; - -import InputFileSystem from '../../../src/fs/InputFileSystem'; -import memoryFS from '../../../src/fs/memory-fs'; -import { createMockInstance, Mock } from '../../helpers/producers'; - -describe('InputFileSystem', () => { - let sut: InputFileSystem; - let memoryFSMock: sinon.SinonStubbedInstance; - let innerFSMock: Mock; - - beforeEach(() => { - memoryFSMock = sinon.stub(memoryFS); - innerFSMock = createMockInstance(CachedInputFileSystem); - sut = new InputFileSystem(innerFSMock, (memoryFSMock as unknown) as IFs); - }); - - describe('writeFileSync', () => { - it('should forward to memory fs', () => { - sut.writeFileSync('path', 'content'); - expect(memoryFSMock.writeFileSync).calledWith('path', 'content'); - }); - it('should replace empty string content', () => { - sut.writeFileSync('path', ''); - expect(memoryFSMock.writeFileSync).calledWith('path', ' '); - }); - it('should mkdirp the directory', () => { - sut.writeFileSync('path/to/file1.js', ''); - expect(memoryFSMock.mkdirpSync).calledWith('path/to'); - }); - }); - - describe('stat', () => { - it('should forward to memory fs', (done) => { - memoryFSMock.stat.callsArgWith(1, undefined, 'foobar'); - sut.stat('arg1', (_error, value) => { - expect(value).eq('foobar'); - expect(innerFSMock.stat).not.called; - done(); - }); - }); - - it('should forward to fs if memory FS resulted in an error', (done) => { - memoryFSMock.stat.callsArgOnWith(1, sut, new Error('foobar')); - innerFSMock.stat.callsArgWith(1, null, 'the stats'); - sut.stat('foobar', (error, stats) => { - expect(error).not.ok; - expect(stats).eq('the stats'); - done(); - }); - }); - - it('should forward fs errors if file did not exist', (done) => { - // Arrange - const expectedError = new Error('File not exists'); - innerFSMock.stat.callsArgWith(1, expectedError); - memoryFSMock.stat.callsArgOnWith(1, sut, new Error('foobar')); - - // Act - sut.stat('foo/bar/not/exits', (err) => { - // Assert - expect(err).eq(expectedError); - done(); - }); - }); - }); - - describe('readFile', () => { - it('should forward readFile to memory FS', (done) => { - memoryFSMock.readFile.callsArgOnWith(2, sut, undefined, 'foobar'); - sut.readFile('path', {}, (_error: Error, value: string) => { - expect(value).eq('foobar'); - expect(memoryFSMock.readFile).calledWith('path'); - expect(innerFSMock.readFile).not.called; - done(); - }); - }); - - it('should forward to real FS if memory-fs gave an error', (done) => { - memoryFSMock.readFile.callsArgOnWith(1, sut, new Error('foobar')); - innerFSMock.readFile.callsArgWith(1, undefined, 'the content'); - sut.readFile('foobar', (_error: Error, content: string) => { - expect(content).eq('the content'); - expect(innerFSMock.readFile).calledWith('foobar'); - done(); - }); - }); - - it('should forward fs errors if file did not exist', (done) => { - // Arrange - const expectedError = new Error('File not exists'); - innerFSMock.readFile.callsArgWith(1, expectedError); - memoryFSMock.readFile.callsArgOnWith(1, sut, new Error('foobar')); - - // Act - sut.readFile('foo/bar/not/exits', (error: Error) => { - // Assert - expect(error).eq(expectedError); - done(); - }); - }); - }); - - describe('statSync', () => { - it('should forward to memory FS', () => { - memoryFSMock.statSync.returns('foobar stats'); - const actual = sut.statSync('path'); - expect(actual).eq('foobar stats'); - expect(memoryFSMock.statSync).calledWith('path'); - expect(innerFSMock.statSync).not.called; - }); - it('should forward to real FS if memory-fs gave an error', () => { - memoryFSMock.statSync.throws(new Error('foobar')); - innerFSMock.statSync.returns('foobar stats'); - const actual = sut.statSync('path'); - expect(actual).eq('foobar stats'); - expect(innerFSMock.statSync).calledWith('path'); - }); - }); - - describe('readFileSync', () => { - it('should forward to memory FS', () => { - memoryFSMock.readFileSync.returns('foobar file'); - const actual = sut.readFileSync('path', 'utf8'); - expect(actual).eq('foobar file'); - expect(memoryFSMock.readFileSync).calledWith('path', 'utf8'); - expect(innerFSMock.readFileSync).not.called; - }); - it('should forward to real FS if memory-fs gave an error', () => { - const error = new Error('foobar'); - memoryFSMock.readFileSync.throws(error); - innerFSMock.readFileSync.returns('foobar file'); - const actual = sut.readFileSync('path'); - expect(actual).eq('foobar file'); - expect(innerFSMock.readFileSync).calledWith('path'); - }); - }); -}); diff --git a/packages/webpack-transpiler/test/unit/fs/OutputFileSystem.spec.ts b/packages/webpack-transpiler/test/unit/fs/OutputFileSystem.spec.ts deleted file mode 100644 index 345231c290..0000000000 --- a/packages/webpack-transpiler/test/unit/fs/OutputFileSystem.spec.ts +++ /dev/null @@ -1,56 +0,0 @@ -import * as path from 'path'; - -import { File } from '@stryker-mutator/api/core'; -import { expect } from 'chai'; - -import OutputFileSystem from '../../../src/fs/OutputFileSystem'; - -describe('OutputFileSystem', () => { - let sut: OutputFileSystem; - - beforeEach(() => { - sut = new OutputFileSystem(); - }); - - actions('mkdir', 'rmdir').forEach((action) => { - it(`should pass through "${action}" without doing anything`, (done) => { - sut[action]('dir', done); - }); - }); - - it('should pass through "mkdirp" without doing anything', (done) => { - sut.mkdirp('dir', done); - }); - - it('should delete files when "unlink" is called', (done) => { - sut.writeFile('file1', 'data', () => { - expect(sut.collectFiles()).lengthOf(1); - sut.unlink('file1', () => { - expect(sut.collectFiles()).lengthOf(0); - done(); - }); - }); - }); - - describe('when "collectFiles"', () => { - it('should collect a css file', () => { - const fileName = 'file.css'; - const fileContent = 'body: { background: blue }'; - sut.writeFile(fileName, fileContent, () => {}); - const expectedFile = new File(path.resolve(fileName), fileContent); - expect(sut.collectFiles()).deep.eq([expectedFile]); - }); - - it('should collect files', () => { - const binContent = Buffer.from(''); - sut.writeFile('bin1.ico', binContent, () => {}); - sut.writeFile('file1.js', 'data', () => {}); - const expectedFiles = [new File(path.resolve('bin1.ico'), binContent), new File(path.resolve('file1.js'), 'data')]; - expect(sut.collectFiles()).deep.eq(expectedFiles); - }); - }); - - function actions(...actions: Array<'mkdir' | 'rmdir'>) { - return actions; - } -}); diff --git a/packages/webpack-transpiler/testResources/.gitignore b/packages/webpack-transpiler/testResources/.gitignore deleted file mode 100644 index 53c37a1660..0000000000 --- a/packages/webpack-transpiler/testResources/.gitignore +++ /dev/null @@ -1 +0,0 @@ -dist \ No newline at end of file diff --git a/packages/webpack-transpiler/testResources/gettingStarted/src/hello-world.txt b/packages/webpack-transpiler/testResources/gettingStarted/src/hello-world.txt deleted file mode 100644 index 6769dd60bd..0000000000 --- a/packages/webpack-transpiler/testResources/gettingStarted/src/hello-world.txt +++ /dev/null @@ -1 +0,0 @@ -Hello world! \ No newline at end of file diff --git a/packages/webpack-transpiler/testResources/gettingStarted/src/main.js b/packages/webpack-transpiler/testResources/gettingStarted/src/main.js deleted file mode 100644 index 5354f4435f..0000000000 --- a/packages/webpack-transpiler/testResources/gettingStarted/src/main.js +++ /dev/null @@ -1,3 +0,0 @@ -const helloWorld = require('./hello-world.txt'); - -console.log(helloWorld); \ No newline at end of file diff --git a/packages/webpack-transpiler/testResources/gettingStarted/webpack.config.js b/packages/webpack-transpiler/testResources/gettingStarted/webpack.config.js deleted file mode 100644 index a0224ec382..0000000000 --- a/packages/webpack-transpiler/testResources/gettingStarted/webpack.config.js +++ /dev/null @@ -1,14 +0,0 @@ -const path = require('path'); -module.exports = { - entry: './src/main.js', - context: __dirname, - output: { - path: path.resolve(__dirname, 'dist'), - filename: 'my-first-webpack.bundle.js' - }, - module: { - rules: [ - { test: /\.txt$/, use: 'raw-loader' } - ] - } -}; \ No newline at end of file diff --git a/packages/webpack-transpiler/testResources/zeroConfig/package.json b/packages/webpack-transpiler/testResources/zeroConfig/package.json deleted file mode 100644 index b3f83d5486..0000000000 --- a/packages/webpack-transpiler/testResources/zeroConfig/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "webpackZeroConfig", - "version": "1.0.0", - "description": "A webpack 4 project with zero configuration", - "main": "index.js", - "scripts": { - "build": "webpack --mode development" - }, - "keywords": [ - "webpack 4" - ], - "author": "Sander Koenders", - "license": "MIT" -} diff --git a/packages/webpack-transpiler/testResources/zeroConfig/src/index.js b/packages/webpack-transpiler/testResources/zeroConfig/src/index.js deleted file mode 100644 index 184aace4b1..0000000000 --- a/packages/webpack-transpiler/testResources/zeroConfig/src/index.js +++ /dev/null @@ -1,9 +0,0 @@ -const sum = require('./lib/sum'); -const divide = require('./lib/divide'); -const square = require('./lib/square'); - -[1,2,3,4].map(number => { - console.log(sum(number)); - console.log(divide(number)); - console.log(square(number)); -}); \ No newline at end of file diff --git a/packages/webpack-transpiler/testResources/zeroConfig/src/lib/divide.js b/packages/webpack-transpiler/testResources/zeroConfig/src/lib/divide.js deleted file mode 100644 index 70384b01f9..0000000000 --- a/packages/webpack-transpiler/testResources/zeroConfig/src/lib/divide.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = (number) => { - return number / number; -}; \ No newline at end of file diff --git a/packages/webpack-transpiler/testResources/zeroConfig/src/lib/square.js b/packages/webpack-transpiler/testResources/zeroConfig/src/lib/square.js deleted file mode 100644 index 0a3f688b24..0000000000 --- a/packages/webpack-transpiler/testResources/zeroConfig/src/lib/square.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = (number) => { - return number * number; -}; \ No newline at end of file diff --git a/packages/webpack-transpiler/testResources/zeroConfig/src/lib/sum.js b/packages/webpack-transpiler/testResources/zeroConfig/src/lib/sum.js deleted file mode 100644 index 93b6362808..0000000000 --- a/packages/webpack-transpiler/testResources/zeroConfig/src/lib/sum.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = (number) => { - return number + number; -}; \ No newline at end of file diff --git a/packages/webpack-transpiler/tsconfig.stryker.json b/packages/webpack-transpiler/tsconfig.stryker.json deleted file mode 100644 index ae424d3c8f..0000000000 --- a/packages/webpack-transpiler/tsconfig.stryker.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "./tsconfig.test.json", - "include": [ - "src", - "src-generated", - "schema/*.json", - "test", - "typings" - ], -} diff --git a/packages/webpack-transpiler/typings/enhanced-resolve.d.ts b/packages/webpack-transpiler/typings/enhanced-resolve.d.ts deleted file mode 100644 index 99c64e963f..0000000000 --- a/packages/webpack-transpiler/typings/enhanced-resolve.d.ts +++ /dev/null @@ -1,85 +0,0 @@ -declare module 'enhanced-resolve' { - export interface Stats { - isFile(): boolean; - isDirectory(): boolean; - isBlockDevice(): boolean; - isCharacterDevice(): boolean; - isSymbolicLink(): boolean; - isFIFO(): boolean; - isSocket(): boolean; - } - - type Callback = (err: NodeJS.ErrnoException | null | undefined, arg?: T) => void; - - export interface AbstractInputFileSystem { - purge?(what?: string | string[]): void; - readdir(path: string, callback: (err: NodeJS.ErrnoException, files: string[]) => void): void; - readdirSync(path: string): string[]; - readFile( - filename: string, - encoding: string | { encoding: string; flag?: string }, - callback: (err: NodeJS.ErrnoException, data: string) => void - ): void; - readFile( - filename: string, - options: { - flag?: string; - }, - callback: (err: NodeJS.ErrnoException, data: Buffer) => void - ): void; - readFile(filename: string, callback: (err: NodeJS.ErrnoException, data: Buffer) => void): void; - readFileSync(filename: string): Buffer; - readJson?(path: string, callback: (err: NodeJS.ErrnoException, data: any) => void): void; - readJsonSync?(path: string): any; - readlink(path: string, callback: (err: NodeJS.ErrnoException, linkString: string) => void): void; - readlinkSync(path: string): string; - stat(path: string, callback: (err: NodeJS.ErrnoException, stats: Stats) => void): void; - statSync(path: string): Stats; - } - - export class NodeJsInputFileSystem implements AbstractInputFileSystem { - public readdir(path: string, callback: (err: NodeJS.ErrnoException, files: string[]) => void): void; - public readFile( - filename: string, - encoding: string | { encoding: string; flag?: string | undefined }, - callback: (err: NodeJS.ErrnoException, data: string) => void - ): void; - public readFile(filename: string, options: { flag?: string | undefined }, callback: (err: NodeJS.ErrnoException, data: Buffer) => void): void; - public readFile(filename: string, callback: (err: NodeJS.ErrnoException, data: Buffer) => void): void; - public readFile(filename: any, options: any, callback?: any): void; - public readlink(path: string, callback: (err: NodeJS.ErrnoException, linkString: string) => void): void; - public stat(path: string, callback: (err: NodeJS.ErrnoException, stats: Stats) => void): void; - public statSync(path: string): Stats; - public readlinkSync(path: string): string; - public readFileSync(filename: string): Buffer; - public readdirSync(path: string): string[]; - } - - export class CachedInputFileSystem { - public fileSystem: AbstractInputFileSystem; - - constructor(fileSystem: AbstractInputFileSystem, duration: number); - - public stat(path: string, callback: Callback): void; - - public readdir(path: string, callback: Callback): void; - - public readFile(path: string, callback: Callback): void; - - public readJson(path: string, callback: Callback): void; - - public readlink(path: string, callback: Callback): void; - - public statSync(path: string | Buffer): Stats; - - public readdirSync(path: string): string[]; - - public readFileSync(filename: string, options?: string): string | Buffer; - - public readlinkSync(path: string | Buffer): string; - - public readJsonSync(path: string): any; - - public purge(what?: string | string[]): void; - } -} diff --git a/perf/config/express/package.json b/perf/config/express/package.json index 12add5dd9b..586e5d1b4a 100644 --- a/perf/config/express/package.json +++ b/perf/config/express/package.json @@ -1,9 +1,8 @@ { "localDependencies": { "@stryker-mutator/core": "../../../packages/core", + "@stryker-mutator/instrumenter": "../../../packages/instrumenter", "@stryker-mutator/api": "../../../packages/api", - "@stryker-mutator/javascript-mutator": "../../../packages/javascript-mutator", - "@stryker-mutator/mocha-framework": "../../../packages/mocha-framework", "@stryker-mutator/mocha-runner": "../../../packages/mocha-runner", "@stryker-mutator/util": "../../../packages/util" } diff --git a/perf/config/express/stryker.conf.json b/perf/config/express/stryker.conf.json index 1d1060605a..bbc46e84a7 100644 --- a/perf/config/express/stryker.conf.json +++ b/perf/config/express/stryker.conf.json @@ -1,7 +1,5 @@ { "$schema": "../../../packages/core/schema/stryker-schema.json", "testRunner": "mocha", - "testFramework": "mocha", - "coverageAnalysis": "perTest", - "mutator": "javascript" + "coverageAnalysis": "perTest" } diff --git a/perf/package-lock.json b/perf/package-lock.json index e69298f9bf..69c741f083 100644 --- a/perf/package-lock.json +++ b/perf/package-lock.json @@ -5,9 +5,9 @@ "requires": true, "dependencies": { "arg": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.0.tgz", - "integrity": "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true }, "buffer-from": { @@ -17,15 +17,15 @@ "dev": true }, "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true }, "make-error": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz", - "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==", + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, "source-map": { @@ -35,9 +35,9 @@ "dev": true }, "source-map-support": { - "version": "0.5.10", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.10.tgz", - "integrity": "sha512-YfQ3tQFTK/yzlGJuX8pTwa4tifQj4QS2Mj7UegOu8jAz59MqIiMGPXxQhVQiIMNzayuUSF/jEuVnfFF5JqybmQ==", + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -45,22 +45,22 @@ } }, "ts-node": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.0.2.tgz", - "integrity": "sha512-MosTrinKmaAcWgO8tqMjMJB22h+sp3Rd1i4fdoWY4mhBDekOwIAKI/bzmRi7IcbCmjquccYg2gcF6NBkLgr0Tw==", + "version": "8.10.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.10.2.tgz", + "integrity": "sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==", "dev": true, "requires": { "arg": "^4.1.0", - "diff": "^3.1.0", + "diff": "^4.0.1", "make-error": "^1.1.1", - "source-map-support": "^0.5.6", - "yn": "^3.0.0" + "source-map-support": "^0.5.17", + "yn": "3.1.1" } }, "yn": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.0.0.tgz", - "integrity": "sha512-+Wo/p5VRfxUgBUGy2j/6KX2mj9AYJWOHuhMjMcbBFc3y54o9/4buK1ksBvuiK01C3kby8DH9lSmJdSxw+4G/2Q==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true } } diff --git a/perf/package.json b/perf/package.json index 49bd3d2d3e..9515e2cb03 100644 --- a/perf/package.json +++ b/perf/package.json @@ -3,11 +3,11 @@ "version": "0.0.0", "private": true, "devDependencies": { - "ts-node": "^8.0.2" + "ts-node": "~8.10.2" }, "scripts": { "merge-config": "ts-node -p tasks/merge-config.ts", - "postinstall": "npm run merge-config && node ../node_modules/lerna/cli.js bootstrap && npm run install-local-dependencies", + "postinstall": "npm run merge-config && node ../node_modules/lerna/cli.js bootstrap --no-ci && npm run install-local-dependencies", "install-local-dependencies": "ts-node -p tasks/install-local-dependencies.ts", "test": "ts-node tasks/run-perf-tests.ts" } diff --git a/perf/test/angular-cli/angular.json b/perf/test/angular-cli/angular.json index e8abeec4a3..1441418b77 100644 --- a/perf/test/angular-cli/angular.json +++ b/perf/test/angular-cli/angular.json @@ -10,13 +10,14 @@ "prefix": "ksw", "schematics": { "@schematics/angular:component": { - "styleext": "scss" + "style": "scss" } }, "architect": { "build": { "builder": "@angular-devkit/build-angular:browser", "options": { + "aot": true, "outputPath": "dist/FEWebwinkel", "index": "src/index.html", "main": "src/main.ts", @@ -34,6 +35,12 @@ }, "configurations": { "production": { + "budgets": [ + { + "type": "anyComponentStyle", + "maximumWarning": "6kb" + } + ], "fileReplacements": [ { "replace": "src/environments/environment.ts", diff --git a/perf/test/angular-cli/package-lock.json b/perf/test/angular-cli/package-lock.json index f6559c9eec..591965c1bf 100644 --- a/perf/test/angular-cli/package-lock.json +++ b/perf/test/angular-cli/package-lock.json @@ -5,19 +5,19 @@ "requires": true, "dependencies": { "@angular-devkit/architect": { - "version": "0.803.18", - "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.803.18.tgz", - "integrity": "sha512-/oNutcuUduXH/4nxHSDRTYK3VGP0PkVUniPdo0yjpg8c2dbfoNkt1ILIV82LPaC8sDwjuXGLx0EH70ETtcnBwg==", + "version": "0.901.12", + "resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.901.12.tgz", + "integrity": "sha512-gLlsxa+3JPV1m1gRvRMujOs4xKox6I5BkYmOD1zfu+dB6y3LuBAvHfXA6FaTDVOMBrmSlWnE4PmOmB6xd7wxMA==", "dev": true, "requires": { - "@angular-devkit/core": "8.3.18", - "rxjs": "6.4.0" + "@angular-devkit/core": "9.1.12", + "rxjs": "6.5.4" }, "dependencies": { "rxjs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", - "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz", + "integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==", "dev": true, "requires": { "tslib": "^1.9.0" @@ -26,91 +26,178 @@ } }, "@angular-devkit/build-angular": { - "version": "0.803.18", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-0.803.18.tgz", - "integrity": "sha512-0Os4tbX/9t+X+PR/0bLmskm9/f5c8bSnrnV0N6jad9lf97RJfxvWC/NSx4xLgOoYuLnzdx2Fe1rSDjU/PFUUuw==", - "dev": true, - "requires": { - "@angular-devkit/architect": "0.803.18", - "@angular-devkit/build-optimizer": "0.803.18", - "@angular-devkit/build-webpack": "0.803.18", - "@angular-devkit/core": "8.3.18", - "@babel/core": "7.5.5", - "@babel/preset-env": "7.5.5", - "@ngtools/webpack": "8.3.18", - "ajv": "6.10.2", - "autoprefixer": "9.6.1", - "browserslist": "4.6.6", - "cacache": "12.0.2", - "caniuse-lite": "1.0.30000989", + "version": "0.901.12", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-angular/-/build-angular-0.901.12.tgz", + "integrity": "sha512-enK+u1Lg1a/KWUs3r8Tc7Igduu5ph9fgziV8bjQeVrswrqFb0m0eEhxe/zV8rvE92H3NBZp5Z+uzOYIcg4eirw==", + "dev": true, + "requires": { + "@angular-devkit/architect": "0.901.12", + "@angular-devkit/build-optimizer": "0.901.12", + "@angular-devkit/build-webpack": "0.901.12", + "@angular-devkit/core": "9.1.12", + "@babel/core": "7.9.0", + "@babel/generator": "7.9.3", + "@babel/preset-env": "7.9.0", + "@babel/template": "7.8.6", + "@jsdevtools/coverage-istanbul-loader": "3.0.3", + "@ngtools/webpack": "9.1.12", + "ajv": "6.12.3", + "autoprefixer": "9.7.4", + "babel-loader": "8.0.6", + "browserslist": "^4.9.1", + "cacache": "15.0.0", + "caniuse-lite": "^1.0.30001032", "circular-dependency-plugin": "5.2.0", - "clean-css": "4.2.1", - "copy-webpack-plugin": "5.0.4", - "core-js": "3.2.1", - "file-loader": "4.2.0", - "find-cache-dir": "3.0.0", - "glob": "7.1.4", - "istanbul-instrumenter-loader": "3.0.1", - "jest-worker": "24.9.0", + "copy-webpack-plugin": "6.0.3", + "core-js": "3.6.4", + "css-loader": "3.5.1", + "cssnano": "4.1.10", + "file-loader": "6.0.0", + "find-cache-dir": "3.3.1", + "glob": "7.1.6", + "jest-worker": "25.1.0", "karma-source-map-support": "1.4.0", - "less": "3.9.0", + "less": "3.11.3", "less-loader": "5.0.0", - "license-webpack-plugin": "2.1.2", - "loader-utils": "1.2.3", - "mini-css-extract-plugin": "0.8.0", + "license-webpack-plugin": "2.1.4", + "loader-utils": "2.0.0", + "mini-css-extract-plugin": "0.9.0", "minimatch": "3.0.4", - "open": "6.4.0", + "open": "7.0.3", "parse5": "4.0.0", - "postcss": "7.0.17", + "postcss": "7.0.27", "postcss-import": "12.0.1", "postcss-loader": "3.0.0", - "raw-loader": "3.1.0", - "regenerator-runtime": "0.13.3", - "rxjs": "6.4.0", - "sass": "1.22.9", - "sass-loader": "7.2.0", - "semver": "6.3.0", + "raw-loader": "4.0.0", + "regenerator-runtime": "0.13.5", + "rimraf": "3.0.2", + "rollup": "2.1.0", + "rxjs": "6.5.4", + "sass": "1.26.3", + "sass-loader": "8.0.2", + "semver": "7.1.3", "source-map": "0.7.3", "source-map-loader": "0.2.4", - "source-map-support": "0.5.13", "speed-measure-webpack-plugin": "1.3.1", - "style-loader": "1.0.0", - "stylus": "0.54.5", + "style-loader": "1.1.3", + "stylus": "0.54.7", "stylus-loader": "3.0.2", - "terser": "4.3.9", - "terser-webpack-plugin": "1.4.1", - "tree-kill": "1.2.1", - "webpack": "4.39.2", + "terser": "4.6.10", + "terser-webpack-plugin": "3.0.3", + "tree-kill": "1.2.2", + "webpack": "4.42.0", "webpack-dev-middleware": "3.7.2", - "webpack-dev-server": "3.9.0", - "webpack-merge": "4.2.1", + "webpack-dev-server": "3.11.0", + "webpack-merge": "4.2.2", "webpack-sources": "1.4.3", - "webpack-subresource-integrity": "1.1.0-rc.6", - "worker-plugin": "3.2.0" + "webpack-subresource-integrity": "1.4.0", + "worker-plugin": "4.0.3" }, "dependencies": { + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/generator": { + "version": "7.9.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.3.tgz", + "integrity": "sha512-RpxM252EYsz9qLUIq6F7YJyK1sv0wWDBFuztfDGWaQKzHjqDHysxSiRUpA/X9jmfqo+WzkAVKFaUily5h+gDCQ==", + "dev": true, + "requires": { + "@babel/types": "^7.9.0", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", + "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", + "dev": true + }, + "@babel/template": { + "version": "7.8.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz", + "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/parser": "^7.8.6", + "@babel/types": "^7.8.6" + } + }, + "@babel/types": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + }, + "dependencies": { + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + } + } + }, "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz", + "integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==", "dev": true, "requires": { - "fast-deep-equal": "^2.0.1", + "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "core-js": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.2.1.tgz", - "integrity": "sha512-Qa5XSVefSVPRxy2XfUC13WbvqkxhkwB3ve+pgCQveNgYzbM/UxZeu1dcOX/xr4UmfUd+muuvsaxilQzCyUurMw==", + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.6.4.tgz", + "integrity": "sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "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", @@ -121,59 +208,74 @@ "path-is-absolute": "^1.0.0" } }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, "rxjs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", - "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz", + "integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==", "dev": true, "requires": { "tslib": "^1.9.0" } }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.1.3.tgz", + "integrity": "sha512-ekM0zfiA9SCBlsKa2X1hxyxiI4L3B6EbVJkkdgQXnSEEaHlGdvyodMruTiulSRWMMB4NeIuYNMC9rTKTz97GxA==", "dev": true } } }, "@angular-devkit/build-optimizer": { - "version": "0.803.18", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.803.18.tgz", - "integrity": "sha512-RmXQK+90GQyvIoaQ+qkIb7guXmx+zNlykliq7p+QFNXzDOohPsjuvGs/oY+NvAngqnVKM9tXZp2oSWXH881PPg==", + "version": "0.901.12", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-optimizer/-/build-optimizer-0.901.12.tgz", + "integrity": "sha512-XuXA+6y9QkIAwSVZhWmne4r7qugUUWaXobgRefbn9heiRlY8/7XkZmmvbSrxc1fgQfQar52W9fAa19fAIeNvnw==", "dev": true, "requires": { - "loader-utils": "1.2.3", + "loader-utils": "2.0.0", "source-map": "0.7.3", - "tslib": "1.10.0", - "typescript": "3.5.3", + "tslib": "1.11.1", + "typescript": "3.6.5", "webpack-sources": "1.4.3" }, "dependencies": { + "tslib": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz", + "integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==", + "dev": true + }, "typescript": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.5.3.tgz", - "integrity": "sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==", + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.5.tgz", + "integrity": "sha512-BEjlc0Z06ORZKbtcxGrIvvwYs5hAnuo6TKdNFL55frVDlB+na3z5bsLhFaIxmT+dPWgBIjMo6aNnTOgHHmHgiQ==", "dev": true } } }, "@angular-devkit/build-webpack": { - "version": "0.803.18", - "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.803.18.tgz", - "integrity": "sha512-utjfPQAp/4IHwmJg/6lsGBdAJczGiCjWpBiF5Q3JweyQ+NUlLFx4ikyUu+rhcZWof7Gk/84toVvlWGbPMz+Ufw==", + "version": "0.901.12", + "resolved": "https://registry.npmjs.org/@angular-devkit/build-webpack/-/build-webpack-0.901.12.tgz", + "integrity": "sha512-zrhZV2LhQ4uFl9at9i2jiedIu932HsaFN4OMMsTFlV+6CZxtEUBI85hhnPa5KQtIYQr2OMQSQf/FyhnBGs0riQ==", "dev": true, "requires": { - "@angular-devkit/architect": "0.803.18", - "@angular-devkit/core": "8.3.18", - "rxjs": "6.4.0" + "@angular-devkit/architect": "0.901.12", + "@angular-devkit/core": "9.1.12", + "rxjs": "6.5.4" }, "dependencies": { "rxjs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", - "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz", + "integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==", "dev": true, "requires": { "tslib": "^1.9.0" @@ -182,34 +284,46 @@ } }, "@angular-devkit/core": { - "version": "8.3.18", - "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-8.3.18.tgz", - "integrity": "sha512-SPlQmBlrcaKZeE9srvuFElcen9iOled4lkD3M4cGwe56u6YoJ71oTAtmGiw9nofTtW0PghGVq8WdDQG5BRqX8Q==", + "version": "9.1.12", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-9.1.12.tgz", + "integrity": "sha512-D/GnBeSlmdgGn7EhuE32HuPuRAjvUuxi7Q6WywBI8PSsXKAGnrypghBwMATNnOA24//CgbW2533Y9VWHaeXdeA==", "dev": true, "requires": { - "ajv": "6.10.2", - "fast-json-stable-stringify": "2.0.0", - "magic-string": "0.25.3", - "rxjs": "6.4.0", + "ajv": "6.12.3", + "fast-json-stable-stringify": "2.1.0", + "magic-string": "0.25.7", + "rxjs": "6.5.4", "source-map": "0.7.3" }, "dependencies": { "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "version": "6.12.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.3.tgz", + "integrity": "sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==", "dev": true, "requires": { - "fast-deep-equal": "^2.0.1", + "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, "rxjs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", - "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz", + "integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==", "dev": true, "requires": { "tslib": "^1.9.0" @@ -218,19 +332,20 @@ } }, "@angular-devkit/schematics": { - "version": "8.3.18", - "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-8.3.18.tgz", - "integrity": "sha512-J9sf/6cSUx2kdXppo/69uZ1gBeM5fcXfnP7MCJCVnsk09QCD9Kr+Xeh8h4WEmLtne7XzI9dcCttHQ5WDNuRulA==", + "version": "9.1.12", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-9.1.12.tgz", + "integrity": "sha512-+GYnUzmIy1/QpYitCC8mI7jcrViGHTtOKvvDPEFjU2nggjNEQaMmsHcdIsjrqggEc23ZZyebNAIewT8CMkJyrQ==", "dev": true, "requires": { - "@angular-devkit/core": "8.3.18", - "rxjs": "6.4.0" + "@angular-devkit/core": "9.1.12", + "ora": "4.0.3", + "rxjs": "6.5.4" }, "dependencies": { "rxjs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", - "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz", + "integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==", "dev": true, "requires": { "tslib": "^1.9.0" @@ -239,39 +354,36 @@ } }, "@angular/animations": { - "version": "8.2.13", - "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-8.2.13.tgz", - "integrity": "sha512-ZE4UZsQ6HDW1ZIj9tL45PVosCcG4Ke7ihV7eWCE1VgLZKDDxTOPbLf1UeEiszUYptMLGH3eGMNBKo85mOlkH8w==", - "requires": { - "tslib": "^1.9.0" - } + "version": "9.1.12", + "resolved": "https://registry.npmjs.org/@angular/animations/-/animations-9.1.12.tgz", + "integrity": "sha512-tphpf9QHnOPoL2Jl7KpR+R5aHNW3oifLEmRUTajJYJGvo1uzdUDE82+V9OGOinxJsYseCth9gYJhN24aYTB9NA==" }, "@angular/cli": { - "version": "8.3.18", - "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-8.3.18.tgz", - "integrity": "sha512-IWiGlAmVPkl/xWCrki3N45uqdYcjUvtWw9bRM53FF1EKLLbjue6DAVD1HktqgqjTyck0P7QkOXWRilT8rXKcEQ==", + "version": "9.1.12", + "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-9.1.12.tgz", + "integrity": "sha512-B0yOab5WbD84bIRRUKOPAJnpka8Qj+CRt61wJfjsqpd/Rj7pD/3ubmdCNoBH7Xa6UlOb0tdYqRPsqfK7uEL0sw==", "dev": true, "requires": { - "@angular-devkit/architect": "0.803.18", - "@angular-devkit/core": "8.3.18", - "@angular-devkit/schematics": "8.3.18", - "@schematics/angular": "8.3.18", - "@schematics/update": "0.803.18", + "@angular-devkit/architect": "0.901.12", + "@angular-devkit/core": "9.1.12", + "@angular-devkit/schematics": "9.1.12", + "@schematics/angular": "9.1.12", + "@schematics/update": "0.901.12", "@yarnpkg/lockfile": "1.1.0", "ansi-colors": "4.1.1", - "debug": "^4.1.1", + "debug": "4.1.1", "ini": "1.3.5", - "inquirer": "6.5.1", - "npm-package-arg": "6.1.0", - "npm-pick-manifest": "3.0.2", - "open": "6.4.0", - "pacote": "9.5.5", + "inquirer": "7.1.0", + "npm-package-arg": "8.0.1", + "npm-pick-manifest": "6.0.0", + "open": "7.0.3", + "pacote": "9.5.12", "read-package-tree": "5.3.1", - "rimraf": "3.0.0", - "semver": "6.3.0", + "rimraf": "3.0.2", + "semver": "7.1.3", "symbol-observable": "1.2.0", - "universal-analytics": "^0.4.20", - "uuid": "^3.3.2" + "universal-analytics": "0.4.20", + "uuid": "7.0.2" }, "dependencies": { "ansi-colors": { @@ -281,811 +393,223 @@ "dev": true }, "rimraf": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.0.tgz", - "integrity": "sha512-NDGVxTsjqfunkds7CqsOiEnxln4Bo7Nddl3XhS4pXg5OzwkLqJ971ZVAAnB+DDLnF76N+VnDEiBHaVV8I06SUg==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "dev": true, "requires": { "glob": "^7.1.3" } }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.1.3.tgz", + "integrity": "sha512-ekM0zfiA9SCBlsKa2X1hxyxiI4L3B6EbVJkkdgQXnSEEaHlGdvyodMruTiulSRWMMB4NeIuYNMC9rTKTz97GxA==", + "dev": true + }, + "uuid": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.2.tgz", + "integrity": "sha512-vy9V/+pKG+5ZTYKf+VcphF5Oc6EFiu3W8Nv3P3zIh0EqVI80ZxOzuPfe9EHjkFNvf8+xuTHVeei4Drydlx4zjw==", "dev": true } } }, "@angular/common": { - "version": "8.2.13", - "resolved": "https://registry.npmjs.org/@angular/common/-/common-8.2.13.tgz", - "integrity": "sha512-I9cTcjUi88L+Mb/a/ZzUrdDcn3YgFFK9LubxaPjAfr6+G7IZ//MY5HuvG8Y41yKprXVVvQCbQ1yQD+GGRSCkaA==", - "requires": { - "tslib": "^1.9.0" - } + "version": "9.1.12", + "resolved": "https://registry.npmjs.org/@angular/common/-/common-9.1.12.tgz", + "integrity": "sha512-XSIqkbM6VV1yixF9zuzeE5eqN1VsiXS517K2VU0XgCRSAzhVhLOeKsdYjeLf7PdSu/HgW/Tr81H+isi9A9I0YA==" }, "@angular/compiler": { - "version": "8.2.13", - "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-8.2.13.tgz", - "integrity": "sha512-u2NWCvEn4SjbMvn2PG6sYcf+rR5u3aYMv3/mNQ9k+2UmCIu3yJrcuCzebjo5SdlDVqKD2vzbyMZnr8VB9OcceQ==", - "requires": { - "tslib": "^1.9.0" - } + "version": "9.1.12", + "resolved": "https://registry.npmjs.org/@angular/compiler/-/compiler-9.1.12.tgz", + "integrity": "sha512-suefk0OFkaJpUUKnV+phbL4T8fmVGHvzkereY5eqybQlumOez8NPL1PJcygAylh/E6OIAYm8SWookYwM6ZY9dg==" }, "@angular/compiler-cli": { - "version": "8.2.13", - "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-8.2.13.tgz", - "integrity": "sha512-ryW2Kozx/oHJrtdeIhgZ24RIU7Za3YIOHS9EMCQ8xMo+ZlSI+t2zOlLAXzK4PVWEjuTtQlKbT0KqilgU0QsHJg==", + "version": "9.1.12", + "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-9.1.12.tgz", + "integrity": "sha512-bbqJ+fbY+aQejSYuHUjE1qYJCXkZBM5Hru9eN7m/j376u83MQ5jWdC290uYx+ipsXcPTa/YRZ44jpL+5cCzIrg==", "dev": true, "requires": { "canonical-path": "1.0.0", - "chokidar": "^2.1.1", + "chokidar": "^3.0.0", "convert-source-map": "^1.5.1", "dependency-graph": "^0.7.2", + "fs-extra": "4.0.2", "magic-string": "^0.25.0", "minimist": "^1.2.0", "reflect-metadata": "^0.1.2", + "semver": "^6.3.0", "source-map": "^0.6.1", - "tslib": "^1.9.0", - "yargs": "13.1.0" + "sourcemap-codec": "^1.4.8", + "yargs": "15.3.0" }, "dependencies": { "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", "dev": true, "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" } }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" } }, - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "fs-extra": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.2.tgz", + "integrity": "sha1-+RcExT0bRh+JNFKwwwfZmXZHq2s=", "dev": true, "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" } }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "p-locate": "^4.1.0" } }, - "fill-range": { + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "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 + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" } }, - "fsevents": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", - "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "dev": true, - "optional": true, "requires": { - "nan": "^2.12.1", - "node-pre-gyp": "^0.12.0" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.3", - "bundled": true, - "dev": true, - "optional": 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" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true, - "optional": true - }, - "minipass": { - "version": "2.3.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.2.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.3.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^4.1.0", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.12.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.4.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.6.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.7.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.4", - "minizlib": "^1.1.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "yallist": { - "version": "3.0.3", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "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": { - "is-buffer": "^1.1.5" - } - }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - } - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "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 - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^5.0.0" } }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dev": true, "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" } }, "yargs": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.1.0.tgz", - "integrity": "sha512-1UhJbXfzHiPqkfXNHYhiz79qM/kZqjTE8yGlEjZa85Q+3+OwcV6NRkV7XOV1W2Eom2bzILeUn55pQYffjVOLAg==", + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.0.tgz", + "integrity": "sha512-g/QCnmjgOl1YJjGsnUg2SatC7NUYEiLXJqxNOQU9qSpjzGtGXda9b+OKccr1kLTy8BN9yqEyqfq5lxlwdc13TA==", "dev": true, "requires": { - "cliui": "^4.0.0", - "find-up": "^3.0.0", + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", "get-caller-file": "^2.0.1", - "os-locale": "^3.1.0", "require-directory": "^2.1.1", "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", - "string-width": "^3.0.0", + "string-width": "^4.2.0", "which-module": "^2.0.0", "y18n": "^4.0.0", - "yargs-parser": "^13.0.0" + "yargs-parser": "^18.1.0" } }, "yargs-parser": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", - "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "dev": true, "requires": { "camelcase": "^5.0.0", @@ -1095,50 +619,35 @@ } }, "@angular/core": { - "version": "8.2.13", - "resolved": "https://registry.npmjs.org/@angular/core/-/core-8.2.13.tgz", - "integrity": "sha512-W8HN0lUQV4Sq85l17nhRIXeIfcw1ZdpgGm6to98pl0y9l/1srfzWfTnofuwCJC7gedt5AMrYJGUaNiDbByosFw==", - "requires": { - "tslib": "^1.9.0" - } + "version": "9.1.12", + "resolved": "https://registry.npmjs.org/@angular/core/-/core-9.1.12.tgz", + "integrity": "sha512-WVA/eh3fzjx0apOzkKot4YRRUsGkHj50zFQWrAOMgivGaj1YVrvhf+m3hpglj5fn/BkLiFDl8RT0wAE8z9X+gQ==" }, "@angular/forms": { - "version": "8.2.13", - "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-8.2.13.tgz", - "integrity": "sha512-l7lHD4kbWK70KY0Xp4IpSa106ZzSgPMwRYMFKd9qhYaJ7v0Y7Shh7Z/ZDCOP730maj9WULnpy5X4eeozWXgvgg==", - "requires": { - "tslib": "^1.9.0" - } + "version": "9.1.12", + "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-9.1.12.tgz", + "integrity": "sha512-LhjnZlC4WEsEsAJfOZLte+Lks3WBAFVeRv2lzoQNFVr/IMzBNDVfjEaaSqKF1cei3cjY39Df2nYDMJM7HfqbJA==" }, "@angular/language-service": { - "version": "8.2.13", - "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-8.2.13.tgz", - "integrity": "sha512-uVkqC5oxul6Jqyxzy0o4DN1TpmcmUWIi7WnDBu+aJVQFp/kqxmkNuJQvugdouxlIYdHC/SwLeVnBIplRjGH5cw==", + "version": "9.1.12", + "resolved": "https://registry.npmjs.org/@angular/language-service/-/language-service-9.1.12.tgz", + "integrity": "sha512-0qfIAn5fP5lD+JW6il5HBHGS89rv+idRv5aooDkHqBhuBo4V2VuB1wNy5eP49GZbHKMW1xPAzv1MqeMdk+zwQA==", "dev": true }, "@angular/platform-browser": { - "version": "8.2.13", - "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-8.2.13.tgz", - "integrity": "sha512-1lPbeLQIbbafjq9ul3IA8s2fMJ/EXeMJ74ouTolVXoPPur9ZPRLX9FqBAO1K4QzkAWhRlyf6qIC+mDZfJILwZw==", - "requires": { - "tslib": "^1.9.0" - } + "version": "9.1.12", + "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-9.1.12.tgz", + "integrity": "sha512-rPa/hJcLfdId6bYB0b6pFUo3QIgjZlvUlmtKMGdrLNLYR8XQxPa2Y/UdN/5YeZ12htGw6GXrX9U8U7nTbUSpkw==" }, "@angular/platform-browser-dynamic": { - "version": "8.2.13", - "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-8.2.13.tgz", - "integrity": "sha512-KP5psUKujAO8jZKHi6LRC+N7hE/epiGOhYZxdher1sCi81sYoZmqrEWkVZ4VKhov/4aC409CocDXcF7nmHV8tg==", - "requires": { - "tslib": "^1.9.0" - } + "version": "9.1.12", + "resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-9.1.12.tgz", + "integrity": "sha512-NmwUZaQeMnA6f+vP9Fp9P+qjL72H8dKlxLS76ujlKHVf75pP5oahWS8wfl7KXel1tKW3FQWMMffmKf5/NHRiSw==" }, "@angular/router": { - "version": "8.2.13", - "resolved": "https://registry.npmjs.org/@angular/router/-/router-8.2.13.tgz", - "integrity": "sha512-9CqnachtdASnEmRMtrG/R3c5nDCjjlCU4n0W/xt5+LlveyuUVvAT/CFUC38km4Df3lIvqap8mSpxzGaEzCL+wQ==", - "requires": { - "tslib": "^1.9.0" - } + "version": "9.1.12", + "resolved": "https://registry.npmjs.org/@angular/router/-/router-9.1.12.tgz", + "integrity": "sha512-+qCaXa9y0nsRhzjAYBqmGoQ2YkrdXgftZwuFDf6t4qEi30EXa0oS97KrlFq0M5GKdLIDGrbUm9PcdHSTOI+ZhA==" }, "@babel/code-frame": { "version": "7.5.5", @@ -1149,54 +658,179 @@ "@babel/highlight": "^7.0.0" } }, - "@babel/core": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.5.5.tgz", - "integrity": "sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg==", + "@babel/compat-data": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.11.0.tgz", + "integrity": "sha512-TPSvJfv73ng0pfnEOh17bYMPQbI95+nGWc71Ss4vZdRBHTDqmM9Z8ZV4rYz8Ks7sfzc95n30k6ODIq5UGnXcYQ==", "dev": true, "requires": { - "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.5.5", - "@babel/helpers": "^7.5.5", - "@babel/parser": "^7.5.5", - "@babel/template": "^7.4.4", - "@babel/traverse": "^7.5.5", - "@babel/types": "^7.5.5", - "convert-source-map": "^1.1.0", + "browserslist": "^4.12.0", + "invariant": "^2.2.4", + "semver": "^5.5.0" + } + }, + "@babel/core": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.9.0.tgz", + "integrity": "sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.9.0", + "@babel/helper-module-transforms": "^7.9.0", + "@babel/helpers": "^7.9.0", + "@babel/parser": "^7.9.0", + "@babel/template": "^7.8.6", + "@babel/traverse": "^7.9.0", + "@babel/types": "^7.9.0", + "convert-source-map": "^1.7.0", "debug": "^4.1.0", - "json5": "^2.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", "lodash": "^4.17.13", "resolve": "^1.3.2", "semver": "^5.4.1", "source-map": "^0.5.0" }, "dependencies": { - "json5": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.1.tgz", - "integrity": "sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ==", + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", "dev": true, "requires": { - "minimist": "^1.2.0" + "@babel/highlight": "^7.10.4" } }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "@babel/generator": { + "version": "7.11.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz", + "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==", + "dev": true, + "requires": { + "@babel/types": "^7.11.5", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/helper-function-name": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", + "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", + "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", + "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", + "dev": true, + "requires": { + "@babel/types": "^7.11.0" + } + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", + "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", "dev": true - } - } - }, - "@babel/generator": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.2.tgz", - "integrity": "sha512-WthSArvAjYLz4TcbKOi88me+KmDJdKSlfwwN8CnUYn9jBkzhq0ZEPuBfkAWIvjJ3AdEV1Cf/+eSQTnp3IDJKlQ==", - "dev": true, - "requires": { - "@babel/types": "^7.7.2", - "jsesc": "^2.5.1", - "lodash": "^4.17.13", + }, + "@babel/template": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", + "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/traverse": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz", + "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.11.5", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/parser": "^7.11.5", + "@babel/types": "^7.11.5", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.19" + }, + "dependencies": { + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + }, + "dependencies": { + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + } + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.2.tgz", + "integrity": "sha512-WthSArvAjYLz4TcbKOi88me+KmDJdKSlfwwN8CnUYn9jBkzhq0ZEPuBfkAWIvjJ3AdEV1Cf/+eSQTnp3IDJKlQ==", + "dev": true, + "requires": { + "@babel/types": "^7.7.2", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", "source-map": "^0.5.0" }, "dependencies": { @@ -1209,64 +843,245 @@ } }, "@babel/helper-annotate-as-pure": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.7.0.tgz", - "integrity": "sha512-k50CQxMlYTYo+GGyUGFwpxKVtxVJi9yh61sXZji3zYHccK9RYliZGSTOgci85T+r+0VFN2nWbGM04PIqwfrpMg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz", + "integrity": "sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA==", "dev": true, "requires": { - "@babel/types": "^7.7.0" + "@babel/types": "^7.10.4" + }, + "dependencies": { + "@babel/types": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + } } }, "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.7.0.tgz", - "integrity": "sha512-Cd8r8zs4RKDwMG/92lpZcnn5WPQ3LAMQbCw42oqUh4s7vsSN5ANUZjMel0OOnxDLq57hoDDbai+ryygYfCTOsw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz", + "integrity": "sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg==", "dev": true, "requires": { - "@babel/helper-explode-assignable-expression": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/helper-explode-assignable-expression": "^7.10.4", + "@babel/types": "^7.10.4" + }, + "dependencies": { + "@babel/types": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + } } }, - "@babel/helper-call-delegate": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-call-delegate/-/helper-call-delegate-7.7.0.tgz", - "integrity": "sha512-Su0Mdq7uSSWGZayGMMQ+z6lnL00mMCnGAbO/R0ZO9odIdB/WNU/VfQKqMQU0fdIsxQYbRjDM4BixIa93SQIpvw==", + "@babel/helper-compilation-targets": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz", + "integrity": "sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ==", "dev": true, "requires": { - "@babel/helper-hoist-variables": "^7.7.0", - "@babel/traverse": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/compat-data": "^7.10.4", + "browserslist": "^4.12.0", + "invariant": "^2.2.4", + "levenary": "^1.1.1", + "semver": "^5.5.0" } }, "@babel/helper-create-regexp-features-plugin": { - "version": "7.7.2", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.7.2.tgz", - "integrity": "sha512-pAil/ZixjTlrzNpjx+l/C/wJk002Wo7XbbZ8oujH/AoJ3Juv0iN/UTcPUHXKMFLqsfS0Hy6Aow8M31brUYBlQQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz", + "integrity": "sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g==", "dev": true, "requires": { - "@babel/helper-regex": "^7.4.4", - "regexpu-core": "^4.6.0" + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-regex": "^7.10.4", + "regexpu-core": "^4.7.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", + "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", + "dev": true, + "requires": { + "regenerate": "^1.4.0" + } + }, + "regexpu-core": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz", + "integrity": "sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ==", + "dev": true, + "requires": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.2.0", + "regjsgen": "^0.5.1", + "regjsparser": "^0.6.4", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.2.0" + } + }, + "regjsparser": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.4.tgz", + "integrity": "sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", + "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==", + "dev": true + } } }, "@babel/helper-define-map": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.7.0.tgz", - "integrity": "sha512-kPKWPb0dMpZi+ov1hJiwse9dWweZsz3V9rP4KdytnX1E7z3cTNmFGglwklzFPuqIcHLIY3bgKSs4vkwXXdflQA==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz", + "integrity": "sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.7.0", - "@babel/types": "^7.7.0", - "lodash": "^4.17.13" + "@babel/helper-function-name": "^7.10.4", + "@babel/types": "^7.10.5", + "lodash": "^4.17.19" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/helper-function-name": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", + "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", + "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", + "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", + "dev": true + }, + "@babel/template": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", + "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/types": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + } } }, "@babel/helper-explode-assignable-expression": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.7.0.tgz", - "integrity": "sha512-CDs26w2shdD1urNUAji2RJXyBFCaR+iBEGnFz3l7maizMkQe3saVw9WtjG1tz8CwbjvlFnaSLVhgnu1SWaherg==", + "version": "7.11.4", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.11.4.tgz", + "integrity": "sha512-ux9hm3zR4WV1Y3xXxXkdG/0gxF9nvI0YVmKVhvK9AfMoaQkemL3sJpXw+Xbz65azo8qJiEz2XVDUpK3KYhH3ZQ==", "dev": true, "requires": { - "@babel/traverse": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/types": "^7.10.4" + }, + "dependencies": { + "@babel/types": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + } } }, "@babel/helper-function-name": { @@ -1290,137 +1105,789 @@ } }, "@babel/helper-hoist-variables": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.7.0.tgz", - "integrity": "sha512-LUe/92NqsDAkJjjCEWkNe+/PcpnisvnqdlRe19FahVapa4jndeuJ+FBiTX1rcAKWKcJGE+C3Q3tuEuxkSmCEiQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz", + "integrity": "sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA==", "dev": true, "requires": { - "@babel/types": "^7.7.0" + "@babel/types": "^7.10.4" + }, + "dependencies": { + "@babel/types": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + } } }, "@babel/helper-member-expression-to-functions": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.7.0.tgz", - "integrity": "sha512-QaCZLO2RtBcmvO/ekOLp8p7R5X2JriKRizeDpm5ChATAFWrrYDcDxPuCIBXKyBjY+i1vYSdcUTMIb8psfxHDPA==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz", + "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==", "dev": true, "requires": { - "@babel/types": "^7.7.0" + "@babel/types": "^7.11.0" + }, + "dependencies": { + "@babel/types": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + } } }, "@babel/helper-module-imports": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.7.0.tgz", - "integrity": "sha512-Dv3hLKIC1jyfTkClvyEkYP2OlkzNvWs5+Q8WgPbxM5LMeorons7iPP91JM+DU7tRbhqA1ZeooPaMFvQrn23RHw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz", + "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==", "dev": true, "requires": { - "@babel/types": "^7.7.0" + "@babel/types": "^7.10.4" + }, + "dependencies": { + "@babel/types": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + } } }, "@babel/helper-module-transforms": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.7.0.tgz", - "integrity": "sha512-rXEefBuheUYQyX4WjV19tuknrJFwyKw0HgzRwbkyTbB+Dshlq7eqkWbyjzToLrMZk/5wKVKdWFluiAsVkHXvuQ==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.7.0", - "@babel/helper-simple-access": "^7.7.0", - "@babel/helper-split-export-declaration": "^7.7.0", - "@babel/template": "^7.7.0", - "@babel/types": "^7.7.0", - "lodash": "^4.17.13" + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz", + "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4", + "@babel/helper-simple-access": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/template": "^7.10.4", + "@babel/types": "^7.11.0", + "lodash": "^4.17.19" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", + "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", + "dev": true, + "requires": { + "@babel/types": "^7.11.0" + } + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", + "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", + "dev": true + }, + "@babel/template": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", + "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/types": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + } } }, "@babel/helper-optimise-call-expression": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.7.0.tgz", - "integrity": "sha512-48TeqmbazjNU/65niiiJIJRc5JozB8acui1OS7bSd6PgxfuovWsvjfWSzlgx+gPFdVveNzUdpdIg5l56Pl5jqg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz", + "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==", "dev": true, "requires": { - "@babel/types": "^7.7.0" + "@babel/types": "^7.10.4" + }, + "dependencies": { + "@babel/types": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + } } }, "@babel/helper-plugin-utils": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", - "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", "dev": true }, "@babel/helper-regex": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.5.5.tgz", - "integrity": "sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.10.5.tgz", + "integrity": "sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg==", "dev": true, "requires": { - "lodash": "^4.17.13" + "lodash": "^4.17.19" + }, + "dependencies": { + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + } } }, "@babel/helper-remap-async-to-generator": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.7.0.tgz", - "integrity": "sha512-pHx7RN8X0UNHPB/fnuDnRXVZ316ZigkO8y8D835JlZ2SSdFKb6yH9MIYRU4fy/KPe5sPHDFOPvf8QLdbAGGiyw==", + "version": "7.11.4", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.11.4.tgz", + "integrity": "sha512-tR5vJ/vBa9wFy3m5LLv2faapJLnDFxNWff2SAYkSE4rLUdbp7CdObYFgI7wK4T/Mj4UzpjPwzR8Pzmr5m7MHGA==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.7.0", - "@babel/helper-wrap-function": "^7.7.0", - "@babel/template": "^7.7.0", - "@babel/traverse": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-wrap-function": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", + "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", + "dev": true + }, + "@babel/template": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", + "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/types": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + } } }, "@babel/helper-replace-supers": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.7.0.tgz", - "integrity": "sha512-5ALYEul5V8xNdxEeWvRsBzLMxQksT7MaStpxjJf9KsnLxpAKBtfw5NeMKZJSYDa0lKdOcy0g+JT/f5mPSulUgg==", - "dev": true, - "requires": { - "@babel/helper-member-expression-to-functions": "^7.7.0", - "@babel/helper-optimise-call-expression": "^7.7.0", - "@babel/traverse": "^7.7.0", - "@babel/types": "^7.7.0" - } - }, - "@babel/helper-simple-access": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.7.0.tgz", - "integrity": "sha512-AJ7IZD7Eem3zZRuj5JtzFAptBw7pMlS3y8Qv09vaBWoFsle0d1kAn5Wq6Q9MyBXITPOKnxwkZKoAm4bopmv26g==", - "dev": true, - "requires": { - "@babel/template": "^7.7.0", - "@babel/types": "^7.7.0" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.0.tgz", - "integrity": "sha512-HgYSI8rH08neWlAH3CcdkFg9qX9YsZysZI5GD8LjhQib/mM0jGOZOVkoUiiV2Hu978fRtjtsGsW6w0pKHUWtqA==", - "dev": true, - "requires": { - "@babel/types": "^7.7.0" - } - }, - "@babel/helper-wrap-function": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.7.0.tgz", - "integrity": "sha512-sd4QjeMgQqzshSjecZjOp8uKfUtnpmCyQhKQrVJBBgeHAB/0FPi33h3AbVlVp07qQtMD4QgYSzaMI7VwncNK/w==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz", + "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==", "dev": true, "requires": { - "@babel/helper-function-name": "^7.7.0", - "@babel/template": "^7.7.0", - "@babel/traverse": "^7.7.0", - "@babel/types": "^7.7.0" + "@babel/helper-member-expression-to-functions": "^7.10.4", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/generator": { + "version": "7.11.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz", + "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==", + "dev": true, + "requires": { + "@babel/types": "^7.11.5", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/helper-function-name": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", + "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", + "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", + "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", + "dev": true, + "requires": { + "@babel/types": "^7.11.0" + } + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", + "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", + "dev": true + }, + "@babel/template": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", + "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/traverse": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz", + "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.11.5", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/parser": "^7.11.5", + "@babel/types": "^7.11.5", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.19" + } + }, + "@babel/types": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } } }, - "@babel/helpers": { + "@babel/helper-simple-access": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz", + "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==", + "dev": true, + "requires": { + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", + "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", + "dev": true + }, + "@babel/template": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", + "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/types": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + } + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz", + "integrity": "sha512-0XIdiQln4Elglgjbwo9wuJpL/K7AGCY26kmEt0+pRP0TAj4jjyNq1MjoRvikrTVqKcx4Gysxt4cXvVFXP/JO2Q==", + "dev": true, + "requires": { + "@babel/types": "^7.11.0" + }, + "dependencies": { + "@babel/types": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + } + } + }, + "@babel/helper-split-export-declaration": { "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.7.0.tgz", - "integrity": "sha512-VnNwL4YOhbejHb7x/b5F39Zdg5vIQpUUNzJwx0ww1EcVRt41bbGRZWhAURrfY32T5zTT3qwNOQFWpn+P0i0a2g==", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.0.tgz", + "integrity": "sha512-HgYSI8rH08neWlAH3CcdkFg9qX9YsZysZI5GD8LjhQib/mM0jGOZOVkoUiiV2Hu978fRtjtsGsW6w0pKHUWtqA==", "dev": true, "requires": { - "@babel/template": "^7.7.0", - "@babel/traverse": "^7.7.0", "@babel/types": "^7.7.0" } }, + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "dev": true + }, + "@babel/helper-wrap-function": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz", + "integrity": "sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/generator": { + "version": "7.11.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz", + "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==", + "dev": true, + "requires": { + "@babel/types": "^7.11.5", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/helper-function-name": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", + "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", + "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", + "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", + "dev": true, + "requires": { + "@babel/types": "^7.11.0" + } + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", + "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", + "dev": true + }, + "@babel/template": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", + "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/traverse": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz", + "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.11.5", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/parser": "^7.11.5", + "@babel/types": "^7.11.5", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.19" + } + }, + "@babel/types": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "@babel/helpers": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz", + "integrity": "sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==", + "dev": true, + "requires": { + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/generator": { + "version": "7.11.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz", + "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==", + "dev": true, + "requires": { + "@babel/types": "^7.11.5", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/helper-function-name": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", + "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", + "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", + "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", + "dev": true, + "requires": { + "@babel/types": "^7.11.0" + } + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", + "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", + "dev": true + }, + "@babel/template": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", + "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/traverse": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz", + "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.11.5", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/parser": "^7.11.5", + "@babel/types": "^7.11.5", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.19" + } + }, + "@babel/types": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, "@babel/highlight": { "version": "7.5.0", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", @@ -1439,473 +1906,781 @@ "dev": true }, "@babel/plugin-proposal-async-generator-functions": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.7.0.tgz", - "integrity": "sha512-ot/EZVvf3mXtZq0Pd0+tSOfGWMizqmOohXmNZg6LNFjHOV+wOPv7BvVYh8oPR8LhpIP3ye8nNooKL50YRWxpYA==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz", + "integrity": "sha512-cNMCVezQbrRGvXJwm9fu/1sJj9bHdGAgKodZdLqOQIpfoH3raqmRPBM17+lh7CzhiKRRBrGtZL9WcjxSoGYUSg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.7.0", - "@babel/plugin-syntax-async-generators": "^7.2.0" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-remap-async-to-generator": "^7.10.4", + "@babel/plugin-syntax-async-generators": "^7.8.0" } }, "@babel/plugin-proposal-dynamic-import": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.7.0.tgz", - "integrity": "sha512-7poL3Xi+QFPC7sGAzEIbXUyYzGJwbc2+gSD0AkiC5k52kH2cqHdqxm5hNFfLW3cRSTcx9bN0Fl7/6zWcLLnKAQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz", + "integrity": "sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-dynamic-import": "^7.2.0" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-dynamic-import": "^7.8.0" } }, "@babel/plugin-proposal-json-strings": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz", - "integrity": "sha512-MAFV1CA/YVmYwZG0fBQyXhmj0BHCB5egZHCKWIFVv/XCxAeVGIHfos3SwDck4LvCllENIAg7xMKOG5kH0dzyUg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz", + "integrity": "sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-json-strings": "^7.2.0" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.0" } }, - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.6.2.tgz", - "integrity": "sha512-LDBXlmADCsMZV1Y9OQwMc0MyGZ8Ta/zlD9N67BfQT8uYwkRswiu2hU6nJKrjrt/58aH/vqfQlR/9yId/7A2gWw==", + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz", + "integrity": "sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-object-rest-spread": "^7.2.0" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" } }, - "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz", - "integrity": "sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==", + "@babel/plugin-proposal-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz", + "integrity": "sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.2.0" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" } }, - "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.7.0.tgz", - "integrity": "sha512-mk34H+hp7kRBWJOOAR0ZMGCydgKMD4iN9TpDRp3IIcbunltxEY89XSimc6WbtSLCDrwcdy/EEw7h5CFCzxTchw==", + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.11.0.tgz", + "integrity": "sha512-wzch41N4yztwoRw0ak+37wxwJM2oiIiy6huGCoqkvSTA9acYWcPfn9Y4aJqmFFJ70KTJUu29f3DQ43uJ9HXzEA==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.7.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-transform-parameters": "^7.10.4" } }, - "@babel/plugin-syntax-async-generators": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz", - "integrity": "sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==", + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz", + "integrity": "sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" } }, - "@babel/plugin-syntax-dynamic-import": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz", - "integrity": "sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w==", + "@babel/plugin-proposal-optional-chaining": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz", + "integrity": "sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.0" } }, - "@babel/plugin-syntax-json-strings": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.2.0.tgz", - "integrity": "sha512-5UGYnMSLRE1dqqZwug+1LISpA403HzlSfsg6P9VXU6TBjcSHeNlw4DxDx7LgpF+iKZoOG/+uzqoRHTdcUpiZNg==", + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz", + "integrity": "sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-create-regexp-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.2.0.tgz", - "integrity": "sha512-t0JKGgqk2We+9may3t0xDdmneaXmyxq0xieYcKHxIsrJO64n1OiMWNUtc5gQK1PA0NpdCRrtZp4z+IUaKugrSA==", + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.8.0" } }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz", - "integrity": "sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w==", + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.8.0" } }, - "@babel/plugin-transform-arrow-functions": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz", - "integrity": "sha512-ER77Cax1+8/8jCB9fo4Ud161OZzWN5qawi4GusDuRLcDbDG+bIGYY20zb2dfAFdTRGzrfq2xZPvF0R64EHnimg==", + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.8.0" } }, - "@babel/plugin-transform-async-to-generator": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.7.0.tgz", - "integrity": "sha512-vLI2EFLVvRBL3d8roAMqtVY0Bm9C1QzLkdS57hiKrjUBSqsQYrBsMCeOg/0KK7B0eK9V71J5mWcha9yyoI2tZw==", + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.7.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-remap-async-to-generator": "^7.7.0" + "@babel/helper-plugin-utils": "^7.8.0" } }, - "@babel/plugin-transform-block-scoped-functions": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.2.0.tgz", - "integrity": "sha512-ntQPR6q1/NKuphly49+QiQiTN0O63uOwjdD6dhIjSWBI5xlrbUFh720TIpzBhpnrLfv2tNH/BXvLIab1+BAI0w==", + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, - "@babel/plugin-transform-block-scoping": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.6.3.tgz", - "integrity": "sha512-7hvrg75dubcO3ZI2rjYTzUrEuh1E9IyDEhhB6qfcooxhDA33xx2MasuLVgdxzcP6R/lipAC6n9ub9maNW6RKdw==", + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "lodash": "^4.17.13" + "@babel/helper-plugin-utils": "^7.8.0" } }, - "@babel/plugin-transform-classes": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.7.0.tgz", - "integrity": "sha512-/b3cKIZwGeUesZheU9jNYcwrEA7f/Bo4IdPmvp7oHgvks2majB5BoT5byAql44fiNQYOPzhk2w8DbgfuafkMoA==", + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.7.0", - "@babel/helper-define-map": "^7.7.0", - "@babel/helper-function-name": "^7.7.0", - "@babel/helper-optimise-call-expression": "^7.7.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.7.0", - "@babel/helper-split-export-declaration": "^7.7.0", - "globals": "^11.1.0" + "@babel/helper-plugin-utils": "^7.8.0" } }, - "@babel/plugin-transform-computed-properties": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.2.0.tgz", - "integrity": "sha512-kP/drqTxY6Xt3NNpKiMomfgkNn4o7+vKxK2DDKcBG9sHj51vHqMBGy8wbDS/J4lMxnqs153/T3+DmCEAkC5cpA==", + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.8.0" } }, - "@babel/plugin-transform-destructuring": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.6.0.tgz", - "integrity": "sha512-2bGIS5P1v4+sWTCnKNDZDxbGvEqi0ijeqM/YqHtVGrvG2y0ySgnEEhXErvE9dA0bnIzY9bIzdFK0jFA46ASIIQ==", + "@babel/plugin-syntax-top-level-await": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz", + "integrity": "sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, - "@babel/plugin-transform-dotall-regex": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.7.0.tgz", - "integrity": "sha512-3QQlF7hSBnSuM1hQ0pS3pmAbWLax/uGNCbPBND9y+oJ4Y776jsyujG2k0Sn2Aj2a0QwVOiOFL5QVPA7spjvzSA==", + "@babel/plugin-transform-arrow-functions": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz", + "integrity": "sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.7.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, - "@babel/plugin-transform-duplicate-keys": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.5.0.tgz", - "integrity": "sha512-igcziksHizyQPlX9gfSjHkE2wmoCH3evvD2qR5w29/Dk0SMKE/eOI7f1HhBdNhR/zxJDqrgpoDTq5YSLH/XMsQ==", + "@babel/plugin-transform-async-to-generator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz", + "integrity": "sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-remap-async-to-generator": "^7.10.4" } }, - "@babel/plugin-transform-exponentiation-operator": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.2.0.tgz", - "integrity": "sha512-umh4hR6N7mu4Elq9GG8TOu9M0bakvlsREEC+ialrQN6ABS4oDQ69qJv1VtR3uxlKMCQMCvzk7vr17RHKcjx68A==", + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz", + "integrity": "sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA==", "dev": true, "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, - "@babel/plugin-transform-for-of": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.4.4.tgz", - "integrity": "sha512-9T/5Dlr14Z9TIEXLXkt8T1DU7F24cbhwhMNUziN3hB1AXoZcdzPcTiKGRn/6iOymDqtTKWnr/BtRKN9JwbKtdQ==", + "@babel/plugin-transform-block-scoping": { + "version": "7.11.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.11.1.tgz", + "integrity": "sha512-00dYeDE0EVEHuuM+26+0w/SCL0BH2Qy7LwHuI4Hi4MH5gkC8/AqMN5uWFJIsoXZrAphiMm1iXzBw6L2T+eA0ew==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, - "@babel/plugin-transform-function-name": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.7.0.tgz", - "integrity": "sha512-P5HKu0d9+CzZxP5jcrWdpe7ZlFDe24bmqP6a6X8BHEBl/eizAsY8K6LX8LASZL0Jxdjm5eEfzp+FIrxCm/p8bA==", - "dev": true, + "@babel/plugin-transform-classes": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz", + "integrity": "sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-define-map": "^7.10.4", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.10.4", + "globals": "^11.1.0" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/helper-function-name": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", + "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", + "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", + "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", + "dev": true, + "requires": { + "@babel/types": "^7.11.0" + } + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", + "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", + "dev": true + }, + "@babel/template": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", + "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/types": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + } + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz", + "integrity": "sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw==", + "dev": true, "requires": { - "@babel/helper-function-name": "^7.7.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz", + "integrity": "sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz", + "integrity": "sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz", + "integrity": "sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz", + "integrity": "sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz", + "integrity": "sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz", + "integrity": "sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/helper-function-name": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", + "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", + "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", + "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", + "dev": true + }, + "@babel/template": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", + "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4" + } + }, + "@babel/types": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + } } }, "@babel/plugin-transform-literals": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.2.0.tgz", - "integrity": "sha512-2ThDhm4lI4oV7fVQ6pNNK+sx+c/GM5/SaML0w/r4ZB7sAneD/piDJtwdKlNckXeyGK7wlwg2E2w33C/Hh+VFCg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz", + "integrity": "sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-member-expression-literals": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.2.0.tgz", - "integrity": "sha512-HiU3zKkSU6scTidmnFJ0bMX8hz5ixC93b4MHMiYebmk2lUVNGOboPsqQvx5LzooihijUoLR/v7Nc1rbBtnc7FA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz", + "integrity": "sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-modules-amd": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.5.0.tgz", - "integrity": "sha512-n20UsQMKnWrltocZZm24cRURxQnWIvsABPJlw/fvoy9c6AgHZzoelAIzajDHAQrDpuKFFPPcFGd7ChsYuIUMpg==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz", + "integrity": "sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.1.0", - "@babel/helper-plugin-utils": "^7.0.0", - "babel-plugin-dynamic-import-node": "^2.3.0" + "@babel/helper-module-transforms": "^7.10.5", + "@babel/helper-plugin-utils": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.7.0.tgz", - "integrity": "sha512-KEMyWNNWnjOom8vR/1+d+Ocz/mILZG/eyHHO06OuBQ2aNhxT62fr4y6fGOplRx+CxCSp3IFwesL8WdINfY/3kg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz", + "integrity": "sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.7.0", - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-simple-access": "^7.7.0", - "babel-plugin-dynamic-import-node": "^2.3.0" + "@babel/helper-module-transforms": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-simple-access": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-systemjs": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.7.0.tgz", - "integrity": "sha512-ZAuFgYjJzDNv77AjXRqzQGlQl4HdUM6j296ee4fwKVZfhDR9LAGxfvXjBkb06gNETPnN0sLqRm9Gxg4wZH6dXg==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz", + "integrity": "sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw==", "dev": true, "requires": { - "@babel/helper-hoist-variables": "^7.7.0", - "@babel/helper-plugin-utils": "^7.0.0", - "babel-plugin-dynamic-import-node": "^2.3.0" + "@babel/helper-hoist-variables": "^7.10.4", + "@babel/helper-module-transforms": "^7.10.5", + "@babel/helper-plugin-utils": "^7.10.4", + "babel-plugin-dynamic-import-node": "^2.3.3" } }, "@babel/plugin-transform-modules-umd": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.7.0.tgz", - "integrity": "sha512-u7eBA03zmUswQ9LQ7Qw0/ieC1pcAkbp5OQatbWUzY1PaBccvuJXUkYzoN1g7cqp7dbTu6Dp9bXyalBvD04AANA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz", + "integrity": "sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.7.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-module-transforms": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.7.0.tgz", - "integrity": "sha512-+SicSJoKouPctL+j1pqktRVCgy+xAch1hWWTMy13j0IflnyNjaoskj+DwRQFimHbLqO3sq2oN2CXMvXq3Bgapg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz", + "integrity": "sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.7.0" + "@babel/helper-create-regexp-features-plugin": "^7.10.4" } }, "@babel/plugin-transform-new-target": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.4.4.tgz", - "integrity": "sha512-r1z3T2DNGQwwe2vPGZMBNjioT2scgWzK9BCnDEh+46z8EEwXBq24uRzd65I7pjtugzPSj921aM15RpESgzsSuA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz", + "integrity": "sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-object-super": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.5.5.tgz", - "integrity": "sha512-un1zJQAhSosGFBduPgN/YFNvWVpRuHKU7IHBglLoLZsGmruJPOo6pbInneflUdmq7YvSVqhpPs5zdBvLnteltQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz", + "integrity": "sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-replace-supers": "^7.5.5" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4" } }, "@babel/plugin-transform-parameters": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.4.4.tgz", - "integrity": "sha512-oMh5DUO1V63nZcu/ZVLQFqiihBGo4OpxJxR1otF50GMeCLiRx5nUdtokd+u9SuVJrvvuIh9OosRFPP4pIPnwmw==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz", + "integrity": "sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw==", "dev": true, "requires": { - "@babel/helper-call-delegate": "^7.4.4", - "@babel/helper-get-function-arity": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" + }, + "dependencies": { + "@babel/helper-get-function-arity": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", + "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", + "dev": true, + "requires": { + "@babel/types": "^7.10.4" + } + }, + "@babel/types": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + } } }, "@babel/plugin-transform-property-literals": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.2.0.tgz", - "integrity": "sha512-9q7Dbk4RhgcLp8ebduOpCbtjh7C0itoLYHXd9ueASKAG/is5PQtMR5VJGka9NKqGhYEGn5ITahd4h9QeBMylWQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz", + "integrity": "sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-regenerator": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.7.0.tgz", - "integrity": "sha512-AXmvnC+0wuj/cFkkS/HFHIojxH3ffSXE+ttulrqWjZZRaUOonfJc60e1wSNT4rV8tIunvu/R3wCp71/tLAa9xg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz", + "integrity": "sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw==", "dev": true, "requires": { - "regenerator-transform": "^0.14.0" + "regenerator-transform": "^0.14.2" } }, "@babel/plugin-transform-reserved-words": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.2.0.tgz", - "integrity": "sha512-fz43fqW8E1tAB3DKF19/vxbpib1fuyCwSPE418ge5ZxILnBhWyhtPgz8eh1RCGGJlwvksHkyxMxh0eenFi+kFw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz", + "integrity": "sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-shorthand-properties": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.2.0.tgz", - "integrity": "sha512-QP4eUM83ha9zmYtpbnyjTLAGKQritA5XW/iG9cjtuOI8s1RuL/3V6a3DeSHfKutJQ+ayUfeZJPcnCYEQzaPQqg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz", + "integrity": "sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-spread": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.6.2.tgz", - "integrity": "sha512-DpSvPFryKdK1x+EDJYCy28nmAaIMdxmhot62jAXF/o99iA33Zj2Lmcp3vDmz+MUh0LNYVPvfj5iC3feb3/+PFg==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.11.0.tgz", + "integrity": "sha512-UwQYGOqIdQJe4aWNyS7noqAnN2VbaczPLiEtln+zPowRNlD+79w3oi2TWfYe0eZgd+gjZCbsydN7lzWysDt+gw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0" } }, "@babel/plugin-transform-sticky-regex": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.2.0.tgz", - "integrity": "sha512-KKYCoGaRAf+ckH8gEL3JHUaFVyNHKe3ASNsZ+AlktgHevvxGigoIttrEJb8iKN03Q7Eazlv1s6cx2B2cQ3Jabw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz", + "integrity": "sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/helper-regex": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/helper-regex": "^7.10.4" } }, "@babel/plugin-transform-template-literals": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.4.4.tgz", - "integrity": "sha512-mQrEC4TWkhLN0z8ygIvEL9ZEToPhG5K7KDW3pzGqOfIGZ28Jb0POUkeWcoz8HnHvhFy6dwAT1j8OzqN8s804+g==", + "version": "7.10.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz", + "integrity": "sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw==", "dev": true, "requires": { - "@babel/helper-annotate-as-pure": "^7.0.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-annotate-as-pure": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-typeof-symbol": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.2.0.tgz", - "integrity": "sha512-2LNhETWYxiYysBtrBTqL8+La0jIoQQnIScUJc74OYvUGRmkskNY4EzLCnjHBzdmb38wqtTaixpo1NctEcvMDZw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz", + "integrity": "sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-transform-unicode-regex": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.7.0.tgz", - "integrity": "sha512-RrThb0gdrNwFAqEAAx9OWgtx6ICK69x7i9tCnMdVrxQwSDp/Abu9DXFU5Hh16VP33Rmxh04+NGW28NsIkFvFKA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz", + "integrity": "sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A==", "dev": true, "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.7.0", - "@babel/helper-plugin-utils": "^7.0.0" + "@babel/helper-create-regexp-features-plugin": "^7.10.4", + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/preset-env": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.5.5.tgz", - "integrity": "sha512-GMZQka/+INwsMz1A5UEql8tG015h5j/qjptpKY2gJ7giy8ohzU710YciJB5rcKsWGWHiW3RUnHib0E5/m3Tp3A==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.9.0.tgz", + "integrity": "sha512-712DeRXT6dyKAM/FMbQTV/FvRCms2hPCx+3weRjZ8iQVQWZejWWk1wwG6ViWMyqb/ouBbGOl5b6aCk0+j1NmsQ==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.9.0", + "@babel/helper-compilation-targets": "^7.8.7", + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-plugin-utils": "^7.8.3", + "@babel/plugin-proposal-async-generator-functions": "^7.8.3", + "@babel/plugin-proposal-dynamic-import": "^7.8.3", + "@babel/plugin-proposal-json-strings": "^7.8.3", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-proposal-numeric-separator": "^7.8.3", + "@babel/plugin-proposal-object-rest-spread": "^7.9.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.8.3", + "@babel/plugin-proposal-optional-chaining": "^7.9.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.8.3", + "@babel/plugin-syntax-async-generators": "^7.8.0", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-json-strings": "^7.8.0", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", + "@babel/plugin-syntax-numeric-separator": "^7.8.0", + "@babel/plugin-syntax-object-rest-spread": "^7.8.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.0", + "@babel/plugin-syntax-top-level-await": "^7.8.3", + "@babel/plugin-transform-arrow-functions": "^7.8.3", + "@babel/plugin-transform-async-to-generator": "^7.8.3", + "@babel/plugin-transform-block-scoped-functions": "^7.8.3", + "@babel/plugin-transform-block-scoping": "^7.8.3", + "@babel/plugin-transform-classes": "^7.9.0", + "@babel/plugin-transform-computed-properties": "^7.8.3", + "@babel/plugin-transform-destructuring": "^7.8.3", + "@babel/plugin-transform-dotall-regex": "^7.8.3", + "@babel/plugin-transform-duplicate-keys": "^7.8.3", + "@babel/plugin-transform-exponentiation-operator": "^7.8.3", + "@babel/plugin-transform-for-of": "^7.9.0", + "@babel/plugin-transform-function-name": "^7.8.3", + "@babel/plugin-transform-literals": "^7.8.3", + "@babel/plugin-transform-member-expression-literals": "^7.8.3", + "@babel/plugin-transform-modules-amd": "^7.9.0", + "@babel/plugin-transform-modules-commonjs": "^7.9.0", + "@babel/plugin-transform-modules-systemjs": "^7.9.0", + "@babel/plugin-transform-modules-umd": "^7.9.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.8.3", + "@babel/plugin-transform-new-target": "^7.8.3", + "@babel/plugin-transform-object-super": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.8.7", + "@babel/plugin-transform-property-literals": "^7.8.3", + "@babel/plugin-transform-regenerator": "^7.8.7", + "@babel/plugin-transform-reserved-words": "^7.8.3", + "@babel/plugin-transform-shorthand-properties": "^7.8.3", + "@babel/plugin-transform-spread": "^7.8.3", + "@babel/plugin-transform-sticky-regex": "^7.8.3", + "@babel/plugin-transform-template-literals": "^7.8.3", + "@babel/plugin-transform-typeof-symbol": "^7.8.4", + "@babel/plugin-transform-unicode-regex": "^7.8.3", + "@babel/preset-modules": "^0.1.3", + "@babel/types": "^7.9.0", + "browserslist": "^4.9.1", + "core-js-compat": "^3.6.2", + "invariant": "^2.2.2", + "levenary": "^1.1.1", + "semver": "^5.5.0" + }, + "dependencies": { + "@babel/types": { + "version": "7.11.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", + "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", + "to-fast-properties": "^2.0.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + } + } + }, + "@babel/preset-modules": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz", + "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==", "dev": true, "requires": { - "@babel/helper-module-imports": "^7.0.0", "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-async-generator-functions": "^7.2.0", - "@babel/plugin-proposal-dynamic-import": "^7.5.0", - "@babel/plugin-proposal-json-strings": "^7.2.0", - "@babel/plugin-proposal-object-rest-spread": "^7.5.5", - "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-syntax-async-generators": "^7.2.0", - "@babel/plugin-syntax-dynamic-import": "^7.2.0", - "@babel/plugin-syntax-json-strings": "^7.2.0", - "@babel/plugin-syntax-object-rest-spread": "^7.2.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.2.0", - "@babel/plugin-transform-arrow-functions": "^7.2.0", - "@babel/plugin-transform-async-to-generator": "^7.5.0", - "@babel/plugin-transform-block-scoped-functions": "^7.2.0", - "@babel/plugin-transform-block-scoping": "^7.5.5", - "@babel/plugin-transform-classes": "^7.5.5", - "@babel/plugin-transform-computed-properties": "^7.2.0", - "@babel/plugin-transform-destructuring": "^7.5.0", "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/plugin-transform-duplicate-keys": "^7.5.0", - "@babel/plugin-transform-exponentiation-operator": "^7.2.0", - "@babel/plugin-transform-for-of": "^7.4.4", - "@babel/plugin-transform-function-name": "^7.4.4", - "@babel/plugin-transform-literals": "^7.2.0", - "@babel/plugin-transform-member-expression-literals": "^7.2.0", - "@babel/plugin-transform-modules-amd": "^7.5.0", - "@babel/plugin-transform-modules-commonjs": "^7.5.0", - "@babel/plugin-transform-modules-systemjs": "^7.5.0", - "@babel/plugin-transform-modules-umd": "^7.2.0", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.4.5", - "@babel/plugin-transform-new-target": "^7.4.4", - "@babel/plugin-transform-object-super": "^7.5.5", - "@babel/plugin-transform-parameters": "^7.4.4", - "@babel/plugin-transform-property-literals": "^7.2.0", - "@babel/plugin-transform-regenerator": "^7.4.5", - "@babel/plugin-transform-reserved-words": "^7.2.0", - "@babel/plugin-transform-shorthand-properties": "^7.2.0", - "@babel/plugin-transform-spread": "^7.2.0", - "@babel/plugin-transform-sticky-regex": "^7.2.0", - "@babel/plugin-transform-template-literals": "^7.4.4", - "@babel/plugin-transform-typeof-symbol": "^7.2.0", - "@babel/plugin-transform-unicode-regex": "^7.4.4", - "@babel/types": "^7.5.5", - "browserslist": "^4.6.0", - "core-js-compat": "^3.1.1", - "invariant": "^2.2.2", - "js-levenshtein": "^1.1.3", - "semver": "^5.5.0" + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + } + }, + "@babel/runtime": { + "version": "7.11.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz", + "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.4" } }, "@babel/template": { @@ -1976,23 +2751,63 @@ "@fortawesome/fontawesome-common-types": "^0.2.25" } }, + "@istanbuljs/schema": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", + "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", + "dev": true + }, + "@jsdevtools/coverage-istanbul-loader": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@jsdevtools/coverage-istanbul-loader/-/coverage-istanbul-loader-3.0.3.tgz", + "integrity": "sha512-TAdNkeGB5Fe4Og+ZkAr1Kvn9by2sfL44IAHFtxlh1BA1XJ5cLpO9iSNki5opWESv3l3vSHsZ9BNKuqFKbEbFaA==", + "dev": true, + "requires": { + "convert-source-map": "^1.7.0", + "istanbul-lib-instrument": "^4.0.1", + "loader-utils": "^1.4.0", + "merge-source-map": "^1.1.0", + "schema-utils": "^2.6.4" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + } + } + }, "@ngtools/webpack": { - "version": "8.3.18", - "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-8.3.18.tgz", - "integrity": "sha512-n3a5IpetPyHEeEcksUf2Ul+hgPfnVnMzvRva/QoTJpLfL1ZpIUAHBeB7qWa5OtJEC87rtLJ2JOc/8nJ9xDCcEQ==", + "version": "9.1.12", + "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-9.1.12.tgz", + "integrity": "sha512-lypMXIq5oxBMsoDu/VOa1yUmmXthhxkCJa8LG0ZohfnbwhmZvz3SAW7omBGuVrb5cVIfLCkaRCSnQ1MNc6ULXw==", "dev": true, "requires": { - "@angular-devkit/core": "8.3.18", - "enhanced-resolve": "4.1.0", - "rxjs": "6.4.0", - "tree-kill": "1.2.1", + "@angular-devkit/core": "9.1.12", + "enhanced-resolve": "4.1.1", + "rxjs": "6.5.4", "webpack-sources": "1.4.3" }, "dependencies": { "rxjs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", - "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz", + "integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==", "dev": true, "requires": { "tslib": "^1.9.0" @@ -2000,62 +2815,105 @@ } } }, + "@nodelib/fs.scandir": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", + "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.3", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", + "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", + "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.3", + "fastq": "^1.6.0" + } + }, + "@npmcli/move-file": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.0.1.tgz", + "integrity": "sha512-Uv6h1sT+0DrblvIrolFtbvM1FgWm+/sy4B3pvLp67Zys+thcukzS5ekn7HsZFGpWP4Q3fYJCljbWQE/XivMRLw==", + "dev": true, + "requires": { + "mkdirp": "^1.0.4" + }, + "dependencies": { + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + } + } + }, "@schematics/angular": { - "version": "8.3.18", - "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-8.3.18.tgz", - "integrity": "sha512-3cQYcmzsWD/MnqauoSozIu1R7DJvty13BH6+XIorEfguWqOwOwgNIWLMsa0iIcy0+TV3vWFI0KZpCKup2u/I1Q==", + "version": "9.1.12", + "resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-9.1.12.tgz", + "integrity": "sha512-r4+aPAGhstsKFMwW/kOen1ACnzuLpz+vMxEpndXOqqVXLkAMsuAbQUFYjIlMy6fH4zdhpI90EJZ1PbOrAXvKxA==", "dev": true, "requires": { - "@angular-devkit/core": "8.3.18", - "@angular-devkit/schematics": "8.3.18" + "@angular-devkit/core": "9.1.12", + "@angular-devkit/schematics": "9.1.12" } }, "@schematics/update": { - "version": "0.803.18", - "resolved": "https://registry.npmjs.org/@schematics/update/-/update-0.803.18.tgz", - "integrity": "sha512-vJxyL1pbn2lcgSH6HUqgA373iJRXQWxdrxuUaQ56qyq1EoicG7EppKz7OlGyKs+nHR9HhtK0eJc35E7I0lEWgA==", + "version": "0.901.12", + "resolved": "https://registry.npmjs.org/@schematics/update/-/update-0.901.12.tgz", + "integrity": "sha512-SxGVYLTHhBC0rSF0OWSWPuJUB1Jhfqkl3o5bBgCC9//DutWiN6WoCCBTrCxR7F5vR2iiD7WqOe9CuvWYfvV8oQ==", "dev": true, "requires": { - "@angular-devkit/core": "8.3.18", - "@angular-devkit/schematics": "8.3.18", + "@angular-devkit/core": "9.1.12", + "@angular-devkit/schematics": "9.1.12", "@yarnpkg/lockfile": "1.1.0", "ini": "1.3.5", - "pacote": "9.5.5", - "rxjs": "6.4.0", - "semver": "6.3.0", + "npm-package-arg": "^8.0.0", + "pacote": "9.5.12", + "rxjs": "6.5.4", + "semver": "7.1.3", "semver-intersect": "1.4.0" }, "dependencies": { "rxjs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.4.0.tgz", - "integrity": "sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz", + "integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==", "dev": true, "requires": { "tslib": "^1.9.0" } }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.1.3.tgz", + "integrity": "sha512-ekM0zfiA9SCBlsKa2X1hxyxiI4L3B6EbVJkkdgQXnSEEaHlGdvyodMruTiulSRWMMB4NeIuYNMC9rTKTz97GxA==", "dev": true } } }, - "@types/events": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", - "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", "dev": true }, "@types/glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", - "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", "dev": true, "requires": { - "@types/events": "*", "@types/minimatch": "*", "@types/node": "*" } @@ -2075,6 +2933,12 @@ "@types/jasmine": "*" } }, + "@types/json-schema": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", + "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", + "dev": true + }, "@types/minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", @@ -2106,9 +2970,9 @@ "dev": true }, "@types/webpack-sources": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.5.tgz", - "integrity": "sha512-zfvjpp7jiafSmrzJ2/i3LqOyTYTuJ7u1KOXlKgDlvsj9Rr0x7ZiYu5lZbXwobL7lmsRNtPXlBfmaUD8eU2Hu8w==", + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-0.1.8.tgz", + "integrity": "sha512-JHB2/xZlXOjzjBB6fMOpH1eQAfsrpqVVIbneE0Rok16WXwFaznaI5vfg75U5WgGJm7V9W1c4xeRQDjX/zwvghA==", "dev": true, "requires": { "@types/node": "*", @@ -2339,9 +3203,9 @@ } }, "acorn": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz", - "integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==", + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.1.tgz", + "integrity": "sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA==", "dev": true }, "adm-zip": { @@ -2374,6 +3238,16 @@ "humanize-ms": "^1.2.1" } }, + "aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, "ajv": { "version": "6.9.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.9.1.tgz", @@ -2393,15 +3267,15 @@ "dev": true }, "ajv-keywords": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", - "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "dev": true }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "alphanum-sort": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", + "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", "dev": true }, "ansi-colors": { @@ -2411,12 +3285,12 @@ "dev": true }, "ansi-escapes": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.2.1.tgz", - "integrity": "sha512-Cg3ymMAdN10wOk/VYfLV7KCQyv7EDirJ64500sU7n9UlmioEtDuU5Gd+hj73hXSU/ex7tHJSssmyftDdkMLO8Q==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", + "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", "dev": true, "requires": { - "type-fest": "^0.5.2" + "type-fest": "^0.11.0" } }, "ansi-html": { @@ -2569,14 +3443,23 @@ } }, "asn1.js": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", - "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", "dev": true, "requires": { "bn.js": "^4.0.0", "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0" + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } } }, "assert": { @@ -2658,18 +3541,18 @@ "dev": true }, "autoprefixer": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.6.1.tgz", - "integrity": "sha512-aVo5WxR3VyvyJxcJC3h4FKfwCQvQWb1tSI5VHNibddCVWrcD1NvlxEweg3TSgiPztMnWfjpy2FURKA2kvDE+Tw==", + "version": "9.7.4", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.7.4.tgz", + "integrity": "sha512-g0Ya30YrMBAEZk60lp+qfX5YQllG+S5W3GYCFvyHTvhOki0AEQJLPEcIuGRsqVwLi8FvXPVtwTGhfr38hVpm0g==", "dev": true, "requires": { - "browserslist": "^4.6.3", - "caniuse-lite": "^1.0.30000980", + "browserslist": "^4.8.3", + "caniuse-lite": "^1.0.30001020", "chalk": "^2.4.2", "normalize-range": "^0.1.2", "num2fraction": "^1.2.2", - "postcss": "^7.0.17", - "postcss-value-parser": "^4.0.0" + "postcss": "^7.0.26", + "postcss-value-parser": "^4.0.2" } }, "aws-sign2": { @@ -2685,206 +3568,68 @@ "dev": true }, "axobject-query": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.1.2.tgz", - "integrity": "sha512-ICt34ZmrVt8UQnvPl6TVyDTkmhXmAyAT4Jh5ugfGUX4MOrZ+U/ZY6/sdylRw3qGNr9Ub5AJsaHeDMzNLehRdOQ==", - "dev": true + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.0.2.tgz", + "integrity": "sha512-MCeek8ZH7hKyO1rWUbKNQBbl4l2eY0ntk7OGi+q0RlafrCnfPxC06WZA+uebCfmYp4mNU9jRBP1AhGyf8+W3ww==", + "dev": true, + "requires": { + "ast-types-flow": "0.0.7" + } }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "babel-loader": { + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.6.tgz", + "integrity": "sha512-4BmWKtBOBm13uoUwd08UwjZlaw3O9GWf456R9j+5YykFZ6LUIjIKLc0zEZf+hauxPOJs96C8k6FvYD09vWzhYw==", "dev": true, "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" + "find-cache-dir": "^2.0.0", + "loader-utils": "^1.0.2", + "mkdirp": "^0.5.1", + "pify": "^4.0.1" }, "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" } }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "babel-generator": { - "version": "6.26.1", - "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", - "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", - "dev": true, - "requires": { - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "detect-indent": "^4.0.0", - "jsesc": "^1.3.0", - "lodash": "^4.17.4", - "source-map": "^0.5.7", - "trim-right": "^1.0.1" - }, - "dependencies": { - "jsesc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", - "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "babel-messages": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-dynamic-import-node": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", - "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==", - "dev": true, - "requires": { - "object.assign": "^4.1.0" - } - }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "dev": true, - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - }, - "dependencies": { - "core-js": { - "version": "2.6.10", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.10.tgz", - "integrity": "sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA==", - "dev": true - }, - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true - } - } - }, - "babel-template": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "lodash": "^4.17.4" - } - }, - "babel-traverse": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", - "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "debug": "^2.6.8", - "globals": "^9.18.0", - "invariant": "^2.2.2", - "lodash": "^4.17.4" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", "dev": true, "requires": { - "ms": "2.0.0" + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" } - }, - "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true } } }, - "babel-types": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", "dev": true, "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" - }, - "dependencies": { - "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true - } + "object.assign": "^4.1.0" } }, - "babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", - "dev": true - }, "backo2": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", @@ -3028,9 +3773,9 @@ "dev": true }, "bn.js": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.1.3.tgz", + "integrity": "sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ==", "dev": true }, "body-parser": { @@ -3094,6 +3839,12 @@ "multicast-dns-service-types": "^1.1.0" } }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, "bootstrap": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.2.1.tgz", @@ -3169,21 +3920,56 @@ "requires": { "bn.js": "^4.1.0", "randombytes": "^2.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } } }, "browserify-sign": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.0.4.tgz", - "integrity": "sha1-qk62jl17ZYuqa/alfmMMvXqT0pg=", - "dev": true, - "requires": { - "bn.js": "^4.1.1", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.2", - "elliptic": "^6.0.0", - "inherits": "^2.0.1", - "parse-asn1": "^5.0.0" + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dev": true, + "requires": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } } }, "browserify-zlib": { @@ -3196,14 +3982,15 @@ } }, "browserslist": { - "version": "4.6.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.6.6.tgz", - "integrity": "sha512-D2Nk3W9JL9Fp/gIcWei8LrERCS+eXu9AM5cfXA8WEZ84lFks+ARnZ0q/R69m2SV3Wjma83QDDPxsNKXUwdIsyA==", + "version": "4.14.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.5.tgz", + "integrity": "sha512-Z+vsCZIvCBvqLoYkBFTwEYH3v5MCQbsAjp50ERycpOjnPmolg1Gjy4+KaWWpm8QOJt9GHkhdqAl14NpCX73CWA==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30000984", - "electron-to-chromium": "^1.3.191", - "node-releases": "^1.1.25" + "caniuse-lite": "^1.0.30001135", + "electron-to-chromium": "^1.3.571", + "escalade": "^3.1.0", + "node-releases": "^1.1.61" } }, "browserstack": { @@ -3291,26 +4078,28 @@ "dev": true }, "cacache": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.2.tgz", - "integrity": "sha512-ifKgxH2CKhJEg6tNdAwziu6Q33EvuG26tYcda6PT3WKisZcYDXsnEdnRv67Po3yCzFfaSoMjGZzJyD2c3DT1dg==", + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.0.tgz", + "integrity": "sha512-L0JpXHhplbJSiDGzyJJnJCTL7er7NzbBgxzVqLswEb4bO91Zbv17OUMuUeu/q0ZwKn3V+1HM4wb9tO4eVE/K8g==", "dev": true, "requires": { - "bluebird": "^3.5.5", - "chownr": "^1.1.1", - "figgy-pudding": "^3.5.1", + "chownr": "^1.1.2", + "fs-minipass": "^2.0.0", "glob": "^7.1.4", - "graceful-fs": "^4.1.15", - "infer-owner": "^1.0.3", + "infer-owner": "^1.0.4", "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", "move-concurrently": "^1.0.1", + "p-map": "^3.0.0", "promise-inflight": "^1.0.1", - "rimraf": "^2.6.3", - "ssri": "^6.0.1", - "unique-filename": "^1.1.1", - "y18n": "^4.0.0" + "rimraf": "^2.7.1", + "ssri": "^8.0.0", + "tar": "^6.0.1", + "unique-filename": "^1.1.1" }, "dependencies": { "glob": { @@ -3326,6 +4115,21 @@ "once": "^1.3.0", "path-is-absolute": "^1.0.0" } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "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" + } } } }, @@ -3382,10 +4186,22 @@ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, + "caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, "caniuse-lite": { - "version": "1.0.30000989", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000989.tgz", - "integrity": "sha512-vrMcvSuMz16YY6GSVZ0dWDTJP8jqk3iFQ/Aq5iqblPwxSVVZI+zxDyTX0VPqtQsDnfdrBDcsmhgTEOh5R8Lbpw==", + "version": "1.0.30001137", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001137.tgz", + "integrity": "sha512-54xKQZTqZrKVHmVz0+UvdZR6kQc7pJDgfhsMYDG19ID1BWoNnDMFm5Q3uSBSU401pBvKYMsHAt9qhEDcxmk8aw==", "dev": true }, "canonical-path": { @@ -3445,9 +4261,9 @@ } }, "chownr": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.3.tgz", - "integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", "dev": true }, "chrome-trace-event": { @@ -3498,22 +4314,11 @@ } } }, - "clean-css": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", - "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==", - "dev": true, - "requires": { - "source-map": "~0.6.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 - } - } + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true }, "cli-cursor": { "version": "3.1.0", @@ -3524,36 +4329,42 @@ "restore-cursor": "^3.1.0" } }, + "cli-spinners": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.4.0.tgz", + "integrity": "sha512-sJAofoarcm76ZGpuooaO0eDy8saEy+YoZBLjC4h8srt4jeBnkYeOgqxgsJQTpyt2LjI5PTfLJHSL+41Yu4fEJA==", + "dev": true + }, "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", "dev": true }, "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", "dev": true, "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" }, "dependencies": { "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^4.1.0" } } } @@ -3575,27 +4386,34 @@ "shallow-clone": "^3.0.0" } }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true + "coa": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", + "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", + "dev": true, + "requires": { + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" + }, + "dependencies": { + "@types/q": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz", + "integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==", + "dev": true + } + } }, "codelyzer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-5.0.1.tgz", - "integrity": "sha512-UVV76+/y1RwaxzCeGPFE3G4GFtfV42r3x8EmRd7XMNFLlLC0ewdtCqWTbvhwPQMxFZZ+OTLEOJNWfyPPn3QFWg==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/codelyzer/-/codelyzer-5.2.2.tgz", + "integrity": "sha512-jB4FZ1Sx7kZhvZVdf+N2BaKTdrrNZOL0Bj10RRfrhHrb3zEvXjJvvq298JPMJAiyiCS/v4zs1QlGU0ip7xGqeA==", "dev": true, "requires": { - "app-root-path": "^2.1.0", + "app-root-path": "^2.2.1", "aria-query": "^3.0.0", - "axobject-query": "^2.0.2", + "axobject-query": "2.0.2", "css-selector-tokenizer": "^0.7.1", "cssauron": "^1.4.0", "damerau-levenshtein": "^1.0.4", @@ -3628,6 +4446,16 @@ "object-visit": "^1.0.0" } }, + "color": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/color/-/color-3.1.2.tgz", + "integrity": "sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg==", + "dev": true, + "requires": { + "color-convert": "^1.9.1", + "color-string": "^1.5.2" + } + }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -3643,6 +4471,16 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, + "color-string": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", + "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", + "dev": true, + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, "colors": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", @@ -3695,12 +4533,20 @@ "dev": true }, "compressible": { - "version": "2.0.17", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.17.tgz", - "integrity": "sha512-BGHeLCK1GV7j1bSmQQAi26X+GgWcTjLr/0tzSvMCl3LH1w1IJ4PFSPoV5316b30cneTziC+B1a+3OjoSUcQYmw==", + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", "dev": true, "requires": { - "mime-db": ">= 1.40.0 < 2" + "mime-db": ">= 1.43.0 < 2" + }, + "dependencies": { + "mime-db": { + "version": "1.45.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz", + "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==", + "dev": true + } } }, "compression": { @@ -3857,57 +4703,54 @@ "dev": true }, "copy-webpack-plugin": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-5.0.4.tgz", - "integrity": "sha512-YBuYGpSzoCHSSDGyHy6VJ7SHojKp6WHT4D7ItcQFNAYx2hrwkMe56e97xfVR0/ovDuMTrMffXUiltvQljtAGeg==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-6.0.3.tgz", + "integrity": "sha512-q5m6Vz4elsuyVEIUXr7wJdIdePWTubsqVbEMvf1WQnHGv0Q+9yPRu7MtYFPt+GBOXRav9lvIINifTQ1vSCs+eA==", "dev": true, "requires": { - "cacache": "^11.3.3", - "find-cache-dir": "^2.1.0", - "glob-parent": "^3.1.0", - "globby": "^7.1.1", - "is-glob": "^4.0.1", - "loader-utils": "^1.2.3", - "minimatch": "^3.0.4", + "cacache": "^15.0.4", + "fast-glob": "^3.2.4", + "find-cache-dir": "^3.3.1", + "glob-parent": "^5.1.1", + "globby": "^11.0.1", + "loader-utils": "^2.0.0", "normalize-path": "^3.0.0", - "p-limit": "^2.2.0", - "schema-utils": "^1.0.0", - "serialize-javascript": "^1.7.0", - "webpack-log": "^2.0.0" + "p-limit": "^3.0.1", + "schema-utils": "^2.7.0", + "serialize-javascript": "^4.0.0", + "webpack-sources": "^1.4.3" }, "dependencies": { "cacache": { - "version": "11.3.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-11.3.3.tgz", - "integrity": "sha512-p8WcneCytvzPxhDvYp31PD039vi77I12W+/KfR9S8AZbaiARFBCpsPJS+9uhWfeBfeAtW7o/4vt3MUqLkbY6nA==", + "version": "15.0.5", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.5.tgz", + "integrity": "sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==", "dev": true, "requires": { - "bluebird": "^3.5.5", - "chownr": "^1.1.1", - "figgy-pudding": "^3.5.1", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", "glob": "^7.1.4", - "graceful-fs": "^4.1.15", - "lru-cache": "^5.1.1", - "mississippi": "^3.0.0", - "mkdirp": "^0.5.1", - "move-concurrently": "^1.0.1", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", "promise-inflight": "^1.0.1", - "rimraf": "^2.6.3", - "ssri": "^6.0.1", - "unique-filename": "^1.1.1", - "y18n": "^4.0.0" + "rimraf": "^3.0.2", + "ssri": "^8.0.0", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" } }, - "find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - } + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true }, "glob": { "version": "7.1.6", @@ -3922,6 +4765,48 @@ "once": "^1.3.0", "path-is-absolute": "^1.0.0" } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "p-limit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz", + "integrity": "sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } } } }, @@ -3931,36 +4816,19 @@ "integrity": "sha512-KX/dnuY/J8FtEwbnrzmAjUYgLqtk+cxM86hfG60LGiW3MmltIc2yAmDgBgEkfm0blZhUrdr1Zd84J2Y14mLxzg==" }, "core-js-compat": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.4.1.tgz", - "integrity": "sha512-YdeJI26gLc0CQJ9asLE5obEgBz2I0+CIgnoTbS2T0d5IPQw/OCgCIFR527RmpduxjrB3gSEHoGOCTq9sigOyfw==", + "version": "3.6.5", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.5.tgz", + "integrity": "sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng==", "dev": true, "requires": { - "browserslist": "^4.7.2", - "semver": "^6.3.0" + "browserslist": "^4.8.5", + "semver": "7.0.0" }, "dependencies": { - "browserslist": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.7.2.tgz", - "integrity": "sha512-uZavT/gZXJd2UTi9Ov7/Z340WOSQ3+m1iBVRUknf+okKxonL9P83S3ctiBDtuRmRu8PiCHjqyueqQ9HYlJhxiw==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001004", - "electron-to-chromium": "^1.3.295", - "node-releases": "^1.1.38" - } - }, - "caniuse-lite": { - "version": "1.0.30001008", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001008.tgz", - "integrity": "sha512-b8DJyb+VVXZGRgJUa30cbk8gKHZ3LOZTBLaUEEVr2P4xpmFigOCc62CO4uzquW641Ouq1Rm9N+rWLWdSYDaDIw==", - "dev": true - }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", "dev": true } } @@ -3984,16 +4852,24 @@ } }, "create-ecdh": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz", - "integrity": "sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", "dev": true, "requires": { "bn.js": "^4.1.0", - "elliptic": "^6.0.0" - } - }, - "create-hash": { + "elliptic": "^6.5.3" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "create-hash": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", @@ -4052,23 +4928,152 @@ "randomfill": "^1.0.3" } }, + "css": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", + "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "source-map": "^0.6.1", + "source-map-resolve": "^0.5.2", + "urix": "^0.1.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 + } + } + }, + "css-color-names": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", + "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", + "dev": true + }, + "css-declaration-sorter": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz", + "integrity": "sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==", + "dev": true, + "requires": { + "postcss": "^7.0.1", + "timsort": "^0.3.0" + } + }, + "css-loader": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.5.1.tgz", + "integrity": "sha512-0G4CbcZzQ9D1Q6ndOfjFuMDo8uLYMu5vc9Abs5ztyHcKvmil6GJrMiNjzzi3tQvUF+mVRuDg7bE6Oc0Prolgig==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "cssesc": "^3.0.0", + "icss-utils": "^4.1.1", + "loader-utils": "^1.2.3", + "normalize-path": "^3.0.0", + "postcss": "^7.0.27", + "postcss-modules-extract-imports": "^2.0.0", + "postcss-modules-local-by-default": "^3.0.2", + "postcss-modules-scope": "^2.2.0", + "postcss-modules-values": "^3.0.0", + "postcss-value-parser": "^4.0.3", + "schema-utils": "^2.6.5", + "semver": "^6.3.0" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, "css-parse": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-1.7.0.tgz", - "integrity": "sha1-Mh9s9zeCpv91ERE5D8BeLGV9jJs=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", + "integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=", + "dev": true, + "requires": { + "css": "^2.0.0" + } + }, + "css-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", + "dev": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "css-select-base-adapter": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", + "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==", "dev": true }, "css-selector-tokenizer": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.2.tgz", - "integrity": "sha512-yj856NGuAymN6r8bn8/Jl46pR+OC3eEvAhfGYDUe7YPtTPAYrSSw4oAniZ9Y8T5B92hjhwTBLUen0/vKPxf6pw==", + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.3.tgz", + "integrity": "sha512-jWQv3oCEL5kMErj4wRnK/OPoBi0D+P1FR2cDCKYPaMeD2eW3/mttav8HT4hT1CKopiJI/psEULjkClhvJo4Lvg==", "dev": true, "requires": { "cssesc": "^3.0.0", - "fastparse": "^1.1.2", - "regexpu-core": "^4.6.0" + "fastparse": "^1.1.2" + } + }, + "css-tree": { + "version": "1.0.0-alpha.37", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", + "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", + "dev": true, + "requires": { + "mdn-data": "2.0.4", + "source-map": "^0.6.1" + }, + "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 + } } }, + "css-what": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.3.0.tgz", + "integrity": "sha512-pv9JPyatiPaQ6pf4OvD/dbfm0o5LviWmwxNWzblYf/1u9QZd0ihV+PMwy5jdQWQ3349kZmKEx9WXuSka2dM4cg==", + "dev": true + }, "cssauron": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/cssauron/-/cssauron-1.4.0.tgz", @@ -4084,6 +5089,116 @@ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true }, + "cssnano": { + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.10.tgz", + "integrity": "sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ==", + "dev": true, + "requires": { + "cosmiconfig": "^5.0.0", + "cssnano-preset-default": "^4.0.7", + "is-resolvable": "^1.0.0", + "postcss": "^7.0.0" + } + }, + "cssnano-preset-default": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz", + "integrity": "sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA==", + "dev": true, + "requires": { + "css-declaration-sorter": "^4.0.1", + "cssnano-util-raw-cache": "^4.0.1", + "postcss": "^7.0.0", + "postcss-calc": "^7.0.1", + "postcss-colormin": "^4.0.3", + "postcss-convert-values": "^4.0.1", + "postcss-discard-comments": "^4.0.2", + "postcss-discard-duplicates": "^4.0.2", + "postcss-discard-empty": "^4.0.1", + "postcss-discard-overridden": "^4.0.1", + "postcss-merge-longhand": "^4.0.11", + "postcss-merge-rules": "^4.0.3", + "postcss-minify-font-values": "^4.0.2", + "postcss-minify-gradients": "^4.0.2", + "postcss-minify-params": "^4.0.2", + "postcss-minify-selectors": "^4.0.2", + "postcss-normalize-charset": "^4.0.1", + "postcss-normalize-display-values": "^4.0.2", + "postcss-normalize-positions": "^4.0.2", + "postcss-normalize-repeat-style": "^4.0.2", + "postcss-normalize-string": "^4.0.2", + "postcss-normalize-timing-functions": "^4.0.2", + "postcss-normalize-unicode": "^4.0.1", + "postcss-normalize-url": "^4.0.1", + "postcss-normalize-whitespace": "^4.0.2", + "postcss-ordered-values": "^4.1.2", + "postcss-reduce-initial": "^4.0.3", + "postcss-reduce-transforms": "^4.0.2", + "postcss-svgo": "^4.0.2", + "postcss-unique-selectors": "^4.0.1" + } + }, + "cssnano-util-get-arguments": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz", + "integrity": "sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8=", + "dev": true + }, + "cssnano-util-get-match": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz", + "integrity": "sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0=", + "dev": true + }, + "cssnano-util-raw-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz", + "integrity": "sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "cssnano-util-same-parent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz", + "integrity": "sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q==", + "dev": true + }, + "csso": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.0.3.tgz", + "integrity": "sha512-NL3spysxUkcrOgnpsT4Xdl2aiEiBG6bXswAABQVHcMrfjjBisFOKwLDOmf4wf32aPdcJws1zds2B0Rg+jqMyHQ==", + "dev": true, + "requires": { + "css-tree": "1.0.0-alpha.39" + }, + "dependencies": { + "css-tree": { + "version": "1.0.0-alpha.39", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.39.tgz", + "integrity": "sha512-7UvkEYgBAHRG9Nt980lYxjsTrCyHFN53ky3wVsDkiMdVqylqRt+Zc+jm5qw7/qyOvN2dHSYtX0e4MbCCExSvnA==", + "dev": true, + "requires": { + "mdn-data": "2.0.6", + "source-map": "^0.6.1" + } + }, + "mdn-data": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.6.tgz", + "integrity": "sha512-rQvjv71olwNHgiTbfPZFkJtjNMciWgswYeciZhtvWLO8bmX3TnhyA62I6sTWOyZssWHJJjY6/KiWwqQsWWsqOA==", + "dev": true + }, + "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 + } + } + }, "custom-event": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/custom-event/-/custom-event-1.0.1.tgz", @@ -4177,6 +5292,23 @@ "strip-bom": "^3.0.0" } }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "requires": { + "clone": "^1.0.2" + }, + "dependencies": { + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + } + } + }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", @@ -4286,6 +5418,12 @@ "requires": { "path-is-inside": "^1.0.2" } + }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true } } }, @@ -4323,15 +5461,6 @@ "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", "dev": true }, - "detect-indent": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", - "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", - "dev": true, - "requires": { - "repeating": "^2.0.0" - } - }, "detect-node": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", @@ -4369,15 +5498,23 @@ "bn.js": "^4.1.0", "miller-rabin": "^4.0.0", "randombytes": "^2.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } } }, "dir-glob": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", - "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, "requires": { - "path-type": "^3.0.0" + "path-type": "^4.0.0" } }, "dns-equal": { @@ -4417,12 +5554,55 @@ "void-elements": "^2.0.0" } }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.2.tgz", + "integrity": "sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA==", + "dev": true + } + } + }, "domain-browser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", "dev": true }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "requires": { + "is-obj": "^2.0.0" + } + }, "duplexify": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", @@ -4452,15 +5632,15 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.306", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.306.tgz", - "integrity": "sha512-frDqXvrIROoYvikSKTIKbHbzO6M3/qC6kCIt/1FOa9kALe++c4VAJnwjSFvf1tYLEUsP2n9XZ4XSCyqc3l7A/A==", + "version": "1.3.574", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.574.tgz", + "integrity": "sha512-kF8Bfe1h8X1pPwlw6oRoIXj0DevowviP6fl0wcljm+nZjy/7+Fos4THo1N/7dVGEJlyEqK9C8qNnbheH+Eazfw==", "dev": true }, "elliptic": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.1.tgz", - "integrity": "sha512-xvJINNLbTeWQjrl6X+7eQCrIy/YPv5XCpKW6kB5mKvtnGILoLDcySuwomfdzt0BMdLNVnuRNTuzKNHj0bva1Cg==", + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz", + "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==", "dev": true, "requires": { "bn.js": "^4.4.0", @@ -4470,18 +5650,26 @@ "inherits": "^2.0.1", "minimalistic-assert": "^1.0.0", "minimalistic-crypto-utils": "^1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } } }, "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, "emojis-list": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", - "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", "dev": true }, "encodeurl": { @@ -4491,12 +5679,23 @@ "dev": true }, "encoding": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", - "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", "dev": true, "requires": { - "iconv-lite": "~0.4.13" + "iconv-lite": "^0.6.2" + }, + "dependencies": { + "iconv-lite": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", + "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + } } }, "end-of-stream": { @@ -4623,13 +5822,13 @@ } }, "enhanced-resolve": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz", - "integrity": "sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz", + "integrity": "sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA==", "dev": true, "requires": { "graceful-fs": "^4.1.2", - "memory-fs": "^0.4.0", + "memory-fs": "^0.5.0", "tapable": "^1.0.0" } }, @@ -4639,6 +5838,12 @@ "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", "dev": true }, + "entities": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.3.tgz", + "integrity": "sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==", + "dev": true + }, "err-code": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/err-code/-/err-code-1.1.2.tgz", @@ -4664,21 +5869,23 @@ } }, "es-abstract": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.0.tgz", - "integrity": "sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg==", + "version": "1.18.0-next.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.0.tgz", + "integrity": "sha512-elZXTZXKn51hUBdJjSZGYRujuzilgXo8vSPQzjGYXLvSlGiCo8VO8ZGV3kjo9a0WNJJ57hENagwbtlRuHuzkcQ==", "dev": true, "requires": { - "es-to-primitive": "^1.2.0", + "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.0", - "is-callable": "^1.1.4", - "is-regex": "^1.0.4", - "object-inspect": "^1.6.0", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", "object-keys": "^1.1.1", - "string.prototype.trimleft": "^2.1.0", - "string.prototype.trimright": "^2.1.0" + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" } }, "es-to-primitive": { @@ -4707,6 +5914,12 @@ "es6-promise": "^4.0.3" } }, + "escalade": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.0.tgz", + "integrity": "sha512-mAk+hPSO8fLDkhV7V0dXazH5pDc6MrjBTPyD3VeKzxnVFjH1MIxbCdqGZB9O8+EwWakZs3ZCbDS4IpRt79V1ig==", + "dev": true + }, "escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -4736,12 +5949,20 @@ "dev": true }, "esrecurse": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "requires": { - "estraverse": "^4.1.0" + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } } }, "estraverse": { @@ -4769,9 +5990,9 @@ "dev": true }, "events": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz", - "integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.2.0.tgz", + "integrity": "sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg==", "dev": true }, "eventsource": { @@ -5046,6 +6267,28 @@ "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", "dev": true }, + "fast-glob": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.4.tgz", + "integrity": "sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" + }, + "dependencies": { + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true + } + } + }, "fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", @@ -5058,6 +6301,15 @@ "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==", "dev": true }, + "fastq": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.8.0.tgz", + "integrity": "sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, "faye-websocket": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz", @@ -5068,52 +6320,28 @@ } }, "figgy-pudding": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.1.tgz", - "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", "dev": true }, "figures": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.1.0.tgz", - "integrity": "sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", "dev": true, "requires": { "escape-string-regexp": "^1.0.5" } }, "file-loader": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-4.2.0.tgz", - "integrity": "sha512-+xZnaK5R8kBJrHK0/6HRlrKNamvVS5rjyuju+rnyxRGuwUJwpAMsVzUl5dz6rK8brkzjV6JpcFNjp6NqV0g1OQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.0.0.tgz", + "integrity": "sha512-/aMOAYEFXDdjG0wytpTL5YQLfZnnTmLNjn+AIrJ/6HVnTfDqLsVKUUwkDf4I4kgex36BvjuXEn/TX9B/1ESyqQ==", "dev": true, "requires": { - "loader-utils": "^1.2.3", - "schema-utils": "^2.0.0" - }, - "dependencies": { - "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", - "dev": true, - "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "schema-utils": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.5.0.tgz", - "integrity": "sha512-32ISrwW2scPXHUSusP8qMg5dLUawKkyV+/qIEV9JdXKx+rsM6mi8vZY8khg2M69Qom16rtroWXD3Ybtiws38gQ==", - "dev": true, - "requires": { - "ajv": "^6.10.2", - "ajv-keywords": "^3.4.1" - } - } + "loader-utils": "^2.0.0", + "schema-utils": "^2.6.5" } }, "fileset": { @@ -5168,13 +6396,13 @@ } }, "find-cache-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.0.0.tgz", - "integrity": "sha512-t7ulV1fmbxh5G9l/492O1p5+EBbr3uwpt6odhFTMc+nWyhmbloe+ja9BZ8pIBtqFWhOmCWVjx+pTW4zDkFoclw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", + "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", "dev": true, "requires": { "commondir": "^1.0.1", - "make-dir": "^3.0.0", + "make-dir": "^3.0.2", "pkg-dir": "^4.1.0" }, "dependencies": { @@ -5198,9 +6426,9 @@ } }, "make-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.0.tgz", - "integrity": "sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, "requires": { "semver": "^6.0.0" @@ -5349,12 +6577,12 @@ } }, "fs-minipass": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "dev": true, "requires": { - "minipass": "^2.6.0" + "minipass": "^3.0.0" } }, "fs-write-stream-atomic": { @@ -5394,10 +6622,16 @@ "integrity": "sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA==", "dev": true }, + "gensync": { + "version": "1.0.0-beta.1", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", + "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", + "dev": true + }, "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, "get-stream": { @@ -5439,24 +6673,12 @@ } }, "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", "dev": true, "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } + "is-glob": "^4.0.1" } }, "globals": { @@ -5466,23 +6688,23 @@ "dev": true }, "globby": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", - "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.1.tgz", + "integrity": "sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ==", "dev": true, "requires": { - "array-union": "^1.0.1", - "dir-glob": "^2.0.0", - "glob": "^7.1.2", - "ignore": "^3.3.5", - "pify": "^3.0.0", - "slash": "^1.0.0" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" }, "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true } } @@ -5494,9 +6716,9 @@ "dev": true }, "handle-thing": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.0.tgz", - "integrity": "sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", "dev": true }, "handlebars": { @@ -5583,9 +6805,9 @@ "dev": true }, "has-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "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 }, "has-value": { @@ -5641,13 +6863,39 @@ } }, "hash-base": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", - "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", "dev": true, "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } } }, "hash.js": { @@ -5660,6 +6908,12 @@ "minimalistic-assert": "^1.0.1" } }, + "hex-color-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", + "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==", + "dev": true + }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -5672,10 +6926,24 @@ } }, "hosted-git-info": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz", - "integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==", - "dev": true + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.5.tgz", + "integrity": "sha512-i4dpK6xj9BIpVOTboXIlKG9+8HMKggcrMX7WA24xZtKwX0TPelq/rbaS5rCKeNX8sJXZJGdSxpnEGtta+wismQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + } + } }, "hpack.js": { "version": "2.1.6", @@ -5689,10 +6957,28 @@ "wbuf": "^1.1.0" } }, + "hsl-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsl-regex/-/hsl-regex-1.0.0.tgz", + "integrity": "sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4=", + "dev": true + }, + "hsla-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz", + "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=", + "dev": true + }, + "html-comment-regex": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz", + "integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==", + "dev": true + }, "html-entities": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz", - "integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.3.1.tgz", + "integrity": "sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA==", "dev": true }, "http-cache-semantics": { @@ -5720,12 +7006,6 @@ "toidentifier": "1.0.0" } }, - "http-parser-js": { - "version": "0.4.10", - "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.10.tgz", - "integrity": "sha1-ksnBN0w1CF912zWexWzCV8u5P6Q=", - "dev": true - }, "http-proxy": { "version": "1.18.0", "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.0.tgz", @@ -5774,6 +7054,111 @@ "is-glob": "^4.0.0", "lodash": "^4.17.11", "micromatch": "^3.1.10" + }, + "dependencies": { + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "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": { + "is-buffer": "^1.1.5" + } + } + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } } }, "http-signature": { @@ -5838,6 +7223,15 @@ "safer-buffer": ">= 2.1.2 < 3" } }, + "icss-utils": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", + "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", + "dev": true, + "requires": { + "postcss": "^7.0.14" + } + }, "ieee754": { "version": "1.1.13", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", @@ -5851,9 +7245,9 @@ "dev": true }, "ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", "dev": true }, "ignore-walk": { @@ -5922,6 +7316,18 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", + "dev": true + }, "indexof": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", @@ -5957,23 +7363,23 @@ "dev": true }, "inquirer": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.1.tgz", - "integrity": "sha512-uxNHBeQhRXIoHWTSNYUFhQVrHYFThIt6IVo2fFmSe8aBwdR3/w6b58hJpiL/fMukFkvGzjg+hSxFtwvVmKZmXw==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.1.0.tgz", + "integrity": "sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg==", "dev": true, "requires": { "ansi-escapes": "^4.2.1", - "chalk": "^2.4.2", + "chalk": "^3.0.0", "cli-cursor": "^3.1.0", "cli-width": "^2.0.0", "external-editor": "^3.0.3", "figures": "^3.0.0", "lodash": "^4.17.15", "mute-stream": "0.0.8", - "run-async": "^2.2.0", - "rxjs": "^6.4.0", + "run-async": "^2.4.0", + "rxjs": "^6.5.3", "string-width": "^4.1.0", - "strip-ansi": "^5.1.0", + "strip-ansi": "^6.0.0", "through": "^2.3.6" }, "dependencies": { @@ -5983,6 +7389,53 @@ "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -5998,34 +7451,24 @@ "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.0" - }, - "dependencies": { - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - } } }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", "dev": true, "requires": { - "ansi-regex": "^4.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - } + "ansi-regex": "^5.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" } } } @@ -6049,12 +7492,6 @@ "loose-envify": "^1.0.0" } }, - "invert-kv": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz", - "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", - "dev": true - }, "ip": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", @@ -6068,15 +7505,15 @@ "dev": true }, "ipaddr.js": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", - "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "dev": true }, "is-absolute-url": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", - "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", + "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", "dev": true }, "is-accessor-descriptor": { @@ -6127,11 +7564,25 @@ "dev": true }, "is-callable": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", + "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", "dev": true }, + "is-color-stop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz", + "integrity": "sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=", + "dev": true, + "requires": { + "css-color-names": "^0.0.4", + "hex-color-regex": "^1.1.0", + "hsl-regex": "^1.0.0", + "hsla-regex": "^1.0.0", + "rgb-regex": "^1.0.1", + "rgba-regex": "^1.0.0" + } + }, "is-data-descriptor": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", @@ -6153,9 +7604,9 @@ } }, "is-date-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", "dev": true }, "is-descriptor": { @@ -6183,6 +7634,12 @@ "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", "dev": true }, + "is-docker": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.1.1.tgz", + "integrity": "sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==", + "dev": true + }, "is-extendable": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", @@ -6195,15 +7652,6 @@ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, - "is-finite": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", @@ -6219,12 +7667,30 @@ "is-extglob": "^2.1.1" } }, + "is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true + }, + "is-negative-zero": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", + "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", + "dev": true + }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true + }, "is-path-cwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", @@ -6264,34 +7730,43 @@ "isobject": "^3.0.1" } }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", - "dev": true - }, "is-regex": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", - "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", "dev": true, "requires": { - "has": "^1.0.1" + "has-symbols": "^1.0.1" } }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, + "is-svg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-3.0.0.tgz", + "integrity": "sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ==", + "dev": true, + "requires": { + "html-comment-regex": "^1.1.0" + } + }, "is-symbol": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", - "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "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.0" + "has-symbols": "^1.0.1" } }, "is-typedarray": { @@ -6307,10 +7782,13 @@ "dev": true }, "is-wsl": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", - "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", - "dev": true + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + } }, "isarray": { "version": "1.0.0", @@ -6395,57 +7873,10 @@ } } }, - "istanbul-instrumenter-loader": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-instrumenter-loader/-/istanbul-instrumenter-loader-3.0.1.tgz", - "integrity": "sha512-a5SPObZgS0jB/ixaKSMdn6n/gXSrK2S6q/UfRJBT3e6gQmVjwZROTODQsYW5ZNwOu78hG62Y3fWlebaVOL0C+w==", - "dev": true, - "requires": { - "convert-source-map": "^1.5.0", - "istanbul-lib-instrument": "^1.7.3", - "loader-utils": "^1.1.0", - "schema-utils": "^0.3.0" - }, - "dependencies": { - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true, - "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" - } - }, - "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", - "dev": true - }, - "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true - }, - "schema-utils": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz", - "integrity": "sha1-9YdyIs4+kx7a4DnxfrNxbnE3+M8=", - "dev": true, - "requires": { - "ajv": "^5.0.0" - } - } - } - }, "istanbul-lib-coverage": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz", - "integrity": "sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", + "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", "dev": true }, "istanbul-lib-hook": { @@ -6458,18 +7889,23 @@ } }, "istanbul-lib-instrument": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz", - "integrity": "sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", + "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", "dev": true, "requires": { - "babel-generator": "^6.18.0", - "babel-template": "^6.16.0", - "babel-traverse": "^6.18.0", - "babel-types": "^6.18.0", - "babylon": "^6.18.0", - "istanbul-lib-coverage": "^1.2.1", - "semver": "^5.3.0" + "@babel/core": "^7.7.5", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, "istanbul-lib-report": { @@ -6577,32 +8013,32 @@ "dev": true }, "jest-worker": { - "version": "24.9.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", - "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", + "version": "25.1.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-25.1.0.tgz", + "integrity": "sha512-ZHhHtlxOWSxCoNOKHGbiLzXnl42ga9CxDr27H36Qn+15pQZd3R/F24jrmjDelw9j/iHUIWMWs08/u2QN50HHOg==", "dev": true, "requires": { "merge-stream": "^2.0.0", - "supports-color": "^6.1.0" + "supports-color": "^7.0.0" }, "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" } } } }, - "js-levenshtein": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", - "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", - "dev": true - }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -6637,6 +8073,12 @@ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", @@ -6662,12 +8104,20 @@ "dev": true }, "json5": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", - "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", "dev": true, "requires": { - "minimist": "^1.2.0" + "minimist": "^1.2.5" + }, + "dependencies": { + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + } } }, "jsonfile": { @@ -6807,35 +8257,27 @@ "dev": true }, "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true }, - "lcid": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz", - "integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==", - "dev": true, - "requires": { - "invert-kv": "^2.0.0" - } - }, "less": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/less/-/less-3.9.0.tgz", - "integrity": "sha512-31CmtPEZraNUtuUREYjSqRkeETFdyEHSEPAGq4erDlUXtda7pzNmctdljdIagSb589d/qXGWiiP31R5JVf+v0w==", + "version": "3.11.3", + "resolved": "https://registry.npmjs.org/less/-/less-3.11.3.tgz", + "integrity": "sha512-VkZiTDdtNEzXA3LgjQiC3D7/ejleBPFVvq+aRI9mIj+Zhmif5TvFPM244bT4rzkvOCvJ9q4zAztok1M7Nygagw==", "dev": true, "requires": { "clone": "^2.1.2", "errno": "^0.1.1", "graceful-fs": "^4.1.2", "image-size": "~0.5.0", + "make-dir": "^2.1.0", "mime": "^1.4.1", - "mkdirp": "^0.5.0", "promise": "^7.1.1", "request": "^2.83.0", - "source-map": "~0.6.0" + "source-map": "~0.6.0", + "tslib": "^1.10.0" }, "dependencies": { "source-map": { @@ -6856,12 +8298,49 @@ "clone": "^2.1.1", "loader-utils": "^1.1.0", "pify": "^4.0.1" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + } + } + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true + }, + "levenary": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/levenary/-/levenary-1.1.1.tgz", + "integrity": "sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ==", + "dev": true, + "requires": { + "leven": "^3.1.0" } }, "license-webpack-plugin": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-2.1.2.tgz", - "integrity": "sha512-7poZHRla+ae0eEButlwMrPpkXyhNVBf2EHePYWT0jyLnI6311/OXJkTI2sOIRungRpQgU2oDMpro5bSFPT5F0A==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/license-webpack-plugin/-/license-webpack-plugin-2.1.4.tgz", + "integrity": "sha512-1Xq72fmPbTg5KofXs+yI5L4QqPFjQ6mZxoeI6D7gfiEDOtaEIk6PGrdLaej90bpDqKNHNxlQ/MW4tMAL6xMPJQ==", "dev": true, "requires": { "@types/webpack-sources": "^0.1.5", @@ -6884,14 +8363,14 @@ "dev": true }, "loader-utils": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.2.3.tgz", - "integrity": "sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz", + "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==", "dev": true, "requires": { "big.js": "^5.2.2", - "emojis-list": "^2.0.0", - "json5": "^1.0.1" + "emojis-list": "^3.0.0", + "json5": "^2.1.2" } }, "locate-path": { @@ -6916,6 +8395,27 @@ "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", "dev": true }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "dev": true + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", + "dev": true + }, + "log-symbols": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", + "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2" + } + }, "log4js": { "version": "4.5.1", "resolved": "https://registry.npmjs.org/log4js/-/log4js-4.5.1.tgz", @@ -6930,9 +8430,9 @@ } }, "loglevel": { - "version": "1.6.6", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.6.tgz", - "integrity": "sha512-Sgr5lbboAUBo3eXCSPL4/KoVz3ROKquOjcctxmHIt+vol2DrqTQe3SwkKKuYhEiWB5kYa13YyopJ69deJ1irzQ==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.0.tgz", + "integrity": "sha512-i2sY04nal5jDcagM3FMfG++T69GEEM8CYuOfeOIvmXzOIcwE9a/CJPR0MFM97pYMj/u10lzz7/zd7+qwhrBTqQ==", "dev": true }, "loose-envify": { @@ -6951,12 +8451,20 @@ "dev": true, "requires": { "yallist": "^3.0.2" + }, + "dependencies": { + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } } }, "magic-string": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.3.tgz", - "integrity": "sha512-6QK0OpF/phMz0Q2AxILkX2mFhi7m+WMwTRg0LQKq/WBB0cDP4rYH3Wp4/d3OTXlrPLVJT/RFqj8tFeAR4nk8AA==", + "version": "0.25.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", + "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", "dev": true, "requires": { "sourcemap-codec": "^1.4.4" @@ -6979,9 +8487,9 @@ "dev": true }, "make-fetch-happen": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-5.0.1.tgz", - "integrity": "sha512-b4dfaMvUDR67zxUq1+GN7Ke9rH5WvGRmoHuMH7l+gmUCR2tCXFP6mpeJ9Dp+jB6z8mShRopSf1vLRBhRs8Cu5w==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-5.0.2.tgz", + "integrity": "sha512-07JHC0r1ykIoruKO8ifMXu+xEU8qOXDFETylktdug6vJDACnP+HKevOu3PXyNPzFyTSlz8vrBYlBO1JZRe8Cag==", "dev": true, "requires": { "agentkeepalive": "^3.4.1", @@ -7006,6 +8514,29 @@ "es6-promisify": "^5.0.0" } }, + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, "debug": { "version": "3.2.6", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", @@ -7015,6 +8546,20 @@ "ms": "^2.1.1" } }, + "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" + } + }, "https-proxy-agent": { "version": "2.2.4", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz", @@ -7024,6 +8569,15 @@ "agent-base": "^4.3.0", "debug": "^3.1.0" } + }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } } } }, @@ -7033,15 +8587,6 @@ "integrity": "sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA==", "dev": true }, - "map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "dev": true, - "requires": { - "p-defer": "^1.0.0" - } - }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", @@ -7068,27 +8613,22 @@ "safe-buffer": "^5.1.2" } }, + "mdn-data": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", + "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==", + "dev": true + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", "dev": true }, - "mem": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz", - "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", - "dev": true, - "requires": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" - } - }, "memory-fs": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", - "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", "dev": true, "requires": { "errno": "^0.1.3", @@ -7101,12 +8641,35 @@ "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", "dev": true }, + "merge-source-map": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", + "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", + "dev": true, + "requires": { + "source-map": "^0.6.1" + }, + "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 + } + } + }, "merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -7114,159 +8677,117 @@ "dev": true }, "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", "dev": true, "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" }, "dependencies": { - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "mime-db": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", + "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", + "dev": true + }, + "mime-types": { + "version": "2.1.24", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", + "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "dev": true, + "requires": { + "mime-db": "1.40.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "mini-css-extract-plugin": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz", + "integrity": "sha512-lp3GeY7ygcgAmVIcRPBVhIkf8Us7FZjA+ILpal44qLdSu11wmjKQ3d9k15lfD7pO4esu9eUIAW7qiYIBppv40A==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "normalize-url": "1.9.1", + "schema-utils": "^1.0.0", + "webpack-sources": "^1.1.0" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "dev": true, "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "minimist": "^1.2.0" } }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" } }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "normalize-url": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", + "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", "dev": true, "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "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": { - "is-buffer": "^1.1.5" - } - } + "object-assign": "^4.0.1", + "prepend-http": "^1.0.0", + "query-string": "^4.1.0", + "sort-keys": "^1.0.0" } }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", "dev": true, "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" } } } }, - "miller-rabin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", - "dev": true, - "requires": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" - } - }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", - "dev": true - }, - "mime-db": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", - "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", - "dev": true - }, - "mime-types": { - "version": "2.1.24", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", - "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", - "dev": true, - "requires": { - "mime-db": "1.40.0" - } - }, - "mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true - }, - "mini-css-extract-plugin": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.8.0.tgz", - "integrity": "sha512-MNpRGbNA52q6U92i0qbVpQNsgk7LExy41MdAlG84FeytfDOtRIf/mCHdEgG8rpTKOaNKiqUnZdlptF469hxqOw==", - "dev": true, - "requires": { - "loader-utils": "^1.1.0", - "normalize-url": "1.9.1", - "schema-utils": "^1.0.0", - "webpack-sources": "^1.1.0" - } - }, "minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -7295,22 +8816,49 @@ "dev": true }, "minipass": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.3.tgz", + "integrity": "sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==", "dev": true, "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" + "yallist": "^4.0.0" + } + }, + "minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dev": true, + "requires": { + "minipass": "^3.0.0" + } + }, + "minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dev": true, + "requires": { + "minipass": "^3.0.0" } }, "minizlib": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "dev": true, "requires": { - "minipass": "^2.9.0" + "minipass": "^3.0.0", + "yallist": "^4.0.0" } }, "mississippi": { @@ -7411,13 +8959,6 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, - "nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", - "dev": true, - "optional": true - }, "nanomatch": { "version": "1.2.13", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", @@ -7456,9 +8997,9 @@ "dev": true }, "node-fetch-npm": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz", - "integrity": "sha512-nJIxm1QmAj4v3nfCvEeCrYSoVwXyxLnaPBK5W1W5DGEJwjlKuC2VEUycGw5oxk+4zZahRrB84PUJJgEmhFTDFw==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/node-fetch-npm/-/node-fetch-npm-2.0.4.tgz", + "integrity": "sha512-iOuIQDWDyjhv9qSDrj9aq/klt6F9z1p2otB3AV7v3zBDcL/x+OfGsvGQZZCcMZbUf4Ujw1xGNQkjvGnVT22cKg==", "dev": true, "requires": { "encoding": "^0.1.11", @@ -7467,9 +9008,9 @@ } }, "node-forge": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.0.tgz", - "integrity": "sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", + "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", "dev": true }, "node-libs-browser": { @@ -7512,21 +9053,10 @@ } }, "node-releases": { - "version": "1.1.39", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.39.tgz", - "integrity": "sha512-8MRC/ErwNCHOlAFycy9OPca46fQYUjbJRDcZTHVWIGXIjYLM73k70vv3WkYutVnM4cCo4hE0MqBVVZjP6vjISA==", - "dev": true, - "requires": { - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } + "version": "1.1.61", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.61.tgz", + "integrity": "sha512-DD5vebQLg8jLCOzwupn954fbIiZht05DAZs0k2u8NStSe6h9XdsuIQL8hSRKYiU8WUQRznmSDrKGbv3ObOmC7g==", + "dev": true }, "normalize-package-data": { "version": "2.5.0", @@ -7538,6 +9068,14 @@ "resolve": "^1.10.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" + }, + "dependencies": { + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + } } }, "normalize-path": { @@ -7553,60 +9091,96 @@ "dev": true }, "normalize-url": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", - "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", + "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==", + "dev": true + }, + "npm-bundled": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", + "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", "dev": true, "requires": { - "object-assign": "^4.0.1", - "prepend-http": "^1.0.0", - "query-string": "^4.1.0", - "sort-keys": "^1.0.0" + "npm-normalize-package-bin": "^1.0.1" } }, - "npm-bundled": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.6.tgz", - "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==", + "npm-install-checks": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-4.0.0.tgz", + "integrity": "sha512-09OmyDkNLYwqKPOnbI8exiOZU2GVVmQp7tgez2BPi5OZC8M82elDAps7sxC4l//uSUtotWqoEIDwjRvWH4qz8w==", + "dev": true, + "requires": { + "semver": "^7.1.1" + }, + "dependencies": { + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + } + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==", "dev": true }, "npm-package-arg": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.0.tgz", - "integrity": "sha512-zYbhP2k9DbJhA0Z3HKUePUgdB1x7MfIfKssC+WLPFMKTBZKpZh5m13PgexJjCq6KW7j17r0jHWcCpxEqnnncSA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-8.0.1.tgz", + "integrity": "sha512-/h5Fm6a/exByzFSTm7jAyHbgOqErl9qSNJDQF32Si/ZzgwT2TERVxRxn3Jurw1wflgyVVAxnFR4fRHPM7y1ClQ==", "dev": true, "requires": { - "hosted-git-info": "^2.6.0", - "osenv": "^0.1.5", - "semver": "^5.5.0", + "hosted-git-info": "^3.0.2", + "semver": "^7.0.0", "validate-npm-package-name": "^3.0.0" + }, + "dependencies": { + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + } } }, "npm-packlist": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.6.tgz", - "integrity": "sha512-u65uQdb+qwtGvEJh/DgQgW1Xg7sqeNbmxYyrvlNznaVTjV3E5P6F/EFjM+BVHXl7JJlsdG8A64M0XI8FI/IOlg==", + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", + "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", "dev": true, "requires": { "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" } }, "npm-pick-manifest": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-3.0.2.tgz", - "integrity": "sha512-wNprTNg+X5nf+tDi+hbjdHhM4bX+mKqv6XmPh7B5eG+QY9VARfQPfCEH013H5GqfNj6ee8Ij2fg8yk0mzps1Vw==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-6.0.0.tgz", + "integrity": "sha512-PdJpXMvjqt4nftNEDpCgjBUF8yI3Q3MyuAmVB9nemnnCg32F4BPL/JFBfdj8DubgHCYUFQhtLWmBPvdsFtjWMg==", "dev": true, "requires": { - "figgy-pudding": "^3.5.1", - "npm-package-arg": "^6.0.0", - "semver": "^5.4.1" + "npm-install-checks": "^4.0.0", + "npm-package-arg": "^8.0.0", + "semver": "^7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + } } }, "npm-registry-fetch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-4.0.2.tgz", - "integrity": "sha512-Z0IFtPEozNdeZRPh3aHHxdG+ZRpzcbQaJLthsm3VhNf6DScicTFRHZzK82u8RsJUsUHkX+QH/zcB/5pmd20H4A==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-4.0.7.tgz", + "integrity": "sha512-cny9v0+Mq6Tjz+e0erFAB+RYJ/AVGzkjnISiobqP8OWj9c9FLoZZu8/SPSKJWE17F1tk4018wfjV+ZbIbqC7fQ==", "dev": true, "requires": { "JSONStream": "^1.3.4", @@ -7618,10 +9192,28 @@ "safe-buffer": "^5.2.0" }, "dependencies": { + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "npm-package-arg": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz", + "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", + "dev": true, + "requires": { + "hosted-git-info": "^2.7.1", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" + } + }, "safe-buffer": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true } } @@ -7635,18 +9227,21 @@ "path-key": "^2.0.0" } }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "dev": true, + "requires": { + "boolbase": "~1.0.0" + } + }, "num2fraction": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", "dev": true }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", @@ -7697,16 +9292,41 @@ } }, "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==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", "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 + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.2.tgz", + "integrity": "sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "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.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } }, "object-keys": { "version": "1.1.1", @@ -7724,25 +9344,46 @@ } }, "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", + "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", "dev": true, "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.0", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" } }, "object.getownpropertydescriptors": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", - "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", + "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", "dev": true, "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.5.1" + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "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.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } } }, "object.pick": { @@ -7754,6 +9395,39 @@ "isobject": "^3.0.1" } }, + "object.values": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz", + "integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1", + "function-bind": "^1.1.1", + "has": "^1.0.3" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "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.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, "obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", @@ -7785,21 +9459,22 @@ } }, "onetime": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", - "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, "requires": { "mimic-fn": "^2.1.0" } }, "open": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/open/-/open-6.4.0.tgz", - "integrity": "sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==", + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/open/-/open-7.0.3.tgz", + "integrity": "sha512-sP2ru2v0P290WFfv49Ap8MF6PkzGNnGlAwHweB4WR4mr5d2d0woiCluUeJ218w7/+PmoBy9JmYgD5A4mLcWOFA==", "dev": true, "requires": { - "is-wsl": "^1.1.0" + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" } }, "opn": { @@ -7809,6 +9484,14 @@ "dev": true, "requires": { "is-wsl": "^1.1.0" + }, + "dependencies": { + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + } } }, "optimist": { @@ -7829,38 +9512,110 @@ } } }, - "original": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", - "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", + "ora": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/ora/-/ora-4.0.3.tgz", + "integrity": "sha512-fnDebVFyz309A73cqCipVL1fBZewq4vwgSHfxh43vVy31mbyoQ8sCH3Oeaog/owYOs/lLlGVPCISQonTneg6Pg==", "dev": true, "requires": { - "url-parse": "^1.4.3" - } - }, - "os-browserify": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", - "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", - "dev": true - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-locale": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz", - "integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==", + "chalk": "^3.0.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.2.0", + "is-interactive": "^1.0.0", + "log-symbols": "^3.0.0", + "mute-stream": "0.0.8", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "original": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", + "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", "dev": true, "requires": { - "execa": "^1.0.0", - "lcid": "^2.0.0", - "mem": "^4.0.0" + "url-parse": "^1.4.3" } }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", @@ -7877,28 +9632,16 @@ "os-tmpdir": "^1.0.0" } }, - "p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", - "dev": true - }, "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", "dev": true }, - "p-is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz", - "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", - "dev": true - }, "p-limit": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", - "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -7914,10 +9657,13 @@ } }, "p-map": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", - "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", - "dev": true + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } }, "p-retry": { "version": "3.0.1", @@ -7935,13 +9681,14 @@ "dev": true }, "pacote": { - "version": "9.5.5", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-9.5.5.tgz", - "integrity": "sha512-jAEP+Nqj4kyMWyNpfTU/Whx1jA7jEc5cCOlurm0/0oL+v8TAp1QSsK83N7bYe+2bEdFzMAtPG5TBebjzzGV0cA==", + "version": "9.5.12", + "resolved": "https://registry.npmjs.org/pacote/-/pacote-9.5.12.tgz", + "integrity": "sha512-BUIj/4kKbwWg4RtnBncXPJd15piFSVNpTzY0rysSr3VnMowTYgkGKcaHrbReepAkjTr8lH2CVWRi58Spg2CicQ==", "dev": true, "requires": { "bluebird": "^3.5.3", "cacache": "^12.0.2", + "chownr": "^1.1.2", "figgy-pudding": "^3.5.1", "get-stream": "^4.1.0", "glob": "^7.1.3", @@ -7953,9 +9700,10 @@ "mississippi": "^3.0.0", "mkdirp": "^0.5.1", "normalize-package-data": "^2.4.0", + "npm-normalize-package-bin": "^1.0.0", "npm-package-arg": "^6.1.0", "npm-packlist": "^1.1.12", - "npm-pick-manifest": "^2.2.3", + "npm-pick-manifest": "^3.0.0", "npm-registry-fetch": "^4.0.0", "osenv": "^0.1.5", "promise-inflight": "^1.0.1", @@ -7965,21 +9713,136 @@ "safe-buffer": "^5.1.2", "semver": "^5.6.0", "ssri": "^6.0.1", - "tar": "^4.4.8", + "tar": "^4.4.10", "unique-filename": "^1.1.1", "which": "^1.3.1" }, "dependencies": { + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.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" + } + } + } + }, + "fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "dev": true, + "requires": { + "minipass": "^2.6.0" + } + }, + "hosted-git-info": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", + "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", + "dev": true + }, + "minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "dev": true, + "requires": { + "minipass": "^2.9.0" + } + }, + "npm-package-arg": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-6.1.1.tgz", + "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", + "dev": true, + "requires": { + "hosted-git-info": "^2.7.1", + "osenv": "^0.1.5", + "semver": "^5.6.0", + "validate-npm-package-name": "^3.0.0" + } + }, "npm-pick-manifest": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-2.2.3.tgz", - "integrity": "sha512-+IluBC5K201+gRU85vFlUwX3PFShZAbAgDNp2ewJdWMVSppdo/Zih0ul2Ecky/X7b51J7LrrUAP+XOmOCvYZqA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-3.0.2.tgz", + "integrity": "sha512-wNprTNg+X5nf+tDi+hbjdHhM4bX+mKqv6XmPh7B5eG+QY9VARfQPfCEH013H5GqfNj6ee8Ij2fg8yk0mzps1Vw==", "dev": true, "requires": { "figgy-pudding": "^3.5.1", "npm-package-arg": "^6.0.0", "semver": "^5.4.1" } + }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "tar": { + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "dev": true, + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true } } }, @@ -8001,14 +9864,13 @@ } }, "parse-asn1": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.5.tgz", - "integrity": "sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", "dev": true, "requires": { - "asn1.js": "^4.0.0", + "asn1.js": "^5.2.0", "browserify-aes": "^1.0.0", - "create-hash": "^1.1.0", "evp_bytestokey": "^1.0.0", "pbkdf2": "^3.0.3", "safe-buffer": "^5.1.1" @@ -8109,143 +9971,703 @@ "dev": true }, "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "pbkdf2": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.1.tgz", + "integrity": "sha512-4Ejy1OPxi9f2tt1rRV7Go7zmfDQ+ZectEQz3VGUQhgq62HtIRPDyG/JtnwIxs6x3uNMwo2V7q1fMvKjb+Tnpqg==", + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "picomatch": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.1.1.tgz", + "integrity": "sha512-OYMyqkKzK7blWO/+XZYP6w8hH0LDvkBvdvKukti+7kqYFCiEAk+gI3DWnryapc0Dau05ugGTy0foQ6mqn4AHYA==", + "dev": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pkg-dir": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "portfinder": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", + "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", + "dev": true, + "requires": { + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.5" + }, + "dependencies": { + "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" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + } + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "postcss": { + "version": "7.0.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz", + "integrity": "sha512-WuQETPMcW9Uf1/22HWUWP9lgsIC+KEHg2kozMflKjbeUtw9ujvFX6QmIfozaErDkmLWS9WEnEdEe6Uo9/BNTdQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.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 + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-calc": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.4.tgz", + "integrity": "sha512-0I79VRAd1UTkaHzY9w83P39YGO/M3bG7/tNLrHGEunBolfoGM0hSjrGvjoeaj0JE/zIw5GsI2KZ0UwDJqv5hjw==", + "dev": true, + "requires": { + "postcss": "^7.0.27", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.0.2" + } + }, + "postcss-colormin": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-4.0.3.tgz", + "integrity": "sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "color": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-convert-values": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz", + "integrity": "sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ==", + "dev": true, + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-discard-comments": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz", + "integrity": "sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-discard-duplicates": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz", + "integrity": "sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-discard-empty": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz", + "integrity": "sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-discard-overridden": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz", + "integrity": "sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-import": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-12.0.1.tgz", + "integrity": "sha512-3Gti33dmCjyKBgimqGxL3vcV8w9+bsHwO5UrBawp796+jdardbcFl4RP5w/76BwNL7aGzpKstIfF9I+kdE8pTw==", + "dev": true, + "requires": { + "postcss": "^7.0.1", + "postcss-value-parser": "^3.2.3", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-load-config": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.2.tgz", + "integrity": "sha512-/rDeGV6vMUo3mwJZmeHfEDvwnTKKqQ0S7OHUi/kJvvtx3aWtyWG2/0ZWnzCt2keEclwN6Tf0DST2v9kITdOKYw==", + "dev": true, + "requires": { + "cosmiconfig": "^5.0.0", + "import-cwd": "^2.0.0" + } + }, + "postcss-loader": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz", + "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "postcss": "^7.0.0", + "postcss-load-config": "^2.0.0", + "schema-utils": "^1.0.0" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "postcss-merge-longhand": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz", + "integrity": "sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw==", + "dev": true, + "requires": { + "css-color-names": "0.0.4", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "stylehacks": "^4.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-merge-rules": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz", + "integrity": "sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "cssnano-util-same-parent": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0", + "vendors": "^1.0.0" + }, + "dependencies": { + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dev": true, + "requires": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-minify-font-values": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz", + "integrity": "sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg==", + "dev": true, + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-minify-gradients": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz", + "integrity": "sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "is-color-stop": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-minify-params": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz", + "integrity": "sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "browserslist": "^4.0.0", + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "uniqs": "^2.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-minify-selectors": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz", + "integrity": "sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "dependencies": { + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dev": true, + "requires": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-modules-extract-imports": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", + "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", + "dev": true, + "requires": { + "postcss": "^7.0.5" + } + }, + "postcss-modules-local-by-default": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz", + "integrity": "sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw==", + "dev": true, + "requires": { + "icss-utils": "^4.1.1", + "postcss": "^7.0.32", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "dependencies": { + "postcss": { + "version": "7.0.34", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.34.tgz", + "integrity": "sha512-H/7V2VeNScX9KE83GDrDZNiGT1m2H+UTnlinIzhjlLX9hfMUn1mHNnGeX81a1c8JSBdBvqk7c2ZOG6ZPn5itGw==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + } + }, + "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 + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-modules-scope": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz", + "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==", + "dev": true, + "requires": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0" + } + }, + "postcss-modules-values": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", + "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", + "dev": true, + "requires": { + "icss-utils": "^4.0.0", + "postcss": "^7.0.6" + } + }, + "postcss-normalize-charset": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz", + "integrity": "sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-normalize-display-values": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz", + "integrity": "sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ==", + "dev": true, + "requires": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-normalize-positions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz", + "integrity": "sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-normalize-repeat-style": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz", + "integrity": "sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-normalize-string": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz", + "integrity": "sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA==", "dev": true, "requires": { - "pify": "^3.0.0" + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" }, "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", "dev": true } } }, - "pbkdf2": { - "version": "3.0.17", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.17.tgz", - "integrity": "sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA==", + "postcss-normalize-timing-functions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz", + "integrity": "sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A==", "dev": true, "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", - "dev": true - }, - "picomatch": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.1.1.tgz", - "integrity": "sha512-OYMyqkKzK7blWO/+XZYP6w8hH0LDvkBvdvKukti+7kqYFCiEAk+gI3DWnryapc0Dau05ugGTy0foQ6mqn4AHYA==", - "dev": true - }, - "pify": { + "postcss-normalize-unicode": { "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz", + "integrity": "sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg==", "dev": true, "requires": { - "pinkie": "^2.0.0" + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "postcss-normalize-url": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz", + "integrity": "sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA==", "dev": true, "requires": { - "find-up": "^3.0.0" + "is-absolute-url": "^2.0.0", + "normalize-url": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } } }, - "portfinder": { - "version": "1.0.25", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.25.tgz", - "integrity": "sha512-6ElJnHBbxVA1XSLgBp7G1FiCkQdlqGzuF7DswL5tcea+E8UpuvPU7beVAjjRwCioTS9ZluNbu+ZyRvgTsmqEBg==", + "postcss-normalize-whitespace": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz", + "integrity": "sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA==", "dev": true, "requires": { - "async": "^2.6.2", - "debug": "^3.1.1", - "mkdirp": "^0.5.1" + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" }, "dependencies": { - "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" - } + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true } } }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "postcss": { - "version": "7.0.17", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.17.tgz", - "integrity": "sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ==", + "postcss-ordered-values": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz", + "integrity": "sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw==", "dev": true, "requires": { - "chalk": "^2.4.2", - "source-map": "^0.6.1", - "supports-color": "^6.1.0" + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^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==", + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", "dev": true - }, - "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } } } }, - "postcss-import": { - "version": "12.0.1", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-12.0.1.tgz", - "integrity": "sha512-3Gti33dmCjyKBgimqGxL3vcV8w9+bsHwO5UrBawp796+jdardbcFl4RP5w/76BwNL7aGzpKstIfF9I+kdE8pTw==", + "postcss-reduce-initial": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz", + "integrity": "sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA==", "dev": true, "requires": { - "postcss": "^7.0.1", - "postcss-value-parser": "^3.2.3", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0" + } + }, + "postcss-reduce-transforms": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz", + "integrity": "sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg==", + "dev": true, + "requires": { + "cssnano-util-get-match": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" }, "dependencies": { "postcss-value-parser": { @@ -8256,32 +10678,53 @@ } } }, - "postcss-load-config": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.0.tgz", - "integrity": "sha512-4pV3JJVPLd5+RueiVVB+gFOAa7GWc25XQcMp86Zexzke69mKf6Nx9LRcQywdz7yZI9n1udOxmLuAwTBypypF8Q==", + "postcss-selector-parser": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.4.tgz", + "integrity": "sha512-gjMeXBempyInaBqpp8gODmwZ52WaYsVOsfr4L4lDQ7n3ncD6mEyySiDtgzCT+NYC0mmeOLvtsF8iaEf0YT6dBw==", "dev": true, "requires": { - "cosmiconfig": "^5.0.0", - "import-cwd": "^2.0.0" + "cssesc": "^3.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1", + "util-deprecate": "^1.0.2" } }, - "postcss-loader": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz", - "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==", + "postcss-svgo": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.2.tgz", + "integrity": "sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw==", "dev": true, "requires": { - "loader-utils": "^1.1.0", + "is-svg": "^3.0.0", "postcss": "^7.0.0", - "postcss-load-config": "^2.0.0", - "schema-utils": "^1.0.0" + "postcss-value-parser": "^3.0.0", + "svgo": "^1.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-unique-selectors": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz", + "integrity": "sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "postcss": "^7.0.0", + "uniqs": "^2.0.0" } }, "postcss-value-parser": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.0.2.tgz", - "integrity": "sha512-LmeoohTpp/K4UiyQCwuGWlONxXamGzCMtFxLq4W1nZVGIQLYvMCJx3yAF9qyyuFpflABI9yVdtJAqbihOsCsJQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", + "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==", "dev": true }, "prepend-http": { @@ -8290,12 +10733,6 @@ "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=", "dev": true }, - "private": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", - "dev": true - }, "process": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", @@ -8471,13 +10908,13 @@ } }, "proxy-addr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", - "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", "dev": true, "requires": { "forwarded": "~0.1.2", - "ipaddr.js": "1.9.0" + "ipaddr.js": "1.9.1" } }, "prr": { @@ -8510,6 +10947,14 @@ "parse-asn1": "^5.0.0", "randombytes": "^2.0.1", "safe-buffer": "^5.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.11.9", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz", + "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw==", + "dev": true + } } }, "pump": { @@ -8592,9 +11037,9 @@ "dev": true }, "querystringify": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz", - "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", "dev": true }, "randombytes": { @@ -8643,35 +11088,33 @@ } }, "raw-loader": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-3.1.0.tgz", - "integrity": "sha512-lzUVMuJ06HF4rYveaz9Tv0WRlUMxJ0Y1hgSkkgg+50iEdaI0TthyEDe08KIHb0XsF6rn8WYTqPCaGTZg3sX+qA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.0.tgz", + "integrity": "sha512-iINUOYvl1cGEmfoaLjnZXt4bKfT2LJnZZib5N/LLyAphC+Dd11vNP9CNVb38j+SAJpFI1uo8j9frmih53ASy7Q==", "dev": true, "requires": { - "loader-utils": "^1.1.0", - "schema-utils": "^2.0.1" + "loader-utils": "^1.2.3", + "schema-utils": "^2.5.0" }, "dependencies": { - "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "dev": true, "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "minimist": "^1.2.0" } }, - "schema-utils": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.5.0.tgz", - "integrity": "sha512-32ISrwW2scPXHUSusP8qMg5dLUawKkyV+/qIEV9JdXKx+rsM6mi8vZY8khg2M69Qom16rtroWXD3Ybtiws38gQ==", + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", "dev": true, "requires": { - "ajv": "^6.10.2", - "ajv-keywords": "^3.4.1" + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" } } } @@ -8694,16 +11137,15 @@ } }, "read-package-json": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-2.1.0.tgz", - "integrity": "sha512-KLhu8M1ZZNkMcrq1+0UJbR8Dii8KZUqB0Sha4mOx/bknfKI/fyrQVrG/YIt2UOtG667sD8+ee4EXMM91W9dC+A==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-2.1.2.tgz", + "integrity": "sha512-D1KmuLQr6ZSJS0tW8hf3WGpRlwszJOXZ3E8Yd/DNRaM5d+1wVRZdHlpGBLAuovjr28LbWvjpWkBHMxpRGGjzNA==", "dev": true, "requires": { "glob": "^7.1.1", - "graceful-fs": "^4.1.2", - "json-parse-better-errors": "^1.0.1", + "json-parse-even-better-errors": "^2.3.0", "normalize-package-data": "^2.0.0", - "slash": "^1.0.0" + "npm-normalize-package-bin": "^1.0.0" } }, "read-package-tree": { @@ -8765,28 +11207,19 @@ "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", "dev": true }, - "regenerate-unicode-properties": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz", - "integrity": "sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==", - "dev": true, - "requires": { - "regenerate": "^1.4.0" - } - }, "regenerator-runtime": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz", - "integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw==", + "version": "0.13.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz", + "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==", "dev": true }, "regenerator-transform": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.1.tgz", - "integrity": "sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ==", + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", + "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", "dev": true, "requires": { - "private": "^0.1.6" + "@babel/runtime": "^7.8.4" } }, "regex-not": { @@ -8800,26 +11233,34 @@ } }, "regexp.prototype.flags": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz", - "integrity": "sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA==", - "dev": true, - "requires": { - "define-properties": "^1.1.2" - } - }, - "regexpu-core": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.6.0.tgz", - "integrity": "sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", + "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", "dev": true, "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.1.0", - "regjsgen": "^0.5.0", - "regjsparser": "^0.6.0", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.1.0" + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "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.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } } }, "regjsgen": { @@ -8828,23 +11269,6 @@ "integrity": "sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg==", "dev": true }, - "regjsparser": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", - "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - } - } - }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -8863,15 +11287,6 @@ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, - "requires": { - "is-finite": "^1.0.0" - } - }, "request": { "version": "2.88.0", "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", @@ -8907,9 +11322,9 @@ "dev": true }, "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", "dev": true }, "requires-port": { @@ -8970,12 +11385,30 @@ "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", "dev": true }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, "rfdc": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.1.4.tgz", "integrity": "sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug==", "dev": true }, + "rgb-regex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz", + "integrity": "sha1-wODWiC3w4jviVKR16O3UGRX+rrE=", + "dev": true + }, + "rgba-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz", + "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=", + "dev": true + }, "rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", @@ -8995,15 +11428,27 @@ "inherits": "^2.0.1" } }, - "run-async": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "rollup": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.1.0.tgz", + "integrity": "sha512-gfE1455AEazVVTJoeQtcOq/U6GSxwoj4XPSWVsuWmgIxj7sBQNLDOSA82PbdMe+cP8ql8fR1jogPFe8Wg8g4SQ==", "dev": true, "requires": { - "is-promise": "^2.1.0" + "fsevents": "~2.1.2" } }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true + }, + "run-parallel": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", + "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==", + "dev": true + }, "run-queue": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", @@ -9043,25 +11488,53 @@ "dev": true }, "sass": { - "version": "1.22.9", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.22.9.tgz", - "integrity": "sha512-FzU1X2V8DlnqabrL4u7OBwD2vcOzNMongEJEx3xMEhWY/v26FFR3aG0hyeu2T965sfR0E9ufJwmG+Qjz78vFPQ==", + "version": "1.26.3", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.26.3.tgz", + "integrity": "sha512-5NMHI1+YFYw4sN3yfKjpLuV9B5l7MqQ6FlkTcC4FT+oHbBRUZoSjHrrt/mE0nFXJyY2kQtU9ou9HxvFVjLFuuw==", "dev": true, "requires": { "chokidar": ">=2.0.0 <4.0.0" } }, "sass-loader": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-7.2.0.tgz", - "integrity": "sha512-h8yUWaWtsbuIiOCgR9fd9c2lRXZ2uG+h8Dzg/AGNj+Hg/3TO8+BBAW9mEP+mh8ei+qBKqSJ0F1FLlYjNBc61OA==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-8.0.2.tgz", + "integrity": "sha512-7o4dbSK8/Ol2KflEmSco4jTjQoV988bM82P9CZdmo9hR3RLnvNc0ufMNdMrB0caq38JQ/FgF4/7RcbcfKzxoFQ==", "dev": true, "requires": { "clone-deep": "^4.0.1", - "loader-utils": "^1.0.1", - "neo-async": "^2.5.0", - "pify": "^4.0.1", - "semver": "^5.5.0" + "loader-utils": "^1.2.3", + "neo-async": "^2.6.1", + "schema-utils": "^2.6.1", + "semver": "^6.3.0" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, "saucelabs": { @@ -9074,20 +11547,40 @@ } }, "sax": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/sax/-/sax-0.5.8.tgz", - "integrity": "sha1-1HLbIo6zMcJQaw6MFVJK25OdEsE=", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", "dev": true }, "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", "dev": true, "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + }, + "dependencies": { + "ajv": { + "version": "6.12.5", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz", + "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + } } }, "select-hose": { @@ -9120,12 +11613,12 @@ } }, "selfsigned": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.7.tgz", - "integrity": "sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA==", + "version": "1.10.8", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.8.tgz", + "integrity": "sha512-2P4PtieJeEwVgTU9QEcwIRDQ/mXJLX8/+I3ur+Pg16nS8oNbrGxEso9NyYWy8NAmXiNl4dlAp5MwoNeCWzON4w==", "dev": true, "requires": { - "node-forge": "0.9.0" + "node-forge": "^0.10.0" } }, "semver": { @@ -9199,10 +11692,13 @@ } }, "serialize-javascript": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.9.1.tgz", - "integrity": "sha512-0Vb/54WJ6k5v8sSWN09S0ora+Hnr+cX40r9F170nT+mSkaxltoE/7R3OrIdBSUv1OoiobH1QoWQbCnAO+e8J1A==", - "dev": true + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } }, "serve-index": { "version": "1.9.1", @@ -9348,15 +11844,32 @@ "dev": true }, "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "dev": true, + "requires": { + "is-arrayish": "^0.3.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "dev": true + } + } + }, "slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, "smart-buffer": { @@ -9616,13 +12129,22 @@ } }, "sockjs": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.19.tgz", - "integrity": "sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw==", + "version": "0.3.20", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.20.tgz", + "integrity": "sha512-SpmVOVpdq0DJc0qArhF3E5xsxvaiqGNb73XfgBpK1y3UD5gs8DSo8aCTsuT5pX8rssdc2NDIzANwP9eCAiSdTA==", "dev": true, "requires": { "faye-websocket": "^0.10.0", - "uuid": "^3.0.1" + "uuid": "^3.4.0", + "websocket-driver": "0.6.5" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } } }, "sockjs-client": { @@ -9708,15 +12230,37 @@ "requires": { "async": "^2.5.0", "loader-utils": "^1.1.0" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + } } }, "source-map-resolve": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", "dev": true, "requires": { - "atob": "^2.1.1", + "atob": "^2.1.2", "decode-uri-component": "^0.2.0", "resolve-url": "^0.2.1", "source-map-url": "^0.4.0", @@ -9748,15 +12292,15 @@ "dev": true }, "sourcemap-codec": { - "version": "1.4.6", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.6.tgz", - "integrity": "sha512-1ZooVLYFxC448piVLBbtOxFcXwnymH9oUF8nRd3CuYDVvkRBxRl6pB4Mtas5a4drtL+E8LDgFkQNcgIw6tc8Hg==", + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", "dev": true }, "spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", @@ -9764,15 +12308,15 @@ } }, "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", "dev": true }, "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, "requires": { "spdx-exceptions": "^2.1.0", @@ -9780,15 +12324,15 @@ } }, "spdx-license-ids": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", - "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz", + "integrity": "sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw==", "dev": true }, "spdy": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.1.tgz", - "integrity": "sha512-HeZS3PBdMA+sZSu0qwpCxl3DeALD5ASx8pAX0jZdKXSpPWbQ6SYGnlg3BBmYLx5LtiZrmkAZfErCm2oECBcioA==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", "dev": true, "requires": { "debug": "^4.1.0", @@ -9813,9 +12357,9 @@ }, "dependencies": { "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==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "dev": true, "requires": { "inherits": "^2.0.3", @@ -9867,14 +12411,20 @@ } }, "ssri": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", - "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.0.tgz", + "integrity": "sha512-aq/pz989nxVYwn16Tsbj1TqFpD5LLrQxHf5zaHuieFV+R0Bbr4y8qUsOA45hXT/N4/9UNXTarBjnjVmjSOVaAA==", "dev": true, "requires": { - "figgy-pudding": "^3.5.1" + "minipass": "^3.1.1" } }, + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "dev": true + }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -9936,9 +12486,9 @@ } }, "stream-shift": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", "dev": true }, "streamroller": { @@ -9972,50 +12522,93 @@ "dev": true }, "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", "dev": true, "requires": { + "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "strip-ansi": "^5.1.0" }, "dependencies": { "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", "dev": true }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^4.1.0" } } } }, - "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==", + "string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", "dev": true, "requires": { "define-properties": "^1.1.3", - "function-bind": "^1.1.1" + "es-abstract": "^1.17.5" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "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.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } } }, - "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==", + "string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", + "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", "dev": true, "requires": { "define-properties": "^1.1.3", - "function-bind": "^1.1.1" + "es-abstract": "^1.17.5" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "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.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } } }, "string_decoder": { @@ -10049,75 +12642,97 @@ "dev": true }, "style-loader": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.0.0.tgz", - "integrity": "sha512-B0dOCFwv7/eY31a5PCieNwMgMhVGFe9w+rh7s/Bx8kfFkrth9zfTZquoYvdw8URgiqxObQKcpW51Ugz1HjfdZw==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.1.3.tgz", + "integrity": "sha512-rlkH7X/22yuwFYK357fMN/BxYOorfnfq0eD7+vqlemSK4wEcejFF1dg4zxP0euBW8NrYx2WZzZ8PPFevr7D+Kw==", "dev": true, "requires": { "loader-utils": "^1.2.3", - "schema-utils": "^2.0.1" + "schema-utils": "^2.6.4" }, "dependencies": { - "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", "dev": true, "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "minimist": "^1.2.0" } }, - "schema-utils": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.5.0.tgz", - "integrity": "sha512-32ISrwW2scPXHUSusP8qMg5dLUawKkyV+/qIEV9JdXKx+rsM6mi8vZY8khg2M69Qom16rtroWXD3Ybtiws38gQ==", + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", "dev": true, "requires": { - "ajv": "^6.10.2", - "ajv-keywords": "^3.4.1" + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" } } } }, - "stylus": { - "version": "0.54.5", - "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.5.tgz", - "integrity": "sha1-QrlWCTHKcJDOhRWnmLqeaqPW3Hk=", + "stylehacks": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz", + "integrity": "sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g==", "dev": true, "requires": { - "css-parse": "1.7.x", - "debug": "*", - "glob": "7.0.x", - "mkdirp": "0.5.x", - "sax": "0.5.x", - "source-map": "0.1.x" + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" }, "dependencies": { - "glob": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.6.tgz", - "integrity": "sha1-IRuvr0nlJbjNkyYNFKsTYVKz9Xo=", + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", "dev": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.2", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" } - }, - "source-map": { - "version": "0.1.43", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + } + } + }, + "stylus": { + "version": "0.54.7", + "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.7.tgz", + "integrity": "sha512-Yw3WMTzVwevT6ZTrLCYNHAFmanMxdylelL3hkWNgPMeTCpMwpV3nXjpOHuBXtFv7aiO2xRuQS6OoAdgkNcSNug==", + "dev": true, + "requires": { + "css-parse": "~2.0.0", + "debug": "~3.1.0", + "glob": "^7.1.3", + "mkdirp": "~0.5.x", + "safer-buffer": "^2.1.2", + "sax": "~1.2.4", + "semver": "^6.0.0", + "source-map": "^0.7.3" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { - "amdefine": ">=0.0.4" + "ms": "2.0.0" } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true } } }, @@ -10130,6 +12745,28 @@ "loader-utils": "^1.0.2", "lodash.clonedeep": "^4.5.0", "when": "~3.6.x" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + } } }, "supports-color": { @@ -10141,6 +12778,27 @@ "has-flag": "^3.0.0" } }, + "svgo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", + "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "coa": "^2.0.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "^0.1.1", + "css-tree": "1.0.0-alpha.37", + "csso": "^4.0.2", + "js-yaml": "^3.13.1", + "mkdirp": "~0.5.1", + "object.values": "^1.1.0", + "sax": "~1.2.4", + "stable": "^0.1.8", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + } + }, "symbol-observable": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", @@ -10154,24 +12812,37 @@ "dev": true }, "tar": { - "version": "4.4.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", - "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.0.5.tgz", + "integrity": "sha512-0b4HOimQHj9nXNEAA7zWwMM91Zhhba3pspja6sQbgTpynOJf+bkjBnfybNYzbpLbnwXnbyB4LOREvlyXLkCHSg==", "dev": true, "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.8.6", - "minizlib": "^1.2.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.3" + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "dependencies": { + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + } } }, "terser": { - "version": "4.3.9", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.3.9.tgz", - "integrity": "sha512-NFGMpHjlzmyOtPL+fDw3G7+6Ueh/sz4mkaUYa4lJCxOPTNzd0Uj0aZJOmsDYoSQyfuVoWDMSWTPU3huyOm2zdA==", + "version": "4.6.10", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.10.tgz", + "integrity": "sha512-qbF/3UOo11Hggsbsqm2hPa6+L4w7bkr+09FNseEe8xrcVD3APGLFqE+Oz1ZKAxjYnFsj80rLOfgAtJ0LNJjtTA==", "dev": true, "requires": { "commander": "^2.20.0", @@ -10188,31 +12859,124 @@ } }, "terser-webpack-plugin": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.1.tgz", - "integrity": "sha512-ZXmmfiwtCLfz8WKZyYUuuHf3dMYEjg8NrjHMb0JqHVHVOSkzp3cW2/XG1fP3tRhqEqSzMwzzRQGtAPbs4Cncxg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-3.0.3.tgz", + "integrity": "sha512-bZFnotuIKq5Rqzrs+qIwFzGdKdffV9epG5vDSEbYzvKAhPeR5RbbrQysfPgbIIMhNAQtZD2hGwBfSKUXjXZZZw==", "dev": true, "requires": { - "cacache": "^12.0.2", - "find-cache-dir": "^2.1.0", - "is-wsl": "^1.1.0", - "schema-utils": "^1.0.0", - "serialize-javascript": "^1.7.0", + "cacache": "^15.0.4", + "find-cache-dir": "^3.3.1", + "jest-worker": "^26.0.0", + "p-limit": "^2.3.0", + "schema-utils": "^2.6.6", + "serialize-javascript": "^3.1.0", "source-map": "^0.6.1", - "terser": "^4.1.2", - "webpack-sources": "^1.4.0", - "worker-farm": "^1.7.0" + "terser": "^4.6.13", + "webpack-sources": "^1.4.3" }, "dependencies": { - "find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "cacache": { + "version": "15.0.5", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.0.5.tgz", + "integrity": "sha512-lloiL22n7sOjEEXdL8NAjTgv9a1u43xICE9/203qonkZUCj5X1UEWIdf2/Y0d6QcCtMzbKQyhrcDbdvlZTs/+A==", "dev": true, "requires": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.0", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + } + }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true + }, + "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" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jest-worker": { + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.3.0.tgz", + "integrity": "sha512-Vmpn2F6IASefL+DVBhPzI2J9/GJUsqzomdeN+P+dK8/jKxbh8R3BtFnx3FIta7wYlPU62cpJMJQo4kuOowcMnw==", + "dev": true, + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "serialize-javascript": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.1.0.tgz", + "integrity": "sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" } }, "source-map": { @@ -10220,6 +12984,26 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + } } } }, @@ -10254,6 +13038,12 @@ "setimmediate": "^1.0.4" } }, + "timsort": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", + "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", + "dev": true + }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -10347,15 +13137,9 @@ } }, "tree-kill": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.1.tgz", - "integrity": "sha512-4hjqbObwlh2dLyW4tcz0Ymw0ggoaVDMveUB9w8kFSQScdRLo0gxO9J7WFcUBo+W3C1TLdFIEwNOWebgZZ0RH9Q==", - "dev": true - }, - "trim-right": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", - "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", "dev": true }, "ts-node": { @@ -10428,9 +13212,9 @@ "dev": true }, "type-fest": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.5.2.tgz", - "integrity": "sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw==", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", + "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", "dev": true }, "type-is": { @@ -10450,9 +13234,9 @@ "dev": true }, "typescript": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.5.3.tgz", - "integrity": "sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==", + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz", + "integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==", "dev": true }, "uglify-js": { @@ -10497,12 +13281,6 @@ "unicode-property-aliases-ecmascript": "^1.0.4" } }, - "unicode-match-property-value-ecmascript": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz", - "integrity": "sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g==", - "dev": true - }, "unicode-property-aliases-ecmascript": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz", @@ -10521,6 +13299,18 @@ "set-value": "^2.0.1" } }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true + }, + "uniqs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", + "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", + "dev": true + }, "unique-filename": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", @@ -10573,6 +13363,12 @@ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", "dev": true }, + "unquote": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", + "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=", + "dev": true + }, "unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", @@ -10720,6 +13516,39 @@ "object.getownpropertydescriptors": "^2.0.3" } }, + "util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + }, + "dependencies": { + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "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.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } + } + }, "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", @@ -10757,6 +13586,12 @@ "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", "dev": true }, + "vendors": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz", + "integrity": "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==", + "dev": true + }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", @@ -10781,14 +13616,61 @@ "dev": true }, "watchpack": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz", - "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.4.tgz", + "integrity": "sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg==", "dev": true, "requires": { - "chokidar": "^2.0.2", + "chokidar": "^3.4.1", "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0" + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.0" + }, + "dependencies": { + "chokidar": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", + "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", + "dev": true, + "optional": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.4.0" + } + }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", + "dev": true, + "optional": true + }, + "readdirp": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", + "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", + "dev": true, + "optional": true, + "requires": { + "picomatch": "^2.2.1" + } + } + } + }, + "watchpack-chokidar2": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz", + "integrity": "sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA==", + "dev": true, + "optional": true, + "requires": { + "chokidar": "^2.1.8" }, "dependencies": { "anymatch": { @@ -10796,6 +13678,7 @@ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "dev": true, + "optional": true, "requires": { "micromatch": "^3.1.4", "normalize-path": "^2.1.1" @@ -10806,6 +13689,7 @@ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "dev": true, + "optional": true, "requires": { "remove-trailing-separator": "^1.0.1" } @@ -10816,13 +13700,15 @@ "version": "1.13.1", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true + "dev": true, + "optional": true }, "braces": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", "dev": true, + "optional": true, "requires": { "arr-flatten": "^1.1.0", "array-unique": "^0.3.2", @@ -10834,6 +13720,18 @@ "snapdragon-node": "^2.0.1", "split-string": "^3.0.2", "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } } }, "chokidar": { @@ -10841,6 +13739,7 @@ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", "dev": true, + "optional": true, "requires": { "anymatch": "^2.0.0", "async-each": "^1.0.1", @@ -10856,572 +13755,58 @@ "upath": "^1.1.1" } }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, + "optional": true, "requires": { "extend-shallow": "^2.0.1", "is-number": "^3.0.0", "repeat-string": "^1.6.1", "to-regex-range": "^2.1.0" - } - }, - "fsevents": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", - "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", - "dev": true, - "optional": true, - "requires": { - "nan": "^2.12.1", - "node-pre-gyp": "^0.12.0" }, "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.3", - "bundled": true, - "dev": true, - "optional": 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" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true, - "optional": true - }, - "minipass": { - "version": "2.3.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.2.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.3.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^4.1.0", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.12.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.4.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.6.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.7.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { + "extend-shallow": { "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.8", - "bundled": true, + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "optional": true, "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.4", - "minizlib": "^1.1.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" + "is-extendable": "^0.1.0" } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "bundled": true, + } + } + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "optional": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "dev": true, "optional": true, "requires": { - "string-width": "^1.0.2 || 2" + "is-extglob": "^2.1.0" } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "yallist": { - "version": "3.0.3", - "bundled": true, - "dev": true, - "optional": true } } }, @@ -11430,6 +13815,7 @@ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", "dev": true, + "optional": true, "requires": { "binary-extensions": "^1.0.0" } @@ -11439,17 +13825,43 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, + "optional": true, "requires": { "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } } }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "dev": true, + "optional": true, "requires": { - "is-buffer": "^1.1.5" + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" } }, "readdirp": { @@ -11457,6 +13869,7 @@ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", "dev": true, + "optional": true, "requires": { "graceful-fs": "^4.1.11", "micromatch": "^3.1.10", @@ -11468,6 +13881,7 @@ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", "dev": true, + "optional": true, "requires": { "is-number": "^3.0.0", "repeat-string": "^1.6.1" @@ -11484,6 +13898,15 @@ "minimalistic-assert": "^1.0.0" } }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "dev": true, + "requires": { + "defaults": "^1.0.3" + } + }, "webdriver-js-extender": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/webdriver-js-extender/-/webdriver-js-extender-2.1.0.tgz", @@ -11495,9 +13918,9 @@ } }, "webpack": { - "version": "4.39.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.39.2.tgz", - "integrity": "sha512-AKgTfz3xPSsEibH00JfZ9sHXGUwIQ6eZ9tLN8+VLzachk1Cw2LVmy+4R7ZiwTa9cZZ15tzySjeMui/UnSCAZhA==", + "version": "4.42.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.42.0.tgz", + "integrity": "sha512-EzJRHvwQyBiYrYqhyjW9AqM90dE4+s1/XtCfn7uWg6cS72zH+2VPFAlsnW0+W0cDi0XRjNKUMoJtpSi50+Ph6w==", "dev": true, "requires": { "@webassemblyjs/ast": "1.8.5", @@ -11520,48 +13943,257 @@ "node-libs-browser": "^2.2.1", "schema-utils": "^1.0.0", "tapable": "^1.1.3", - "terser-webpack-plugin": "^1.4.1", + "terser-webpack-plugin": "^1.4.3", "watchpack": "^1.6.0", "webpack-sources": "^1.4.1" }, "dependencies": { "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "version": "6.12.5", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz", + "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==", "dev": true, "requires": { - "fast-deep-equal": "^2.0.1", + "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } - } - } - }, - "webpack-core": { - "version": "0.6.9", - "resolved": "https://registry.npmjs.org/webpack-core/-/webpack-core-0.6.9.tgz", - "integrity": "sha1-/FcViMhVjad76e+23r3Fo7FyvcI=", - "dev": true, - "requires": { - "source-list-map": "~0.1.7", - "source-map": "~0.4.1" - }, - "dependencies": { - "source-list-map": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-0.1.8.tgz", - "integrity": "sha1-xVCyq1Qn9rPyH1r+rYjE9Vh7IQY=", + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.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" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "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": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", "dev": true }, + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "ssri": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.1.tgz", + "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", "dev": true, "requires": { - "amdefine": ">=0.0.4" + "figgy-pudding": "^3.5.1" + } + }, + "terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dev": true, + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" } } } @@ -11579,18 +14211,28 @@ "webpack-log": "^2.0.0" }, "dependencies": { + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, "mime": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz", - "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==", + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.6.tgz", + "integrity": "sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA==", "dev": true } } }, "webpack-dev-server": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.9.0.tgz", - "integrity": "sha512-E6uQ4kRrTX9URN9s/lIbqTAztwEPdvzVrcmHE8EQ9YnuT9J8Es5Wrd8n9BKg1a0oZ5EgEke/EQFgUsp18dSTBw==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.0.tgz", + "integrity": "sha512-PUxZ+oSTxogFQgkTtFndEtJIPNmml7ExwufBZ9L2/Xyyd5PnOL5UreWe5ZT7IU25DSdykL9p1MLQzmLh2ljSeg==", "dev": true, "requires": { "ansi-html": "0.0.7", @@ -11601,31 +14243,31 @@ "debug": "^4.1.1", "del": "^4.1.1", "express": "^4.17.1", - "html-entities": "^1.2.1", + "html-entities": "^1.3.1", "http-proxy-middleware": "0.19.1", "import-local": "^2.0.0", "internal-ip": "^4.3.0", "ip": "^1.1.5", "is-absolute-url": "^3.0.3", "killable": "^1.0.1", - "loglevel": "^1.6.4", + "loglevel": "^1.6.8", "opn": "^5.5.0", "p-retry": "^3.0.1", - "portfinder": "^1.0.25", + "portfinder": "^1.0.26", "schema-utils": "^1.0.0", "selfsigned": "^1.10.7", "semver": "^6.3.0", "serve-index": "^1.9.1", - "sockjs": "0.3.19", + "sockjs": "0.3.20", "sockjs-client": "1.4.0", - "spdy": "^4.0.1", + "spdy": "^4.0.2", "strip-ansi": "^3.0.1", "supports-color": "^6.1.0", "url": "^0.11.0", "webpack-dev-middleware": "^3.7.2", "webpack-log": "^2.0.0", "ws": "^6.2.1", - "yargs": "12.0.5" + "yargs": "^13.3.2" }, "dependencies": { "anymatch": { @@ -11671,6 +14313,17 @@ "snapdragon-node": "^2.0.1", "split-string": "^3.0.2", "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } } }, "chokidar": { @@ -11684,22 +14337,13 @@ "braces": "^2.3.2", "fsevents": "^1.2.7", "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" } }, "fill-range": { @@ -11712,556 +14356,53 @@ "is-number": "^3.0.0", "repeat-string": "^1.6.1", "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } } }, "fsevents": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.9.tgz", - "integrity": "sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw==", + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, - "optional": true, "requires": { - "nan": "^2.12.1", - "node-pre-gyp": "^0.12.0" + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" }, "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "^2.1.1" - } - }, - "deep-extend": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.3", - "bundled": true, - "dev": true, - "optional": 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" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.24", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true, - "optional": true - }, - "minipass": { - "version": "2.3.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.2.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.3.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^4.1.0", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.12.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.1", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.2.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.4.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.6.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "^7.1.3" - } - }, - "safe-buffer": { - "version": "5.1.2", - "bundled": true, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "dev": true, - "optional": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.7.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, "requires": { - "ansi-regex": "^2.0.0" + "is-extglob": "^2.1.0" } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.4", - "minizlib": "^1.1.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.3", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "yallist": { - "version": "3.0.3", - "bundled": true, - "dev": true, - "optional": true } } }, + "is-absolute-url": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", + "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", + "dev": true + }, "is-binary-path": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", @@ -12278,15 +14419,38 @@ "dev": true, "requires": { "kind-of": "^3.0.2" + }, + "dependencies": { + "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": { + "is-buffer": "^1.1.5" + } + } } }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" } }, "readdirp": { @@ -12300,6 +14464,17 @@ "readable-stream": "^2.0.2" } }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", @@ -12338,12 +14513,12 @@ } }, "webpack-merge": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.1.tgz", - "integrity": "sha512-4p8WQyS98bUJcCvFMbdGZyZmsKuWjWVnVHnAS3FFg0HDaRVrPbkivx2RYCre8UiemD67RsiFFLfn4JhLAin8Vw==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.2.tgz", + "integrity": "sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g==", "dev": true, "requires": { - "lodash": "^4.17.5" + "lodash": "^4.17.15" } }, "webpack-sources": { @@ -12365,29 +14540,27 @@ } }, "webpack-subresource-integrity": { - "version": "1.1.0-rc.6", - "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-1.1.0-rc.6.tgz", - "integrity": "sha512-Az7y8xTniNhaA0620AV1KPwWOqawurVVDzQSpPAeR5RwNbL91GoBSJAAo9cfd+GiFHwsS5bbHepBw1e6Hzxy4w==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/webpack-subresource-integrity/-/webpack-subresource-integrity-1.4.0.tgz", + "integrity": "sha512-GB1kB/LwAWC3CxwcedGhMkxGpNZxSheCe1q+KJP1bakuieAdX/rGHEcf5zsEzhKXpqsGqokgsDoD9dIkr61VDQ==", "dev": true, "requires": { - "webpack-core": "^0.6.8" + "webpack-sources": "^1.3.0" } }, "websocket-driver": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.3.tgz", - "integrity": "sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg==", + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.6.5.tgz", + "integrity": "sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY=", "dev": true, "requires": { - "http-parser-js": ">=0.4.0 <0.4.11", - "safe-buffer": ">=5.1.0", "websocket-extensions": ">=0.1.1" } }, "websocket-extensions": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.3.tgz", - "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", "dev": true }, "when": { @@ -12427,42 +14600,60 @@ } }, "worker-plugin": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/worker-plugin/-/worker-plugin-3.2.0.tgz", - "integrity": "sha512-W5nRkw7+HlbsEt3qRP6MczwDDISjiRj2GYt9+bpe8A2La00TmJdwzG5bpdMXhRt1qcWmwAvl1TiKaHRa+XDS9Q==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/worker-plugin/-/worker-plugin-4.0.3.tgz", + "integrity": "sha512-7hFDYWiKcE3yHZvemsoM9lZis/PzurHAEX1ej8PLCu818Rt6QqUAiDdxHPCKZctzmhqzPpcFSgvMCiPbtooqAg==", "dev": true, "requires": { "loader-utils": "^1.1.0" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + } } }, "wrap-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", "dev": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" }, "dependencies": { - "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", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", "dev": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "ansi-regex": "^4.1.0" } } } @@ -12525,35 +14716,33 @@ "dev": true }, "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, "yargs": { - "version": "12.0.5", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", - "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", "dev": true, "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.2.0", + "cliui": "^5.0.0", "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.0.0", + "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", + "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", - "string-width": "^2.0.0", + "string-width": "^3.0.0", "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^11.1.1" + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" } }, "yargs-parser": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", - "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", "dev": true, "requires": { "camelcase": "^5.0.0", @@ -12573,9 +14762,9 @@ "dev": true }, "zone.js": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.9.1.tgz", - "integrity": "sha512-GkPiJL8jifSrKReKaTZ5jkhrMEgXbXYC+IPo1iquBjayRa0q86w3Dipjn8b415jpitMExe9lV8iTsv8tk3DGag==" + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/zone.js/-/zone.js-0.10.3.tgz", + "integrity": "sha512-LXVLVEq0NNOqK/fLJo3d0kfzd4sxwn2/h67/02pjCjfKDxgx1i9QqpvtHD8CrBnSSwMw5+dy11O7FRX5mkO7Cg==" } } } diff --git a/perf/test/angular-cli/package.json b/perf/test/angular-cli/package.json index 83e6a3dacf..5392f7f1c5 100644 --- a/perf/test/angular-cli/package.json +++ b/perf/test/angular-cli/package.json @@ -14,32 +14,32 @@ }, "private": true, "dependencies": { - "@angular/animations": "~8.2.13", - "@angular/common": "~8.2.13", - "@angular/compiler": "~8.2.13", - "@angular/core": "~8.2.13", - "@angular/forms": "~8.2.13", - "@angular/platform-browser": "~8.2.13", - "@angular/platform-browser-dynamic": "~8.2.13", - "@angular/router": "~8.2.13", + "@angular/animations": "~9.1.12", + "@angular/common": "~9.1.12", + "@angular/compiler": "~9.1.12", + "@angular/core": "~9.1.12", + "@angular/forms": "~9.1.12", + "@angular/platform-browser": "~9.1.12", + "@angular/platform-browser-dynamic": "~9.1.12", + "@angular/router": "~9.1.12", "@fortawesome/angular-fontawesome": "~0.5.0", "@fortawesome/fontawesome-svg-core": "~1.2.25", "@fortawesome/free-solid-svg-icons": "~5.11.2", "bootstrap": "~4.2.1", "core-js": "~3.4.1", "rxjs": "~6.5.3", - "tslib": "~1.10.0", - "zone.js": "~0.9.1" + "tslib": "^1.10.0", + "zone.js": "~0.10.2" }, "devDependencies": { - "@angular-devkit/build-angular": "~0.803.18", - "@angular/cli": "~8.3.18", - "@angular/compiler-cli": "~8.2.13", - "@angular/language-service": "~8.2.13", + "@angular-devkit/build-angular": "~0.901.12", + "@angular/cli": "~9.1.12", + "@angular/compiler-cli": "~9.1.12", + "@angular/language-service": "~9.1.12", "@types/jasmine": "~3.4.6", "@types/jasminewd2": "~2.0.8", - "@types/node": "~12.12.7", - "codelyzer": "~5.0.1", + "@types/node": "^12.11.1", + "codelyzer": "^5.1.2", "jasmine-core": "~3.5.0", "jasmine-spec-reporter": "~4.2.1", "karma": "~4.4.1", @@ -50,13 +50,13 @@ "protractor": "~5.4.0", "ts-node": "~8.5.0", "tslint": "~5.20.1", - "typescript": "~3.5.3" + "typescript": "~3.8.3" }, "localDependencies": { "@stryker-mutator/core": "../../../packages/core", + "@stryker-mutator/instrumenter": "../../../packages/instrumenter", "@stryker-mutator/api": "../../../packages/api", "@stryker-mutator/karma-runner": "../../../packages/karma-runner", - "@stryker-mutator/typescript": "../../../packages/typescript", "@stryker-mutator/util": "../../../packages/util" } } diff --git a/perf/test/angular-cli/src/tsconfig.app.json b/perf/test/angular-cli/src/tsconfig.app.json index 190fd300b6..f3a1b80180 100644 --- a/perf/test/angular-cli/src/tsconfig.app.json +++ b/perf/test/angular-cli/src/tsconfig.app.json @@ -4,8 +4,11 @@ "outDir": "../out-tsc/app", "types": [] }, - "exclude": [ - "test.ts", - "**/*.spec.ts" + "files": [ + "main.ts", + "polyfills.ts" + ], + "include": [ + "src/**/*.d.ts" ] } diff --git a/perf/test/angular-cli/stryker.conf.js b/perf/test/angular-cli/stryker.conf.js deleted file mode 100644 index 4141e851f4..0000000000 --- a/perf/test/angular-cli/stryker.conf.js +++ /dev/null @@ -1,27 +0,0 @@ -// This config was generated using a preset. -// Please see the handbook for more information: https://github.com/stryker-mutator/stryker-handbook/blob/master/stryker/guides/angular.md#angular -module.exports = function(config) { - config.set({ - mutate: [ - "src/app/catalogus/*.ts", - "src/app/shopping-cart/*.ts", - "src/app/services/*.ts", - "!src/**/*.spec.ts" - ], - - mutator: "typescript", - testRunner: "karma", - karma: { - configFile: "src/karma.conf.js", - projectType: "angular-cli", - config: { - browsers: ["ChromeHeadless"] - } - }, - timeoutMS: 60000, - reporters: ["progress", "clear-text", "html"], - maxConcurrentTestRunners: 2, - coverageAnalysis: 'off', // Coverage analysis with a transpiler is not supported a.t.m. - tsconfigFile: 'tsconfig.json', // Location of your tsconfig.json file - }); -}; diff --git a/perf/test/angular-cli/stryker.conf.json b/perf/test/angular-cli/stryker.conf.json new file mode 100644 index 0000000000..cb8496e4cd --- /dev/null +++ b/perf/test/angular-cli/stryker.conf.json @@ -0,0 +1,21 @@ +{ + "$schema": "../../../packages/core/schema/stryker-schema.json", + "mutate": [ + "src/app/catalogus/*.ts", + "src/app/shopping-cart/*.ts", + "src/app/services/*.ts", + "!src/**/*.spec.ts" + ], + "testRunner": "karma", + "karma": { + "configFile": "src/karma.conf.js", + "projectType": "angular-cli", + "config": { + "browsers": ["ChromeHeadless"] + } + }, + "timeoutMS": 60000, + "reporters": ["progress", "clear-text", "html"], + "concurrency": 2, + "coverageAnalysis": "perTest" +} diff --git a/stryker.parent.conf.js b/stryker.parent.conf.js deleted file mode 100644 index a06bddf2f0..0000000000 --- a/stryker.parent.conf.js +++ /dev/null @@ -1,32 +0,0 @@ -module.exports = { - mutate: ['src/**/*.ts'], - coverageAnalysis: 'perTest', - tsconfigFile: 'tsconfig.stryker.json', - mutator: 'typescript', - transpilers: [ - 'typescript' - ], - mochaOptions: { - spec: ['test/helpers/**/*.js', 'test/unit/**/*.js'] - }, - testFramework: 'mocha', - testRunner: 'mocha', - reporters: ['progress', 'html', 'dashboard'], - maxConcurrentTestRunners: 4, - plugins: [ - require.resolve('./packages/mocha-runner/src/index'), - require.resolve('./packages/mocha-framework/src/index'), - require.resolve('./packages/typescript/src/index'), - ], - dashboard: { - reportType: 'full' - }, - files: [ - '{src,test,src-generated}/**/*.ts', - '!{src,test,src-generated}/**/*.d.ts', - 'schema/**/*.json', - '*', // files directly in the package directory - 'typings/**/*.ts', - ] -}; - diff --git a/stryker.parent.conf.json b/stryker.parent.conf.json new file mode 100644 index 0000000000..70a3ab9c70 --- /dev/null +++ b/stryker.parent.conf.json @@ -0,0 +1,20 @@ +{ + "$schema": "./packages/core/schema/stryker-schema.json", + "coverageAnalysis": "perTest", + "testRunner": "mocha", + "reporters": [ + "progress", + "html", + "dashboard" + ], + "plugins": [ + "../mocha-runner", + "../typescript-checker" + ], + "checkers": ["typescript"], + "dashboard": {}, + "buildCommand": "tsc -b", + "mochaOptions": { + "spec": ["test/unit/**/*.js"] + } +} diff --git a/tasks/instrument-test-resources.js b/tasks/instrument-test-resources.js new file mode 100644 index 0000000000..6da5e0f478 --- /dev/null +++ b/tasks/instrument-test-resources.js @@ -0,0 +1,35 @@ +const { Instrumenter } = require('../packages/instrumenter'); +const fs = require('fs'); +const path = require('path'); +const { File, INSTRUMENTER_CONSTANTS } = require('../packages/api/core'); + +const instrumenter = new Instrumenter({ + ...console, + isDebugEnabled() { return true; } +}); + +async function main() { + await instrument(['./packages/mocha-runner/testResources/sample-project/MyMath.js'], + './packages/mocha-runner/testResources/sample-project-instrumented', + '__stryker2__'); + await instrument([ + './packages/jasmine-runner/testResources/jasmine-init/lib/jasmine_examples/Player.js', + './packages/jasmine-runner/testResources/jasmine-init/lib/jasmine_examples/Song.js' + ], './packages/jasmine-runner/testResources/jasmine-init-instrumented/lib/jasmine_examples', + '__stryker2__'); + await instrument([ + './packages/karma-runner/testResources/sampleProject/src/Add.js', + './packages/karma-runner/testResources/sampleProject/src/Circle.js', + ], './packages/karma-runner/testResources/instrumented/src') +} + +async function instrument(from, to, globalNamespace = INSTRUMENTER_CONSTANTS.NAMESPACE) { + const files = from.map(fileName => new File(path.basename(fileName), fs.readFileSync(fileName))); + const out = await instrumenter.instrument(files, { plugins: null }); + out.files.forEach(file => { + const toFileName = path.resolve(to, file.name); + fs.writeFileSync(toFileName, `// This file is generated with ${path.relative(process.cwd(), __filename)}\n ${file.textContent.replace(new RegExp(INSTRUMENTER_CONSTANTS.NAMESPACE, 'g'), globalNamespace)}`); + console.log(`✅ ${toFileName}`); + }); +} +main(); diff --git a/tsconfig.json b/tsconfig.json index 1952064bc7..6ac870289b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,6 +4,7 @@ { "path": "packages/api" }, { "path": "packages/util" }, { "path": "packages/core" }, + { "path": "packages/instrumenter" }, { "path": "packages/babel-transpiler" }, { "path": "packages/jasmine-framework" }, { "path": "packages/jasmine-runner" }, @@ -12,8 +13,8 @@ { "path": "packages/karma-runner" }, { "path": "packages/mocha-framework" }, { "path": "packages/mocha-runner" }, - { "path": "packages/mutator-specification" }, { "path": "packages/typescript" }, + { "path": "packages/typescript-checker" }, { "path": "packages/vue-mutator" }, { "path": "packages/wct-runner" }, { "path": "packages/webpack-transpiler" }, diff --git a/tsconfig.lint.json b/tsconfig.lint.json index 91aa3ba6b6..f500c4bdde 100644 --- a/tsconfig.lint.json +++ b/tsconfig.lint.json @@ -1,9 +1,19 @@ { "extends": "./tsconfig.settings.json", - // This file is a workaround for: https://github.com/palantir/tslint/issues/4137 + // This file is a workaround for: https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/parser#parseroptionsproject "include": [ "packages/*/src", "packages/*/typings", - "packages/*/test" + "packages/*/test", + "packages/api/config.ts", + "packages/api/core.ts", + "packages/api/logging.ts", + "packages/api/mutant.ts", + "packages/api/report.ts", + "packages/api/test_framework.ts", + "packages/api/test_runner.ts", + "packages/api/test_runner2.ts", + "packages/api/transpile.ts", + "packages/api/plugin.ts" ] } diff --git a/workspace.code-workspace b/workspace.code-workspace index 37c8a1aa81..5528a9e809 100644 --- a/workspace.code-workspace +++ b/workspace.code-workspace @@ -4,6 +4,10 @@ "name": "core", "path": "packages/core" }, + { + "name": "instrumenter", + "path": "packages/instrumenter" + }, { "name": "grunt-stryker", "path": "packages/grunt-stryker" @@ -16,10 +20,6 @@ "name": "babel-transpiler", "path": "packages/babel-transpiler" }, - { - "name": "html-reporter", - "path": "packages/html-reporter" - }, { "name": "jasmine-framework", "path": "packages/jasmine-framework" @@ -48,14 +48,14 @@ "name": "mocha-runner", "path": "packages/mocha-runner" }, - { - "name": "mutator-specification", - "path": "packages/mutator-specification" - }, { "name": "typescript", "path": "packages/typescript" }, + { + "name": "typescript-checker", + "path": "packages/typescript-checker" + }, { "name": "vue-mutator", "path": "packages/vue-mutator" @@ -90,7 +90,15 @@ } ], "settings": { - "typescript.tsdk": "parent\\node_modules\\typescript\\lib", + "typescript.tsdk": "parent/node_modules/typescript/lib", + "search.exclude": { + "**/node_modules": true, + "**/bower_components": true, + "**/*.code-search": true, + "**/*.tsbuildinfo": true, + "**/.stryker-tmp": true, + "**/CHANGELOG.md": true, + }, "files.exclude": { ".git": true, ".tscache": true, @@ -120,7 +128,10 @@ }, "cSpell.words": [ "Surrializable", + "execa", "memfs", + "nocheck", + "preprocessors", "serializable", "surrialize" ]