mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 01:47:00 +01:00
split unit tests (#16455)
Co-authored-by: legobeat <109787230+legobeat@users.noreply.github.com>
This commit is contained in:
parent
01c0d7823d
commit
64839b6bf7
@ -16,6 +16,7 @@ executors:
|
|||||||
|
|
||||||
orbs:
|
orbs:
|
||||||
gh: circleci/github-cli@2.0
|
gh: circleci/github-cli@2.0
|
||||||
|
codecov: codecov/codecov@3.2.2
|
||||||
|
|
||||||
workflows:
|
workflows:
|
||||||
test_and_release:
|
test_and_release:
|
||||||
@ -93,9 +94,20 @@ workflows:
|
|||||||
- test-e2e-chrome-mv3:
|
- test-e2e-chrome-mv3:
|
||||||
requires:
|
requires:
|
||||||
- prep-build-test-mv3
|
- prep-build-test-mv3
|
||||||
- test-unit:
|
- test-unit-mocha:
|
||||||
requires:
|
requires:
|
||||||
- prep-deps
|
- prep-deps
|
||||||
|
- test-unit-jest-main:
|
||||||
|
requires:
|
||||||
|
- prep-deps
|
||||||
|
- test-unit-jest-development:
|
||||||
|
requires:
|
||||||
|
- prep-deps
|
||||||
|
- upload-and-validate-coverage:
|
||||||
|
requires:
|
||||||
|
- test-unit-jest-main
|
||||||
|
- test-unit-jest-development
|
||||||
|
- test-unit-mocha
|
||||||
- test-unit-global:
|
- test-unit-global:
|
||||||
requires:
|
requires:
|
||||||
- prep-deps
|
- prep-deps
|
||||||
@ -127,8 +139,11 @@ workflows:
|
|||||||
- test-lint-shellcheck
|
- test-lint-shellcheck
|
||||||
- test-lint-lockfile
|
- test-lint-lockfile
|
||||||
- test-lint-changelog
|
- test-lint-changelog
|
||||||
- test-unit
|
- test-unit-jest-main
|
||||||
|
- test-unit-jest-development
|
||||||
- test-unit-global
|
- test-unit-global
|
||||||
|
- test-unit-mocha
|
||||||
|
- upload-and-validate-coverage
|
||||||
- validate-source-maps
|
- validate-source-maps
|
||||||
- validate-source-maps-beta
|
- validate-source-maps-beta
|
||||||
- validate-source-maps-flask
|
- validate-source-maps-flask
|
||||||
@ -823,9 +838,6 @@ jobs:
|
|||||||
- store_artifacts:
|
- store_artifacts:
|
||||||
path: coverage
|
path: coverage
|
||||||
destination: coverage
|
destination: coverage
|
||||||
- store_artifacts:
|
|
||||||
path: jest-coverage
|
|
||||||
destination: jest-coverage
|
|
||||||
- store_artifacts:
|
- store_artifacts:
|
||||||
path: test-artifacts
|
path: test-artifacts
|
||||||
destination: test-artifacts
|
destination: test-artifacts
|
||||||
@ -902,8 +914,8 @@ jobs:
|
|||||||
git config user.email metamaskbot@users.noreply.github.com
|
git config user.email metamaskbot@users.noreply.github.com
|
||||||
yarn ts-migration:dashboard:deploy
|
yarn ts-migration:dashboard:deploy
|
||||||
|
|
||||||
test-unit:
|
test-unit-mocha:
|
||||||
executor: node-browsers
|
executor: node-browsers-medium-plus
|
||||||
steps:
|
steps:
|
||||||
- checkout
|
- checkout
|
||||||
- attach_workspace:
|
- attach_workspace:
|
||||||
@ -911,24 +923,60 @@ jobs:
|
|||||||
- run:
|
- run:
|
||||||
name: test:coverage:mocha
|
name: test:coverage:mocha
|
||||||
command: yarn test:coverage:mocha
|
command: yarn test:coverage:mocha
|
||||||
- run:
|
|
||||||
name: test:coverage:jest
|
|
||||||
command: yarn test:coverage:jest
|
|
||||||
- run:
|
|
||||||
name: Validate coverage thresholds
|
|
||||||
command: |
|
|
||||||
if ! git diff --exit-code jest.config.js development/jest.config.js; then
|
|
||||||
echo "Detected changes in coverage thresholds"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
- persist_to_workspace:
|
- persist_to_workspace:
|
||||||
root: .
|
root: .
|
||||||
paths:
|
paths:
|
||||||
- .nyc_output
|
- .nyc_output
|
||||||
- coverage
|
- coverage
|
||||||
- jest-coverage
|
|
||||||
|
test-unit-jest-development:
|
||||||
|
executor: node-browsers
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- attach_workspace:
|
||||||
|
at: .
|
||||||
|
- run:
|
||||||
|
name: jest development unit tests
|
||||||
|
command: yarn test:coverage:jest:dev
|
||||||
|
- persist_to_workspace:
|
||||||
|
root: .
|
||||||
|
paths:
|
||||||
|
- coverage
|
||||||
- store_test_results:
|
- store_test_results:
|
||||||
path: test/test-results/junit.xml
|
path: test/test-results/junit.xml
|
||||||
|
|
||||||
|
test-unit-jest-main:
|
||||||
|
executor: node-browsers-medium-plus
|
||||||
|
parallelism: 12
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- attach_workspace:
|
||||||
|
at: .
|
||||||
|
- run:
|
||||||
|
name: test:coverage:jest
|
||||||
|
command: yarn test:coverage:jest
|
||||||
|
- persist_to_workspace:
|
||||||
|
root: .
|
||||||
|
paths:
|
||||||
|
- coverage
|
||||||
|
- store_test_results:
|
||||||
|
path: test/test-results/junit.xml
|
||||||
|
|
||||||
|
upload-and-validate-coverage:
|
||||||
|
executor: node-browsers
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- attach_workspace:
|
||||||
|
at: .
|
||||||
|
- codecov/upload
|
||||||
|
- run:
|
||||||
|
name: test:coverage:validate
|
||||||
|
command: yarn test:coverage:validate
|
||||||
|
- persist_to_workspace:
|
||||||
|
root: .
|
||||||
|
paths:
|
||||||
|
- coverage
|
||||||
|
|
||||||
test-unit-global:
|
test-unit-global:
|
||||||
executor: node-browsers
|
executor: node-browsers
|
||||||
steps:
|
steps:
|
||||||
|
@ -36,6 +36,7 @@ ignores:
|
|||||||
- 'source-map-explorer'
|
- 'source-map-explorer'
|
||||||
# development tool
|
# development tool
|
||||||
- 'improved-yarn-audit'
|
- 'improved-yarn-audit'
|
||||||
|
- 'nyc'
|
||||||
# storybook
|
# storybook
|
||||||
- '@storybook/core'
|
- '@storybook/core'
|
||||||
- '@storybook/addon-essentials'
|
- '@storybook/addon-essentials'
|
||||||
|
@ -42,6 +42,8 @@ module.exports = {
|
|||||||
'test/e2e/**/*.js',
|
'test/e2e/**/*.js',
|
||||||
'test/helpers/*.js',
|
'test/helpers/*.js',
|
||||||
'test/lib/wait-until-called.js',
|
'test/lib/wait-until-called.js',
|
||||||
|
'test/run-unit-tests.js',
|
||||||
|
'test/merge-coverage.js',
|
||||||
],
|
],
|
||||||
extends: [
|
extends: [
|
||||||
path.resolve(__dirname, '.eslintrc.base.js'),
|
path.resolve(__dirname, '.eslintrc.base.js'),
|
||||||
@ -337,6 +339,8 @@ module.exports = {
|
|||||||
'development/**/*.js',
|
'development/**/*.js',
|
||||||
'test/e2e/benchmark.js',
|
'test/e2e/benchmark.js',
|
||||||
'test/helpers/setup-helper.js',
|
'test/helpers/setup-helper.js',
|
||||||
|
'test/run-unit-tests.js',
|
||||||
|
'test/merge-coverage.js',
|
||||||
],
|
],
|
||||||
rules: {
|
rules: {
|
||||||
'node/no-process-exit': 'off',
|
'node/no-process-exit': 'off',
|
||||||
|
16
codecov.yml
Normal file
16
codecov.yml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
codecov:
|
||||||
|
bot: 'codecov-io'
|
||||||
|
require_ci_to_pass: yes
|
||||||
|
coverage:
|
||||||
|
round: nearest
|
||||||
|
status:
|
||||||
|
project:
|
||||||
|
global:
|
||||||
|
target: auto
|
||||||
|
threshold: 0%
|
||||||
|
base: auto
|
||||||
|
transforms:
|
||||||
|
target: 100%
|
||||||
|
threshold: 0%
|
||||||
|
paths:
|
||||||
|
- development/build/transforms/**/*.js
|
20
coverage-targets.js
Normal file
20
coverage-targets.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// Codecov uses a yaml file for its configuration and it targets line coverage.
|
||||||
|
// To keep our policy in place we have thile file separate from our
|
||||||
|
// codecov.yml file that specifies coverage targets for each project in the
|
||||||
|
// codecov.yml file. These targets are read by the test/merge-coverage.js
|
||||||
|
// script, and the paths from the codecov.yml file are used to figure out which
|
||||||
|
// subset of files to check against these targets.
|
||||||
|
module.exports = {
|
||||||
|
global: {
|
||||||
|
branches: 20,
|
||||||
|
functions: 30,
|
||||||
|
lines: 57,
|
||||||
|
statements: 40,
|
||||||
|
},
|
||||||
|
transforms: {
|
||||||
|
branches: 100,
|
||||||
|
functions: 100,
|
||||||
|
lines: 100,
|
||||||
|
statements: 100,
|
||||||
|
},
|
||||||
|
};
|
@ -1,19 +1,11 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
displayName: '/development',
|
displayName: '/development',
|
||||||
collectCoverageFrom: ['<rootDir>/**/*.js'],
|
collectCoverageFrom: ['<rootDir>/build/transforms/**/*.js'],
|
||||||
coverageDirectory: '../jest-coverage/development/',
|
coverageDirectory: '../coverage',
|
||||||
coverageReporters: ['html', 'text-summary', 'json-summary'],
|
coverageReporters: ['json'],
|
||||||
coverageThreshold: {
|
|
||||||
'./development/build/transforms/**/*.js': {
|
|
||||||
branches: 100,
|
|
||||||
functions: 100,
|
|
||||||
lines: 100,
|
|
||||||
statements: 100,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
resetMocks: true,
|
resetMocks: true,
|
||||||
restoreMocks: true,
|
restoreMocks: true,
|
||||||
testEnvironment: 'node',
|
testEnvironment: 'node',
|
||||||
testMatch: ['<rootDir>/build/**/*.test.js'],
|
testMatch: ['<rootDir>/build/transforms/**/*.test.js'],
|
||||||
testTimeout: 2500,
|
testTimeout: 2500,
|
||||||
};
|
};
|
||||||
|
@ -1,33 +1,19 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
collectCoverageFrom: [
|
collectCoverageFrom: [
|
||||||
|
'<rootDir>/app/scripts/constants/error-utils.js',
|
||||||
|
'<rootDir>/app/scripts/controllers/network/**/*.js',
|
||||||
'<rootDir>/app/scripts/controllers/permissions/**/*.js',
|
'<rootDir>/app/scripts/controllers/permissions/**/*.js',
|
||||||
|
'<rootDir>/app/scripts/flask/**/*.js',
|
||||||
|
'<rootDir>/app/scripts/lib/**/*.js',
|
||||||
'<rootDir>/app/scripts/lib/createRPCMethodTrackingMiddleware.js',
|
'<rootDir>/app/scripts/lib/createRPCMethodTrackingMiddleware.js',
|
||||||
|
'<rootDir>/app/scripts/migrations/*.js',
|
||||||
|
'<rootDir>/app/scripts/platforms/*.js',
|
||||||
'<rootDir>/shared/**/*.js',
|
'<rootDir>/shared/**/*.js',
|
||||||
'<rootDir>/ui/**/*.js',
|
'<rootDir>/ui/**/*.js',
|
||||||
],
|
],
|
||||||
coverageDirectory: './jest-coverage/main',
|
coverageDirectory: './coverage',
|
||||||
coveragePathIgnorePatterns: ['.stories.js', '.snap'],
|
coveragePathIgnorePatterns: ['.stories.js', '.snap'],
|
||||||
coverageReporters: ['html', 'text-summary', 'json-summary'],
|
coverageReporters: ['json'],
|
||||||
coverageThreshold: {
|
|
||||||
global: {
|
|
||||||
branches: 48,
|
|
||||||
functions: 46,
|
|
||||||
lines: 52,
|
|
||||||
statements: 52,
|
|
||||||
},
|
|
||||||
'./app/scripts/controllers/permissions/**/*.js': {
|
|
||||||
branches: 100,
|
|
||||||
functions: 100,
|
|
||||||
lines: 100,
|
|
||||||
statements: 100,
|
|
||||||
},
|
|
||||||
'./app/scripts/lib/createRPCMethodTrackingMiddleware.js': {
|
|
||||||
branches: 95.65,
|
|
||||||
functions: 100,
|
|
||||||
lines: 100,
|
|
||||||
statements: 100,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
reporters: [
|
reporters: [
|
||||||
'default',
|
'default',
|
||||||
[
|
[
|
||||||
@ -48,16 +34,16 @@ module.exports = {
|
|||||||
],
|
],
|
||||||
setupFilesAfterEnv: ['<rootDir>/test/jest/setup.js'],
|
setupFilesAfterEnv: ['<rootDir>/test/jest/setup.js'],
|
||||||
testMatch: [
|
testMatch: [
|
||||||
'<rootDir>/ui/**/*.test.js',
|
'<rootDir>/app/scripts/constants/error-utils.test.js',
|
||||||
'<rootDir>/shared/**/*.test.js',
|
|
||||||
'<rootDir>/app/scripts/lib/**/*.test.js',
|
|
||||||
'<rootDir>/app/scripts/migrations/*.test.js',
|
|
||||||
'<rootDir>/app/scripts/platforms/*.test.js',
|
|
||||||
'<rootDir>/app/scripts/controllers/network/**/*.test.js',
|
'<rootDir>/app/scripts/controllers/network/**/*.test.js',
|
||||||
'<rootDir>/app/scripts/controllers/permissions/**/*.test.js',
|
'<rootDir>/app/scripts/controllers/permissions/**/*.test.js',
|
||||||
'<rootDir>/app/scripts/flask/**/*.test.js',
|
'<rootDir>/app/scripts/flask/**/*.test.js',
|
||||||
|
'<rootDir>/app/scripts/lib/**/*.test.js',
|
||||||
'<rootDir>/app/scripts/lib/createRPCMethodTrackingMiddleware.test.js',
|
'<rootDir>/app/scripts/lib/createRPCMethodTrackingMiddleware.test.js',
|
||||||
'<rootDir>/app/scripts/constants/error-utils.test.js',
|
'<rootDir>/app/scripts/migrations/*.test.js',
|
||||||
|
'<rootDir>/app/scripts/platforms/*.test.js',
|
||||||
|
'<rootDir>/shared/**/*.test.js',
|
||||||
|
'<rootDir>/ui/**/*.test.js',
|
||||||
],
|
],
|
||||||
testTimeout: 2500,
|
testTimeout: 2500,
|
||||||
// We have to specify the environment we are running in, which is jsdom. The
|
// We have to specify the environment we are running in, which is jsdom. The
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
branches: 95,
|
|
||||||
lines: 95,
|
|
||||||
functions: 95,
|
|
||||||
statements: 95,
|
|
||||||
};
|
|
17
package.json
17
package.json
@ -26,17 +26,21 @@
|
|||||||
"dapp-chain": "GANACHE_ARGS='-b 2' concurrently -k -n ganache,dapp -p '[{time}][{name}]' 'yarn ganache:start' 'sleep 5 && yarn dapp'",
|
"dapp-chain": "GANACHE_ARGS='-b 2' concurrently -k -n ganache,dapp -p '[{time}][{name}]' 'yarn ganache:start' 'sleep 5 && yarn dapp'",
|
||||||
"forwarder": "node ./development/static-server.js ./node_modules/@metamask/forwarder/dist/ --port 9010",
|
"forwarder": "node ./development/static-server.js ./node_modules/@metamask/forwarder/dist/ --port 9010",
|
||||||
"dapp-forwarder": "concurrently -k -n forwarder,dapp -p '[{time}][{name}]' 'yarn forwarder' 'yarn dapp'",
|
"dapp-forwarder": "concurrently -k -n forwarder,dapp -p '[{time}][{name}]' 'yarn forwarder' 'yarn dapp'",
|
||||||
"test:unit": "./test/test-unit-combined.sh",
|
"test:unit": "node ./test/run-unit-tests.js --mocha --jestGlobal --jestDev",
|
||||||
"test:unit:jest": "./test/test-unit-jest.sh",
|
"test:unit:jest": "./test/test-unit-jest.sh",
|
||||||
"test:unit:global": "mocha test/unit-global/*.test.js",
|
"test:unit:global": "mocha test/unit-global/*.test.js",
|
||||||
"test:unit:mocha": "mocha './app/**/*.test.js'",
|
"test:unit:mocha": "node ./test/run-unit-tests.js --mocha",
|
||||||
"test:e2e:chrome": "SELENIUM_BROWSER=chrome node test/e2e/run-all.js",
|
"test:e2e:chrome": "SELENIUM_BROWSER=chrome node test/e2e/run-all.js",
|
||||||
"test:e2e:chrome:snaps": "SELENIUM_BROWSER=chrome node test/e2e/run-all.js --snaps",
|
"test:e2e:chrome:snaps": "SELENIUM_BROWSER=chrome node test/e2e/run-all.js --snaps",
|
||||||
"test:e2e:firefox": "SELENIUM_BROWSER=firefox node test/e2e/run-all.js",
|
"test:e2e:firefox": "SELENIUM_BROWSER=firefox node test/e2e/run-all.js",
|
||||||
"test:e2e:firefox:snaps": "SELENIUM_BROWSER=firefox node test/e2e/run-all.js --snaps",
|
"test:e2e:firefox:snaps": "SELENIUM_BROWSER=firefox node test/e2e/run-all.js --snaps",
|
||||||
"test:e2e:single": "node test/e2e/run-e2e-test.js",
|
"test:e2e:single": "node test/e2e/run-e2e-test.js",
|
||||||
"test:coverage:mocha": "nyc --reporter=text --reporter=html yarn test:unit:mocha",
|
"test:coverage:mocha": "node ./test/run-unit-tests.js --mocha --coverage",
|
||||||
"test:coverage:jest": "yarn test:unit:jest --coverage --maxWorkers=2 && yarn jest-it-up -m 5",
|
"test:coverage:jest": "node ./test/run-unit-tests.js --jestGlobal --coverage",
|
||||||
|
"test:coverage:jest:dev": "node ./test/run-unit-tests.js --jestDev --coverage",
|
||||||
|
"test:coverage:validate": "node ./test/merge-coverage.js",
|
||||||
|
"test:coverage": "node ./test/run-unit-tests.js --mocha --jestGlobal --jestDev --coverage && yarn test:coverage:validate",
|
||||||
|
"test:coverage:html": "yarn test:coverage --html",
|
||||||
"ganache:start": "./development/run-ganache.sh",
|
"ganache:start": "./development/run-ganache.sh",
|
||||||
"sentry:publish": "node ./development/sentry-publish.js",
|
"sentry:publish": "node ./development/sentry-publish.js",
|
||||||
"lint": "yarn lint:prettier && yarn lint:eslint && yarn lint:tsc && yarn lint:styles",
|
"lint": "yarn lint:prettier && yarn lint:eslint && yarn lint:tsc && yarn lint:styles",
|
||||||
@ -447,10 +451,13 @@
|
|||||||
"history": "^5.0.0",
|
"history": "^5.0.0",
|
||||||
"improved-yarn-audit": "^3.0.0",
|
"improved-yarn-audit": "^3.0.0",
|
||||||
"ini": "^3.0.0",
|
"ini": "^3.0.0",
|
||||||
|
"istanbul-lib-coverage": "^3.2.0",
|
||||||
|
"istanbul-lib-report": "^3.0.0",
|
||||||
|
"istanbul-reports": "^3.1.5",
|
||||||
"jest": "^29.1.2",
|
"jest": "^29.1.2",
|
||||||
"jest-canvas-mock": "^2.3.1",
|
"jest-canvas-mock": "^2.3.1",
|
||||||
"jest-environment-jsdom": "^29.1.2",
|
"jest-environment-jsdom": "^29.1.2",
|
||||||
"jest-it-up": "^2.0.2",
|
"js-yaml": "^4.1.0",
|
||||||
"jsdom": "^11.2.0",
|
"jsdom": "^11.2.0",
|
||||||
"koa": "^2.7.0",
|
"koa": "^2.7.0",
|
||||||
"lavamoat": "^6.2.0",
|
"lavamoat": "^6.2.0",
|
||||||
|
245
test/merge-coverage.js
Normal file
245
test/merge-coverage.js
Normal file
@ -0,0 +1,245 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const libCoverage = require('istanbul-lib-coverage');
|
||||||
|
const libReport = require('istanbul-lib-report');
|
||||||
|
const reports = require('istanbul-reports');
|
||||||
|
const glob = require('fast-glob');
|
||||||
|
const yargs = require('yargs/yargs');
|
||||||
|
const { hideBin } = require('yargs/helpers');
|
||||||
|
const yaml = require('js-yaml');
|
||||||
|
const codecovTargets = require('../coverage-targets');
|
||||||
|
|
||||||
|
const codecovConfig = yaml.load(fs.readFileSync('codecov.yml', 'utf8'));
|
||||||
|
|
||||||
|
const COVERAGE_DIR = './coverage/';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load .json file at path and parse it into a javascript object
|
||||||
|
*
|
||||||
|
* @param {string} filePath - path to the file to load
|
||||||
|
* @returns {object} the JavaScript object parsed from the file
|
||||||
|
*/
|
||||||
|
function loadData(filePath) {
|
||||||
|
const json = fs.readFileSync(filePath);
|
||||||
|
return JSON.parse(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads an array of json coverage files and merges them into a final coverage
|
||||||
|
* report.
|
||||||
|
*
|
||||||
|
* @param {string[]} files - array of strings that are paths to files
|
||||||
|
* @returns {libCoverage.CoverageMap} CoverageMap
|
||||||
|
*/
|
||||||
|
function mergeCoverageMaps(files) {
|
||||||
|
const coverageMap = libCoverage.createCoverageMap({});
|
||||||
|
|
||||||
|
files.forEach((covergeFinalFile) => {
|
||||||
|
coverageMap.merge(loadData(covergeFinalFile));
|
||||||
|
});
|
||||||
|
|
||||||
|
return coverageMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given a target directory and a coverageMap generates a finalized coverage
|
||||||
|
* summary report and saves it to the directory.
|
||||||
|
*
|
||||||
|
* @param {string} dir - target directory
|
||||||
|
* @param {libCoverage.CoverageMap} coverageMap - CoverageMap to report on
|
||||||
|
* @param reportType
|
||||||
|
* @param reportOptions
|
||||||
|
*/
|
||||||
|
function generateSummaryReport(dir, coverageMap, reportType, reportOptions) {
|
||||||
|
const context = libReport.createContext({
|
||||||
|
dir,
|
||||||
|
coverageMap,
|
||||||
|
});
|
||||||
|
|
||||||
|
reports.create(reportType, reportOptions ?? {}).execute(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a multiline string with coverage data
|
||||||
|
*
|
||||||
|
* @param {CoverageTarget} target - Target coverage threshold
|
||||||
|
* @param {import('istanbul-lib-coverage').CoverageSummaryData} actual -
|
||||||
|
* istanbul coverage summary detailing actual summary
|
||||||
|
* @returns {string} multiline report of coverage
|
||||||
|
*/
|
||||||
|
function generateConsoleReport(target, actual) {
|
||||||
|
const { lines, branches, functions, statements } = actual.data;
|
||||||
|
const breakdown =
|
||||||
|
`Lines: ${lines.covered}/${lines.total} (${lines.pct}%). Target: ${target.lines}%\n` +
|
||||||
|
`Branches: ${branches.covered}/${branches.total} (${branches.pct}%). Target: ${target.branches}%\n` +
|
||||||
|
`Statements: ${statements.covered}/${statements.total} (${statements.pct}%). Target: ${target.statements}%\n` +
|
||||||
|
`Functions: ${functions.covered}/${functions.total} (${functions.pct}%). Target: ${target.functions}%`;
|
||||||
|
return breakdown;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {object} CoverageTarget
|
||||||
|
* @property {number} lines - percentage of lines that must be covered
|
||||||
|
* @property {number} statements - percentage of statements that must be covered
|
||||||
|
* @property {number} branches - percentage of branches that must be covered
|
||||||
|
* @property {number} functions - percentage of functions that must be covered
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the coverage meets target
|
||||||
|
*
|
||||||
|
* @param {CoverageTarget} target
|
||||||
|
* @param {import('istanbul-lib-coverage').CoverageSummaryData} actual
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
function isCoverageInsufficient(target, actual) {
|
||||||
|
const lineCoverageNotMet = actual.lines.pct < target.lines;
|
||||||
|
const branchCoverageNotMet = actual.branches.pct < target.branches;
|
||||||
|
const functionCoverageNotMet = actual.functions.pct < target.functions;
|
||||||
|
const statementCoverageNotMet = actual.statements.pct < target.statements;
|
||||||
|
return (
|
||||||
|
lineCoverageNotMet ||
|
||||||
|
branchCoverageNotMet ||
|
||||||
|
functionCoverageNotMet ||
|
||||||
|
statementCoverageNotMet
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the coverage should be bumped up
|
||||||
|
*
|
||||||
|
* @param {CoverageTarget} target
|
||||||
|
* @param {import('istanbul-lib-coverage').CoverageSummaryData} actual
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
function shouldCoverageBeBumped(target, actual) {
|
||||||
|
const lineCoverageNeedsBumped = actual.lines.pct > target.lines + 5;
|
||||||
|
const branchCoverageNeedsBumped = actual.branches.pct > target.branches + 5;
|
||||||
|
const functionCoverageNeedsBumped =
|
||||||
|
actual.functions.pct > target.functions + 5;
|
||||||
|
const statementCoverageNeedsBumped =
|
||||||
|
actual.statements.pct > target.statements + 5;
|
||||||
|
return (
|
||||||
|
lineCoverageNeedsBumped ||
|
||||||
|
branchCoverageNeedsBumped ||
|
||||||
|
functionCoverageNeedsBumped ||
|
||||||
|
statementCoverageNeedsBumped
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and returns a combined coverage summary report of every file in the
|
||||||
|
* provided array.
|
||||||
|
*
|
||||||
|
* @param {string[]} files - array of files generated by fast-glob
|
||||||
|
* @param {libCoverage.CoverageMap} coverageMap
|
||||||
|
* @returns {import('istanbul-lib-coverage').CoverageSummaryData}
|
||||||
|
*/
|
||||||
|
function getFileCoverage(files, coverageMap) {
|
||||||
|
const subCoverageMap = libCoverage.createCoverageMap({});
|
||||||
|
|
||||||
|
files.forEach((file) => {
|
||||||
|
try {
|
||||||
|
subCoverageMap.merge(
|
||||||
|
coverageMap.fileCoverageFor(`${process.cwd()}/${file}`),
|
||||||
|
);
|
||||||
|
} catch {
|
||||||
|
// If the coverage doesn't exist, it means that it was excluded from
|
||||||
|
// coverage or had no coverage to report, which is fine. Glob is a lot
|
||||||
|
// wider of a net then what the test file runners match against.
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const summary = subCoverageMap.getCoverageSummary();
|
||||||
|
return summary;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks coverage and reports to console
|
||||||
|
* Throws an error if coverage isn't met
|
||||||
|
*
|
||||||
|
* @param {string} name - The target's name from coverageThresholds in jest
|
||||||
|
* config
|
||||||
|
* @param {CoverageTarget} target - the target coverage threshold
|
||||||
|
* @param {import('istanbul-lib-coverage').CoverageSummaryData} actual -
|
||||||
|
* istanbul coverage summary representing actual coverage
|
||||||
|
*/
|
||||||
|
function checkCoverage(name, target, actual) {
|
||||||
|
const breakdown = generateConsoleReport(target, actual);
|
||||||
|
if (isCoverageInsufficient(target, actual)) {
|
||||||
|
const errorMsg = `Coverage thresholds for ${name} NOT met\n${breakdown}`;
|
||||||
|
throw new Error(errorMsg);
|
||||||
|
} else if (shouldCoverageBeBumped(target, actual)) {
|
||||||
|
const errorMsg = `Coverage EXCEEDS threshold for ${name} and must be bumped\n${breakdown}`;
|
||||||
|
throw new Error(errorMsg);
|
||||||
|
}
|
||||||
|
console.log(`Coverage thresholds for ${name} met\n${breakdown}\n\n`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Primary script function
|
||||||
|
*/
|
||||||
|
async function start() {
|
||||||
|
const {
|
||||||
|
argv: { html },
|
||||||
|
} = yargs(hideBin(process.argv)).usage(
|
||||||
|
'$0 [options]',
|
||||||
|
'Run unit tests on the application code.',
|
||||||
|
(yargsInstance) =>
|
||||||
|
yargsInstance
|
||||||
|
.option('html', {
|
||||||
|
alias: ['h'],
|
||||||
|
default: false,
|
||||||
|
description: 'Generate HTML report',
|
||||||
|
type: 'boolean',
|
||||||
|
})
|
||||||
|
.strict(),
|
||||||
|
);
|
||||||
|
// First get all of the files matching the pattern coverage-final-${n}.json
|
||||||
|
// from the coverage directory
|
||||||
|
const files = fs.readdirSync(COVERAGE_DIR);
|
||||||
|
const filePaths = files
|
||||||
|
.filter(
|
||||||
|
(file) =>
|
||||||
|
path.basename(file).startsWith('coverage-final') &&
|
||||||
|
path.extname(file) === '.json',
|
||||||
|
)
|
||||||
|
.map((file) => path.join(COVERAGE_DIR, file));
|
||||||
|
|
||||||
|
// Next, generate a coverageMap
|
||||||
|
const coverageMap = mergeCoverageMaps(filePaths, true);
|
||||||
|
|
||||||
|
// Persist this to file, which may eventually be used in more steps
|
||||||
|
generateSummaryReport(COVERAGE_DIR, coverageMap, 'json-summary');
|
||||||
|
if (html) {
|
||||||
|
generateSummaryReport(COVERAGE_DIR, coverageMap, 'html');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the keys in coverageThreshold in jest config to determine targets
|
||||||
|
const coverageTargets = Object.keys(codecovConfig.coverage.status.project);
|
||||||
|
|
||||||
|
// Check coverage totals for each target
|
||||||
|
coverageTargets.forEach((target) => {
|
||||||
|
const summary =
|
||||||
|
target === 'global'
|
||||||
|
? coverageMap.getCoverageSummary()
|
||||||
|
: getFileCoverage(
|
||||||
|
glob.sync([
|
||||||
|
...codecovConfig.coverage.status.project[target].paths,
|
||||||
|
// checking test file coverage is redundant.
|
||||||
|
'!**/*.test.js',
|
||||||
|
'!**/__mocks__/**/*.js',
|
||||||
|
'!**/*.stories.js',
|
||||||
|
]),
|
||||||
|
coverageMap,
|
||||||
|
);
|
||||||
|
// Check and validate the coverage
|
||||||
|
checkCoverage(target, codecovTargets[target], summary);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
start().catch((error) => {
|
||||||
|
// Report the errored coverage check
|
||||||
|
console.error(error);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
192
test/run-unit-tests.js
Normal file
192
test/run-unit-tests.js
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
const { hideBin } = require('yargs/helpers');
|
||||||
|
const yargs = require('yargs/yargs');
|
||||||
|
const { runCommand, runInShell } = require('../development/lib/run-command');
|
||||||
|
|
||||||
|
const { CIRCLE_NODE_INDEX, CIRCLE_NODE_TOTAL } = process.env;
|
||||||
|
|
||||||
|
const GLOBAL_JEST_CONFIG = './jest.config.js';
|
||||||
|
const DEVELOPMENT_JEST_CONFIG = './development/jest.config.js';
|
||||||
|
|
||||||
|
start().catch((error) => {
|
||||||
|
console.error(error);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {object} JestParams
|
||||||
|
* @property {'global' | 'dev'} target - Which configuration to use for Jest.
|
||||||
|
* @property {boolean} [coverage] - Whether to collect coverage during testing.
|
||||||
|
* @property {number} [currentShard] - Current process number when using test
|
||||||
|
* splitting across many processes.
|
||||||
|
* @property {number} [totalShards] - Total number of processes tests will be
|
||||||
|
* split across.
|
||||||
|
* @property {number} [maxWorkers] - Total number of workers to use when
|
||||||
|
* running tests.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute jest test runner with given params
|
||||||
|
*
|
||||||
|
* @param {JestParams} params - Configuration for jest test runner
|
||||||
|
*/
|
||||||
|
async function runJest(
|
||||||
|
{ target, coverage, currentShard, totalShards, maxWorkers } = {
|
||||||
|
target: 'global',
|
||||||
|
coverage: false,
|
||||||
|
currentShard: 1,
|
||||||
|
totalShards: 1,
|
||||||
|
maxWorkers: 2,
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
const options = [
|
||||||
|
'jest',
|
||||||
|
`--config=${
|
||||||
|
target === 'global' ? GLOBAL_JEST_CONFIG : DEVELOPMENT_JEST_CONFIG
|
||||||
|
}`,
|
||||||
|
];
|
||||||
|
options.push(`--maxWorkers=${maxWorkers}`);
|
||||||
|
if (coverage) {
|
||||||
|
options.push('--coverage');
|
||||||
|
}
|
||||||
|
// We use jest's new 'shard' feature to run tests in parallel across many
|
||||||
|
// different processes if totalShards > 1
|
||||||
|
if (totalShards > 1) {
|
||||||
|
options.push(`--shard=${currentShard}/${totalShards}`);
|
||||||
|
}
|
||||||
|
await runInShell('yarn', options);
|
||||||
|
if (coverage) {
|
||||||
|
// Once done we rename the coverage file so that it is unique among test
|
||||||
|
// runners and job number
|
||||||
|
await runCommand('mv', [
|
||||||
|
'./coverage/coverage-final.json',
|
||||||
|
`./coverage/coverage-final-${target}-${currentShard}.json`,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run mocha tests on the app directory. Mocha tests do not yet support
|
||||||
|
* parallelism / test-splitting.
|
||||||
|
*
|
||||||
|
* @param {boolean} coverage - Use nyc to collect coverage
|
||||||
|
*/
|
||||||
|
async function runMocha({ coverage }) {
|
||||||
|
const options = ['mocha', './app/**/*.test.js'];
|
||||||
|
// If coverage is true, then we need to run nyc as the first command
|
||||||
|
// and mocha after, so we use unshift to add three options to the beginning
|
||||||
|
// of the options array.
|
||||||
|
if (coverage) {
|
||||||
|
options.unshift('nyc', '--reporter=json', 'yarn');
|
||||||
|
}
|
||||||
|
await runInShell('yarn', options);
|
||||||
|
if (coverage) {
|
||||||
|
// Once done we rename the coverage file so that it is unique among test
|
||||||
|
// runners
|
||||||
|
await runCommand('mv', [
|
||||||
|
'./coverage/coverage-final.json',
|
||||||
|
`./coverage/coverage-final-mocha.json`,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function start() {
|
||||||
|
const {
|
||||||
|
argv: { mocha, jestGlobal, jestDev, coverage, fakeParallelism, maxWorkers },
|
||||||
|
} = yargs(hideBin(process.argv)).usage(
|
||||||
|
'$0 [options]',
|
||||||
|
'Run unit tests on the application code.',
|
||||||
|
(yargsInstance) =>
|
||||||
|
yargsInstance
|
||||||
|
.option('mocha', {
|
||||||
|
alias: ['m'],
|
||||||
|
default: false,
|
||||||
|
description: 'Run Mocha tests',
|
||||||
|
type: 'boolean',
|
||||||
|
})
|
||||||
|
.option('jestDev', {
|
||||||
|
alias: ['d'],
|
||||||
|
default: false,
|
||||||
|
description: 'Run Jest tests with development folder config',
|
||||||
|
type: 'boolean',
|
||||||
|
})
|
||||||
|
.option('jestGlobal', {
|
||||||
|
alias: ['g'],
|
||||||
|
default: false,
|
||||||
|
demandOption: false,
|
||||||
|
description: 'Run Jest global (primary config) tests',
|
||||||
|
type: 'boolean',
|
||||||
|
})
|
||||||
|
.option('coverage', {
|
||||||
|
alias: ['c'],
|
||||||
|
default: true,
|
||||||
|
demandOption: false,
|
||||||
|
description: 'Collect coverage',
|
||||||
|
type: 'boolean',
|
||||||
|
})
|
||||||
|
.option('fakeParallelism', {
|
||||||
|
alias: ['f'],
|
||||||
|
default: 0,
|
||||||
|
demandOption: false,
|
||||||
|
description:
|
||||||
|
'Pretend to be CircleCI and fake parallelism (use at your own risk)',
|
||||||
|
type: 'number',
|
||||||
|
})
|
||||||
|
.option('maxWorkers', {
|
||||||
|
alias: ['mw'],
|
||||||
|
default: 2,
|
||||||
|
demandOption: false,
|
||||||
|
description:
|
||||||
|
'The safer way to increase performance locally, sets the number of processes to use internally. Recommended 2',
|
||||||
|
type: 'number',
|
||||||
|
})
|
||||||
|
.strict(),
|
||||||
|
);
|
||||||
|
|
||||||
|
const circleNodeIndex = parseInt(CIRCLE_NODE_INDEX ?? '0', 10);
|
||||||
|
const circleNodeTotal = parseInt(CIRCLE_NODE_TOTAL ?? '1', 10);
|
||||||
|
|
||||||
|
const maxProcesses = fakeParallelism > 0 ? fakeParallelism : circleNodeTotal;
|
||||||
|
const currentProcess = circleNodeIndex;
|
||||||
|
|
||||||
|
if (fakeParallelism) {
|
||||||
|
console.log(
|
||||||
|
`Using fake parallelism of ${fakeParallelism}. Your machine may become as useful as a brick during this operation.`,
|
||||||
|
);
|
||||||
|
if (jestGlobal && jestDev) {
|
||||||
|
throw new Error(
|
||||||
|
'Do not try to run both jest test configs with fakeParallelism, bad things could happen.',
|
||||||
|
);
|
||||||
|
} else if (mocha) {
|
||||||
|
throw new Error('Test splitting is not supported for mocha yet.');
|
||||||
|
} else {
|
||||||
|
const processes = [];
|
||||||
|
for (let x = 0; x < fakeParallelism; x++) {
|
||||||
|
processes.push(
|
||||||
|
runJest({
|
||||||
|
target: jestGlobal ? 'global' : 'dev',
|
||||||
|
totalShards: fakeParallelism,
|
||||||
|
currentShard: x + 1,
|
||||||
|
maxWorkers: 1, // ignore maxWorker option on purpose
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
await Promise.all(processes);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const options = {
|
||||||
|
coverage,
|
||||||
|
currentShard: currentProcess + 1,
|
||||||
|
totalShards: maxProcesses,
|
||||||
|
maxWorkers,
|
||||||
|
};
|
||||||
|
if (mocha) {
|
||||||
|
await runMocha(options);
|
||||||
|
}
|
||||||
|
if (jestDev) {
|
||||||
|
await runJest({ target: 'dev', ...options });
|
||||||
|
}
|
||||||
|
if (jestGlobal) {
|
||||||
|
await runJest({ target: 'global', ...options });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -x
|
|
||||||
set -e
|
|
||||||
set -u
|
|
||||||
set -o pipefail
|
|
||||||
|
|
||||||
concurrently --raw -n mocha,jest,global \
|
|
||||||
"yarn test:unit:mocha" \
|
|
||||||
"yarn test:unit:jest" \
|
|
||||||
"yarn test:unit:global"
|
|
@ -1,10 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -x
|
|
||||||
set -e
|
|
||||||
set -u
|
|
||||||
set -o pipefail
|
|
||||||
|
|
||||||
concurrently -n production,development \
|
|
||||||
"jest --config=./jest.config.js $*" \
|
|
||||||
"jest --config=./development/jest.config.js $*"
|
|
95
yarn.lock
95
yarn.lock
@ -2621,44 +2621,6 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@inquirer/confirm@npm:^0.0.14-alpha.0":
|
|
||||||
version: 0.0.14-alpha.0
|
|
||||||
resolution: "@inquirer/confirm@npm:0.0.14-alpha.0"
|
|
||||||
dependencies:
|
|
||||||
"@inquirer/core": ^0.0.15-alpha.0
|
|
||||||
"@inquirer/input": ^0.0.15-alpha.0
|
|
||||||
chalk: ^4.1.1
|
|
||||||
checksum: 84daf47030318e0adf6eeef85388e341f6f68c0c06c0d1d329cb6185f6d21abf74c3124102bf62f4f42145c8dc9193d719209e3759987a1bdbcfb88139b9936c
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"@inquirer/core@npm:^0.0.15-alpha.0":
|
|
||||||
version: 0.0.15-alpha.0
|
|
||||||
resolution: "@inquirer/core@npm:0.0.15-alpha.0"
|
|
||||||
dependencies:
|
|
||||||
ansi-escapes: ^4.2.1
|
|
||||||
chalk: ^4.1.1
|
|
||||||
cli-spinners: ^2.6.0
|
|
||||||
cli-width: ^3.0.0
|
|
||||||
lodash: ^4.17.21
|
|
||||||
mute-stream: ^0.0.8
|
|
||||||
run-async: ^2.3.0
|
|
||||||
string-width: ^4.1.0
|
|
||||||
strip-ansi: ^6.0.0
|
|
||||||
checksum: 26a94a8db80e57f926c889b5730c6c9a0f18d6bf1e6dbfb68eaa6bcda33550db66118ce6afd9e91130ea2e4da42b6d7236b94c16fbab931ed04b4f442b9a5c78
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"@inquirer/input@npm:^0.0.15-alpha.0":
|
|
||||||
version: 0.0.15-alpha.0
|
|
||||||
resolution: "@inquirer/input@npm:0.0.15-alpha.0"
|
|
||||||
dependencies:
|
|
||||||
"@inquirer/core": ^0.0.15-alpha.0
|
|
||||||
chalk: ^4.1.1
|
|
||||||
checksum: c294b2fa100e2955e271b1b0590b5f360c65c560d653f39554cd381f145fdf13be9ea2c3c069d39a71f84fc3c8ba20d9d78a0b210f8cb5533d138567029e28ee
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"@istanbuljs/load-nyc-config@npm:^1.0.0":
|
"@istanbuljs/load-nyc-config@npm:^1.0.0":
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
resolution: "@istanbuljs/load-nyc-config@npm:1.0.0"
|
resolution: "@istanbuljs/load-nyc-config@npm:1.0.0"
|
||||||
@ -8363,13 +8325,6 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"ansi-colors@npm:^4.1.0":
|
|
||||||
version: 4.1.1
|
|
||||||
resolution: "ansi-colors@npm:4.1.1"
|
|
||||||
checksum: 138d04a51076cb085da0a7e2d000c5c0bb09f6e772ed5c65c53cb118d37f6c5f1637506d7155fb5f330f0abcf6f12fa2e489ac3f8cdab9da393bf1bb4f9a32b0
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"ansi-escapes@npm:^4.2.1":
|
"ansi-escapes@npm:^4.2.1":
|
||||||
version: 4.3.0
|
version: 4.3.0
|
||||||
resolution: "ansi-escapes@npm:4.3.0"
|
resolution: "ansi-escapes@npm:4.3.0"
|
||||||
@ -11227,7 +11182,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"cli-spinners@npm:^2.5.0, cli-spinners@npm:^2.6.0":
|
"cli-spinners@npm:^2.5.0":
|
||||||
version: 2.6.1
|
version: 2.6.1
|
||||||
resolution: "cli-spinners@npm:2.6.1"
|
resolution: "cli-spinners@npm:2.6.1"
|
||||||
checksum: 423409baaa7a58e5104b46ca1745fbfc5888bbd0b0c5a626e052ae1387060839c8efd512fb127e25769b3dc9562db1dc1b5add6e0b93b7ef64f477feb6416a45
|
checksum: 423409baaa7a58e5104b46ca1745fbfc5888bbd0b0c5a626e052ae1387060839c8efd512fb127e25769b3dc9562db1dc1b5add6e0b93b7ef64f477feb6416a45
|
||||||
@ -11247,13 +11202,6 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"cli-width@npm:^3.0.0":
|
|
||||||
version: 3.0.0
|
|
||||||
resolution: "cli-width@npm:3.0.0"
|
|
||||||
checksum: 4c94af3769367a70e11ed69aa6095f1c600c0ff510f3921ab4045af961820d57c0233acfa8b6396037391f31b4c397e1f614d234294f979ff61430a6c166c3f6
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"cliui@npm:^3.2.0":
|
"cliui@npm:^3.2.0":
|
||||||
version: 3.2.0
|
version: 3.2.0
|
||||||
resolution: "cliui@npm:3.2.0"
|
resolution: "cliui@npm:3.2.0"
|
||||||
@ -11614,13 +11562,6 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"commander@npm:^9.0.0":
|
|
||||||
version: 9.2.0
|
|
||||||
resolution: "commander@npm:9.2.0"
|
|
||||||
checksum: 7c82e4cd969712aa6d7c055b8351807a7230f9f31ef7ec7881e11a1147511de85adf5d6ccfd200240a118eecf693b220caf6865b8efbcea558a70d35aa9ed711
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"comment-parser@npm:1.3.1":
|
"comment-parser@npm:1.3.1":
|
||||||
version: 1.3.1
|
version: 1.3.1
|
||||||
resolution: "comment-parser@npm:1.3.1"
|
resolution: "comment-parser@npm:1.3.1"
|
||||||
@ -20149,7 +20090,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"istanbul-reports@npm:^3.0.0, istanbul-reports@npm:^3.1.3":
|
"istanbul-reports@npm:^3.0.0, istanbul-reports@npm:^3.1.3, istanbul-reports@npm:^3.1.5":
|
||||||
version: 3.1.5
|
version: 3.1.5
|
||||||
resolution: "istanbul-reports@npm:3.1.5"
|
resolution: "istanbul-reports@npm:3.1.5"
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -20437,19 +20378,6 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"jest-it-up@npm:^2.0.2":
|
|
||||||
version: 2.0.2
|
|
||||||
resolution: "jest-it-up@npm:2.0.2"
|
|
||||||
dependencies:
|
|
||||||
"@inquirer/confirm": ^0.0.14-alpha.0
|
|
||||||
ansi-colors: ^4.1.0
|
|
||||||
commander: ^9.0.0
|
|
||||||
bin:
|
|
||||||
jest-it-up: bin/jest-it-up
|
|
||||||
checksum: 1482d8b9862331b6cc7d858fd1c05d95fb1bc2adbc37e243c20e6e10f259fecf600d3b1023dadf11acadb158ea171677f8f375969e058dff46002be81a49079b
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"jest-junit@npm:^14.0.1":
|
"jest-junit@npm:^14.0.1":
|
||||||
version: 14.0.1
|
version: 14.0.1
|
||||||
resolution: "jest-junit@npm:14.0.1"
|
resolution: "jest-junit@npm:14.0.1"
|
||||||
@ -23126,11 +23054,14 @@ __metadata:
|
|||||||
improved-yarn-audit: ^3.0.0
|
improved-yarn-audit: ^3.0.0
|
||||||
ini: ^3.0.0
|
ini: ^3.0.0
|
||||||
is-retry-allowed: ^2.2.0
|
is-retry-allowed: ^2.2.0
|
||||||
|
istanbul-lib-coverage: ^3.2.0
|
||||||
|
istanbul-lib-report: ^3.0.0
|
||||||
|
istanbul-reports: ^3.1.5
|
||||||
jest: ^29.1.2
|
jest: ^29.1.2
|
||||||
jest-canvas-mock: ^2.3.1
|
jest-canvas-mock: ^2.3.1
|
||||||
jest-environment-jsdom: ^29.1.2
|
jest-environment-jsdom: ^29.1.2
|
||||||
jest-it-up: ^2.0.2
|
|
||||||
jest-junit: ^14.0.1
|
jest-junit: ^14.0.1
|
||||||
|
js-yaml: ^4.1.0
|
||||||
jsdom: ^11.2.0
|
jsdom: ^11.2.0
|
||||||
json-rpc-engine: ^6.1.0
|
json-rpc-engine: ^6.1.0
|
||||||
json-rpc-middleware-stream: ^2.1.1
|
json-rpc-middleware-stream: ^2.1.1
|
||||||
@ -23985,13 +23916,6 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"mute-stream@npm:^0.0.8":
|
|
||||||
version: 0.0.8
|
|
||||||
resolution: "mute-stream@npm:0.0.8"
|
|
||||||
checksum: ff48d251fc3f827e5b1206cda0ffdaec885e56057ee86a3155e1951bc940fd5f33531774b1cc8414d7668c10a8907f863f6561875ee6e8768931a62121a531a1
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"nan@npm:^2.12.1, nan@npm:^2.13.2, nan@npm:^2.14.0":
|
"nan@npm:^2.12.1, nan@npm:^2.13.2, nan@npm:^2.14.0":
|
||||||
version: 2.15.0
|
version: 2.15.0
|
||||||
resolution: "nan@npm:2.15.0"
|
resolution: "nan@npm:2.15.0"
|
||||||
@ -29048,13 +28972,6 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"run-async@npm:^2.3.0":
|
|
||||||
version: 2.4.1
|
|
||||||
resolution: "run-async@npm:2.4.1"
|
|
||||||
checksum: a2c88aa15df176f091a2878eb840e68d0bdee319d8d97bbb89112223259cebecb94bc0defd735662b83c2f7a30bed8cddb7d1674eb48ae7322dc602b22d03797
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"run-parallel@npm:^1.1.9":
|
"run-parallel@npm:^1.1.9":
|
||||||
version: 1.1.9
|
version: 1.1.9
|
||||||
resolution: "run-parallel@npm:1.1.9"
|
resolution: "run-parallel@npm:1.1.9"
|
||||||
|
Loading…
Reference in New Issue
Block a user