diff --git a/package.json b/package.json index dc2100f385a6..2d2921aa58b7 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,6 @@ "babel-jest": "workspace:*", "babel-loader": "^9.0.0", "camelcase": "^6.2.0", - "chalk": "^4.0.0", "dedent": "^1.0.0", "eslint": "^8.8.0", "eslint-config-prettier": "^10.0.0", @@ -66,6 +65,7 @@ "netlify-plugin-cache": "^1.0.3", "node-notifier": "^10.0.0", "p-limit": "^3.1.0", + "picocolors": "^1.1.1", "pkg-dir": "^5.0.0", "prettier": "^3.0.3", "promise": "^8.0.2", diff --git a/packages/babel-jest/package.json b/packages/babel-jest/package.json index 5ad598091288..c4176f70b0f9 100644 --- a/packages/babel-jest/package.json +++ b/packages/babel-jest/package.json @@ -24,8 +24,8 @@ "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^7.0.0", "babel-preset-jest": "workspace:*", - "chalk": "^4.0.0", "graceful-fs": "^4.2.9", + "picocolors": "^1.1.1", "slash": "^3.0.0" }, "devDependencies": { diff --git a/packages/babel-jest/src/index.ts b/packages/babel-jest/src/index.ts index b67b93de8781..820b92b71cd0 100644 --- a/packages/babel-jest/src/index.ts +++ b/packages/babel-jest/src/index.ts @@ -13,8 +13,8 @@ import { transformSync as babelTransform, transformAsync as babelTransformAsync, } from '@babel/core'; -import chalk = require('chalk'); import * as fs from 'graceful-fs'; +import * as pc from 'picocolors'; import slash = require('slash'); import type { TransformOptions as JestTransformOptions, @@ -38,9 +38,9 @@ function assertLoadedBabelConfig( ): asserts babelConfig { if (!babelConfig) { throw new Error( - `babel-jest: Babel ignores ${chalk.bold( + `babel-jest: Babel ignores ${pc.bold( slash(path.relative(cwd, filename)), - )} - make sure to include the file in Jest's ${chalk.bold( + )} - make sure to include the file in Jest's ${pc.bold( 'transformIgnorePatterns', )} as well.`, ); diff --git a/packages/create-jest/package.json b/packages/create-jest/package.json index 745b04c7169e..e4f2be6c67d7 100644 --- a/packages/create-jest/package.json +++ b/packages/create-jest/package.json @@ -23,11 +23,11 @@ }, "dependencies": { "@jest/types": "workspace:*", - "chalk": "^4.0.0", "exit-x": "^0.2.2", "graceful-fs": "^4.2.9", "jest-config": "workspace:*", "jest-util": "workspace:*", + "picocolors": "^1.1.1", "prompts": "^2.0.1" }, "engines": { diff --git a/packages/create-jest/src/runCreate.ts b/packages/create-jest/src/runCreate.ts index f544c76c35a0..2d343d0b38f4 100644 --- a/packages/create-jest/src/runCreate.ts +++ b/packages/create-jest/src/runCreate.ts @@ -6,9 +6,9 @@ */ import * as path from 'path'; -import chalk = require('chalk'); import exit = require('exit-x'); import * as fs from 'graceful-fs'; +import picocolors = require('picocolors'); import prompts = require('prompts'); import {constants} from 'jest-config'; import {clearLine, tryRealpath} from 'jest-util'; @@ -37,9 +37,9 @@ export async function runCLI(): Promise { clearLine(process.stderr); clearLine(process.stdout); if (error instanceof Error && Boolean(error?.stack)) { - console.error(chalk.red(error.stack)); + console.error(picocolors.red(error.stack)); } else { - console.error(chalk.red(error)); + console.error(picocolors.red(String(error))); } exit(1); @@ -103,7 +103,7 @@ export async function runCreate(rootDir = process.cwd()): Promise { // Start the init process console.log(); console.log( - chalk.underline( + picocolors.underline( 'The following questions will help Jest to create a suitable configuration for your project\n', ), ); @@ -146,7 +146,7 @@ export async function runCreate(rootDir = process.cwd()): Promise { fs.writeFileSync(projectPackageJsonPath, modifiedPackageJson); console.log(''); - console.log(`✏️ Modified ${chalk.cyan(projectPackageJsonPath)}`); + console.log(`✏️ Modified ${picocolors.cyan(projectPackageJsonPath)}`); } const generatedConfig = generateConfigFile( @@ -159,6 +159,6 @@ export async function runCreate(rootDir = process.cwd()): Promise { console.log(''); console.log( - `📝 Configuration file created at ${chalk.cyan(jestConfigPath)}`, + `📝 Configuration file created at ${picocolors.cyan(jestConfigPath)}`, ); } diff --git a/packages/expect/package.json b/packages/expect/package.json index d1eb4c88ea22..3e424341ebb1 100644 --- a/packages/expect/package.json +++ b/packages/expect/package.json @@ -31,7 +31,6 @@ "devDependencies": { "@fast-check/jest": "^2.0.0", "@jest/test-utils": "workspace:*", - "chalk": "^4.0.0", "immutable": "^5.0.0" }, "engines": { diff --git a/packages/expect/src/__tests__/matchers.test.js b/packages/expect/src/__tests__/matchers.test.js index 6f636471a494..8a26e5bc22c6 100644 --- a/packages/expect/src/__tests__/matchers.test.js +++ b/packages/expect/src/__tests__/matchers.test.js @@ -5,12 +5,10 @@ * LICENSE file in the root directory of this source tree. */ -const chalk = require('chalk'); const Immutable = require('immutable'); const {alignedAnsiStyleSerializer} = require('@jest/test-utils'); const {stringify} = require('jest-matcher-utils'); const {expect: jestExpect} = require('../'); -const chalkEnabled = chalk.enabled; expect.addSnapshotSerializer(alignedAnsiStyleSerializer); @@ -21,14 +19,6 @@ jestExpect.extend({ }, }); -beforeAll(() => { - chalk.enabled = true; -}); - -afterAll(() => { - chalk.enabled = chalkEnabled; -}); - it('should throw if passed two arguments', () => { expect(() => jestExpect('foo', 'bar')).toThrow( new Error('Expect takes at most one argument.'), diff --git a/packages/jest-circus/package.json b/packages/jest-circus/package.json index 1e4aa7411daa..f834f518705a 100644 --- a/packages/jest-circus/package.json +++ b/packages/jest-circus/package.json @@ -25,7 +25,6 @@ "@jest/test-result": "workspace:*", "@jest/types": "workspace:*", "@types/node": "*", - "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^1.0.0", "is-generator-fn": "^2.0.0", @@ -36,6 +35,7 @@ "jest-snapshot": "workspace:*", "jest-util": "workspace:*", "p-limit": "^3.1.0", + "picocolors": "^1.1.1", "pretty-format": "workspace:*", "pure-rand": "^6.0.0", "slash": "^3.0.0", diff --git a/packages/jest-circus/src/formatNodeAssertErrors.ts b/packages/jest-circus/src/formatNodeAssertErrors.ts index 3d617aa78475..a9579192ff7a 100644 --- a/packages/jest-circus/src/formatNodeAssertErrors.ts +++ b/packages/jest-circus/src/formatNodeAssertErrors.ts @@ -6,7 +6,7 @@ */ import {AssertionError} from 'assert'; -import chalk = require('chalk'); +import * as pc from 'picocolors'; import type {Circus} from '@jest/types'; import { type DiffOptions, @@ -93,10 +93,10 @@ const operatorMessage = (operator: string | undefined) => { const assertThrowingMatcherHint = (operatorName: string) => operatorName - ? chalk.dim('assert') + - chalk.dim(`.${operatorName}(`) + - chalk.red('function') + - chalk.dim(')') + ? pc.dim('assert') + + pc.dim(`.${operatorName}(`) + + pc.red('function') + + pc.dim(')') : ''; const assertMatcherHint = ( @@ -107,19 +107,15 @@ const assertMatcherHint = ( let message = ''; if (operator === '==' && expected === true) { - message = - chalk.dim('assert') + - chalk.dim('(') + - chalk.red('received') + - chalk.dim(')'); + message = pc.dim('assert') + pc.dim('(') + pc.red('received') + pc.dim(')'); } else if (operatorName) { message = - chalk.dim('assert') + - chalk.dim(`.${operatorName}(`) + - chalk.red('received') + - chalk.dim(', ') + - chalk.green('expected') + - chalk.dim(')'); + pc.dim('assert') + + pc.dim(`.${operatorName}(`) + + pc.red('received') + + pc.dim(', ') + + pc.green('expected') + + pc.dim(')'); } return message; @@ -141,10 +137,10 @@ function assertionErrorMessage( return ( // eslint-disable-next-line prefer-template buildHintString(assertThrowingMatcherHint(operatorName)) + - chalk.reset('Expected the function not to throw an error.\n') + - chalk.reset('Instead, it threw:\n') + + pc.reset('Expected the function not to throw an error.\n') + + pc.reset('Instead, it threw:\n') + ` ${printReceived(actual)}` + - chalk.reset(hasCustomMessage ? `\n\nMessage:\n ${message}` : '') + + pc.reset(hasCustomMessage ? `\n\nMessage:\n ${message}` : '') + trimmedStack ); } @@ -153,16 +149,16 @@ function assertionErrorMessage( if (error.generatedMessage) { return ( buildHintString(assertThrowingMatcherHint(operatorName)) + - chalk.reset(error.message) + - chalk.reset(hasCustomMessage ? `\n\nMessage:\n ${message}` : '') + + pc.reset(error.message) + + pc.reset(hasCustomMessage ? `\n\nMessage:\n ${message}` : '') + trimmedStack ); } return ( buildHintString(assertThrowingMatcherHint(operatorName)) + - chalk.reset('Expected the function to throw an error.\n') + - chalk.reset("But it didn't throw anything.") + - chalk.reset(hasCustomMessage ? `\n\nMessage:\n ${message}` : '') + + pc.reset('Expected the function to throw an error.\n') + + pc.reset("But it didn't throw anything.") + + pc.reset(hasCustomMessage ? `\n\nMessage:\n ${message}` : '') + trimmedStack ); } @@ -170,7 +166,7 @@ function assertionErrorMessage( if (operatorName === 'fail') { return ( buildHintString(assertMatcherHint(operator, operatorName, expected)) + - chalk.reset(hasCustomMessage ? `Message:\n ${message}` : '') + + pc.reset(hasCustomMessage ? `Message:\n ${message}` : '') + trimmedStack ); } @@ -178,11 +174,11 @@ function assertionErrorMessage( return ( // eslint-disable-next-line prefer-template buildHintString(assertMatcherHint(operator, operatorName, expected)) + - chalk.reset(`Expected value ${operatorMessage(operator)}`) + + pc.reset(`Expected value ${operatorMessage(operator)}`) + ` ${printExpected(expected)}\n` + - chalk.reset('Received:\n') + + pc.reset('Received:\n') + ` ${printReceived(actual)}` + - chalk.reset(hasCustomMessage ? `\n\nMessage:\n ${message}` : '') + + pc.reset(hasCustomMessage ? `\n\nMessage:\n ${message}` : '') + (diffString ? `\n\nDifference:\n\n${diffString}` : '') + trimmedStack ); diff --git a/packages/jest-cli/package.json b/packages/jest-cli/package.json index 0860288e9f11..a0d199b9e2cc 100644 --- a/packages/jest-cli/package.json +++ b/packages/jest-cli/package.json @@ -18,12 +18,12 @@ "@jest/core": "workspace:*", "@jest/test-result": "workspace:*", "@jest/types": "workspace:*", - "chalk": "^4.0.0", "exit-x": "^0.2.2", "import-local": "^3.0.2", "jest-config": "workspace:*", "jest-util": "workspace:*", "jest-validate": "workspace:*", + "picocolors": "^1.1.1", "yargs": "^17.3.1" }, "devDependencies": { diff --git a/packages/jest-cli/src/run.ts b/packages/jest-cli/src/run.ts index fca08629a9a4..198998ed4be3 100644 --- a/packages/jest-cli/src/run.ts +++ b/packages/jest-cli/src/run.ts @@ -6,8 +6,8 @@ */ import * as path from 'path'; -import chalk = require('chalk'); import exit = require('exit-x'); +import * as pc from 'picocolors'; import yargs = require('yargs'); import {getVersion, runCLI} from '@jest/core'; import type {AggregatedResult} from '@jest/test-result'; @@ -31,9 +31,9 @@ export async function run( clearLine(process.stderr); clearLine(process.stdout); if (error?.stack) { - console.error(chalk.red(error.stack)); + console.error(pc.red(error.stack)); } else { - console.error(chalk.red(error)); + console.error(pc.red(error)); } exit(1); @@ -117,7 +117,7 @@ const readResultsAndExit = ( if (globalConfig.forceExit) { if (!globalConfig.detectOpenHandles) { console.warn( - `${chalk.bold( + `${pc.bold( 'Force exiting Jest: ', )}Have you considered using \`--detectOpenHandles\` to detect ` + 'async operations that kept running after all tests finished?', @@ -132,12 +132,14 @@ const readResultsAndExit = ( const timeout = globalConfig.openHandlesTimeout; setTimeout(() => { console.warn( - chalk.yellow.bold( - `Jest did not exit ${ - timeout === 1000 ? 'one second' : `${timeout / 1000} seconds` - } after the test run has completed.\n\n'`, + pc.yellow( + pc.bold( + `Jest did not exit ${ + timeout === 1000 ? 'one second' : `${timeout / 1000} seconds` + } after the test run has completed.\n\n'`, + ), ) + - chalk.yellow( + pc.yellow( 'This usually means that there are asynchronous operations that ' + "weren't stopped in your tests. Consider running Jest with " + '`--detectOpenHandles` to troubleshoot this issue.', diff --git a/packages/jest-config/package.json b/packages/jest-config/package.json index 19690b2b80dc..06ef23b29c08 100644 --- a/packages/jest-config/package.json +++ b/packages/jest-config/package.json @@ -40,7 +40,6 @@ "@jest/test-sequencer": "workspace:*", "@jest/types": "workspace:*", "babel-jest": "workspace:*", - "chalk": "^4.0.0", "ci-info": "^4.0.0", "deepmerge": "^4.2.2", "glob": "^10.3.10", @@ -56,6 +55,7 @@ "jest-validate": "workspace:*", "micromatch": "^4.0.8", "parse-json": "^5.2.0", + "picocolors": "^1.1.1", "pretty-format": "workspace:*", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" diff --git a/packages/jest-config/src/Deprecated.ts b/packages/jest-config/src/Deprecated.ts index c319f13d2be4..74f9dfe452de 100644 --- a/packages/jest-config/src/Deprecated.ts +++ b/packages/jest-config/src/Deprecated.ts @@ -5,12 +5,12 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); +import * as pc from 'picocolors'; import type {DeprecatedOptions} from 'jest-validate'; function formatDeprecation(message: string): string { const lines = [ - message.replaceAll(/\*(.+?)\*/g, (_, s) => chalk.bold(`"${s}"`)), + message.replaceAll(/\*(.+?)\*/g, (_, s) => pc.bold(`"${s}"`)), '', 'Please update your configuration.', ]; @@ -19,40 +19,40 @@ function formatDeprecation(message: string): string { const deprecatedOptions: DeprecatedOptions = { browser: () => - ` Option ${chalk.bold( + ` Option ${pc.bold( '"browser"', )} has been deprecated. Please install "browser-resolve" and use the "resolver" option in Jest configuration as shown in the documentation: https://jestjs.io/docs/configuration#resolver-string`, collectCoverageOnlyFrom: (_options: { collectCoverageOnlyFrom?: Record; - }) => ` Option ${chalk.bold( + }) => ` Option ${pc.bold( '"collectCoverageOnlyFrom"', - )} was replaced by ${chalk.bold('"collectCoverageFrom"')}. + )} was replaced by ${pc.bold('"collectCoverageFrom"')}. Please update your configuration.`, - extraGlobals: (_options: {extraGlobals?: string}) => ` Option ${chalk.bold( + extraGlobals: (_options: {extraGlobals?: string}) => ` Option ${pc.bold( '"extraGlobals"', - )} was replaced by ${chalk.bold('"sandboxInjectedGlobals"')}. + )} was replaced by ${pc.bold('"sandboxInjectedGlobals"')}. Please update your configuration.`, init: () => - ` Option ${chalk.bold( + ` Option ${pc.bold( '"init"', )} has been deprecated. Please use "create-jest" package as shown in the documentation: https://jestjs.io/docs/getting-started#generate-a-basic-configuration-file`, - moduleLoader: (_options: {moduleLoader?: string}) => ` Option ${chalk.bold( + moduleLoader: (_options: {moduleLoader?: string}) => ` Option ${pc.bold( '"moduleLoader"', - )} was replaced by ${chalk.bold('"runtime"')}. + )} was replaced by ${pc.bold('"runtime"')}. Please update your configuration.`, preprocessorIgnorePatterns: (_options: { preprocessorIgnorePatterns?: Array; - }) => ` Option ${chalk.bold( + }) => ` Option ${pc.bold( '"preprocessorIgnorePatterns"', - )} was replaced by ${chalk.bold( + )} was replaced by ${pc.bold( '"transformIgnorePatterns"', )}, which support multiple preprocessors. @@ -60,9 +60,7 @@ const deprecatedOptions: DeprecatedOptions = { scriptPreprocessor: (_options: { scriptPreprocessor?: string; - }) => ` Option ${chalk.bold( - '"scriptPreprocessor"', - )} was replaced by ${chalk.bold( + }) => ` Option ${pc.bold('"scriptPreprocessor"')} was replaced by ${pc.bold( '"transform"', )}, which support multiple preprocessors. @@ -70,9 +68,9 @@ const deprecatedOptions: DeprecatedOptions = { setupTestFrameworkScriptFile: (_options: { setupTestFrameworkScriptFile?: string; - }) => ` Option ${chalk.bold( + }) => ` Option ${pc.bold( '"setupTestFrameworkScriptFile"', - )} was replaced by configuration ${chalk.bold( + )} was replaced by configuration ${pc.bold( '"setupFilesAfterEnv"', )}, which supports multiple paths. @@ -80,7 +78,7 @@ const deprecatedOptions: DeprecatedOptions = { testPathDirs: (_options: { testPathDirs?: Array; - }) => ` Option ${chalk.bold('"testPathDirs"')} was replaced by ${chalk.bold( + }) => ` Option ${pc.bold('"testPathDirs"')} was replaced by ${pc.bold( '"roots"', )}. @@ -92,17 +90,17 @@ const deprecatedOptions: DeprecatedOptions = { 'Option *testPathPattern* was replaced by *testPathPatterns*.', ), - testURL: (_options: {testURL?: string}) => ` Option ${chalk.bold( + testURL: (_options: {testURL?: string}) => ` Option ${pc.bold( '"testURL"', - )} was replaced by passing the URL via ${chalk.bold( + )} was replaced by passing the URL via ${pc.bold( '"testEnvironmentOptions.url"', )}. Please update your configuration.`, - timers: (_options: {timers?: string}) => ` Option ${chalk.bold( + timers: (_options: {timers?: string}) => ` Option ${pc.bold( '"timers"', - )} was replaced by ${chalk.bold('"fakeTimers"')}. + )} was replaced by ${pc.bold('"fakeTimers"')}. Please update your configuration.`, }; diff --git a/packages/jest-config/src/ReporterValidationErrors.ts b/packages/jest-config/src/ReporterValidationErrors.ts index 661d91a4ce6f..bf3adc4c9b76 100644 --- a/packages/jest-config/src/ReporterValidationErrors.ts +++ b/packages/jest-config/src/ReporterValidationErrors.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); +import * as pc from 'picocolors'; import type {Config} from '@jest/types'; import {getType} from 'jest-get-type'; import {ValidationError} from 'jest-validate'; @@ -28,9 +28,9 @@ export function createReporterError( ): ValidationError { const errorMessage = ` Reporter at index ${reporterIndex} must be of type:\n` + - ` ${chalk.bold.green(validReporterTypes.join(' or '))}\n` + + ` ${pc.bold(pc.green(validReporterTypes.join(' or ')))}\n` + ' but instead received:\n' + - ` ${chalk.bold.red(getType(reporterValue))}`; + ` ${pc.bold(pc.red(getType(reporterValue)))}`; return new ValidationError(ERROR, errorMessage, DOCUMENTATION_NOTE); } @@ -47,12 +47,14 @@ export function createArrayReporterError( ` Unexpected value for ${valueName} ` + `at index ${valueIndex} of reporter at index ${reporterIndex}\n` + ' Expected:\n' + - ` ${chalk.bold.red(expectedType)}\n` + + ` ${pc.bold(pc.red(expectedType))}\n` + ' Got:\n' + - ` ${chalk.bold.green(getType(value))}\n` + + ` ${pc.bold(pc.green(getType(value)))}\n` + ' Reporter configuration:\n' + - ` ${chalk.bold.green( - JSON.stringify(arrayReporter, null, 2).split('\n').join('\n '), + ` ${pc.bold( + pc.green( + JSON.stringify(arrayReporter, null, 2).split('\n').join('\n '), + ), )}`; return new ValidationError(ERROR, errorMessage, DOCUMENTATION_NOTE); diff --git a/packages/jest-config/src/color.ts b/packages/jest-config/src/color.ts index c9ff80d4c22f..bfbb05eed5bc 100644 --- a/packages/jest-config/src/color.ts +++ b/packages/jest-config/src/color.ts @@ -6,9 +6,8 @@ */ import {createHash} from 'crypto'; -import type {ForegroundColor} from 'chalk'; -type Color = typeof ForegroundColor; +type Color = 'red' | 'green' | 'yellow' | 'blue' | 'magenta' | 'cyan' | 'white'; const colors: Array = [ 'red', diff --git a/packages/jest-config/src/index.ts b/packages/jest-config/src/index.ts index 8523938629ca..44bc0f663205 100644 --- a/packages/jest-config/src/index.ts +++ b/packages/jest-config/src/index.ts @@ -6,8 +6,8 @@ */ import * as path from 'path'; -import chalk = require('chalk'); import * as fs from 'graceful-fs'; +import * as pc from 'picocolors'; import type {Config} from '@jest/types'; import {tryRealpath} from 'jest-util'; import * as constants from './constants'; @@ -228,16 +228,16 @@ const ensureNoDuplicateConfigs = ( const {configPath} = config; if (configPathMap.has(configPath)) { - const message = `Whoops! Two projects resolved to the same config path: ${chalk.bold( + const message = `Whoops! Two projects resolved to the same config path: ${pc.bold( String(configPath), )}: - Project 1: ${chalk.bold(projects[parsedConfigs.indexOf(config)])} - Project 2: ${chalk.bold( + Project 1: ${pc.bold(projects[parsedConfigs.indexOf(config)])} + Project 2: ${pc.bold( projects[parsedConfigs.indexOf(configPathMap.get(configPath))], )} -This usually means that your ${chalk.bold( +This usually means that your ${pc.bold( '"projects"', )} config includes a directory that doesn't have any configuration recognizable by Jest. Please fix it. `; diff --git a/packages/jest-config/src/normalize.ts b/packages/jest-config/src/normalize.ts index a0724cc09754..1edbaa360726 100644 --- a/packages/jest-config/src/normalize.ts +++ b/packages/jest-config/src/normalize.ts @@ -8,11 +8,11 @@ import {createHash} from 'crypto'; import {totalmem} from 'os'; import * as path from 'path'; -import chalk = require('chalk'); import merge = require('deepmerge'); import {glob} from 'glob'; import {statSync} from 'graceful-fs'; import micromatch = require('micromatch'); +import * as pc from 'picocolors'; import {TestPathPatterns} from '@jest/pattern'; import type {Config} from '@jest/types'; import {replacePathSepForRegex} from 'jest-regex-util'; @@ -69,9 +69,7 @@ function verifyDirectoryExists(path: string, key: string) { if (!rootStat.isDirectory()) { throw createConfigError( - ` ${chalk.bold(path)} in the ${chalk.bold( - key, - )} option is not a directory.`, + ` ${pc.bold(path)} in the ${pc.bold(key)} option is not a directory.`, ); } } catch (error: any) { @@ -81,7 +79,7 @@ function verifyDirectoryExists(path: string, key: string) { if (error.code === 'ENOENT') { throw createConfigError( - ` Directory ${chalk.bold(path)} in the ${chalk.bold( + ` Directory ${pc.bold(path)} in the ${pc.bold( key, )} option was not found.`, ); @@ -89,7 +87,7 @@ function verifyDirectoryExists(path: string, key: string) { // Not sure in which cases `statSync` can throw, so let's just show the underlying error to the user throw createConfigError( - ` Got an error trying to find ${chalk.bold(path)} in the ${chalk.bold( + ` Got an error trying to find ${pc.bold(path)} in the ${pc.bold( key, )} option.\n\n Error was: ${error.message}`, ); @@ -149,7 +147,7 @@ const setupPreset = async ( } catch (error: any) { if (error instanceof SyntaxError || error instanceof TypeError) { throw createConfigError( - ` Preset ${chalk.bold(presetPath)} is invalid:\n\n ${ + ` Preset ${pc.bold(presetPath)} is invalid:\n\n ${ error.message }\n ${error.stack}`, ); @@ -163,24 +161,24 @@ const setupPreset = async ( if (preset) { throw createConfigError( - ` Module ${chalk.bold( + ` Module ${pc.bold( presetPath, )} should have "jest-preset.js" or "jest-preset.json" file at the root.`, ); } throw createConfigError( - ` Preset ${chalk.bold(presetPath)} not found relative to rootDir ${chalk.bold(options.rootDir)}.`, + ` Preset ${pc.bold(presetPath)} not found relative to rootDir ${pc.bold(options.rootDir)}.`, ); } throw createConfigError( - ` Missing dependency in ${chalk.bold(presetPath)}:\n\n ${ + ` Missing dependency in ${pc.bold(presetPath)}:\n\n ${ error.message }\n ${error.stack}`, ); } throw createConfigError( - ` An unknown error occurred in ${chalk.bold(presetPath)}:\n\n ${ + ` An unknown error occurred in ${pc.bold(presetPath)}:\n\n ${ error.message }\n ${error.stack}`, ); @@ -331,7 +329,7 @@ const normalizeRootDir = ( // Assert that there *is* a rootDir if (!options.rootDir) { throw createConfigError( - ` Configuration option ${chalk.bold('rootDir')} must be specified.`, + ` Configuration option ${pc.bold('rootDir')} must be specified.`, ); } options.rootDir = path.normalize(options.rootDir); @@ -410,7 +408,7 @@ const buildTestPathPatterns = (argv: Config.Argv): TestPathPatterns => { // eslint-disable-next-line no-console console.log( - chalk.red( + pc.red( ` Invalid testPattern ${testPathPatterns.toPretty()} supplied. ` + 'Running all tests instead.', ), @@ -425,7 +423,7 @@ const buildTestPathPatterns = (argv: Config.Argv): TestPathPatterns => { function printConfig(opts: Array) { const string = opts.map(ext => `'${ext}'`).join(', '); - return chalk.bold(`extensionsToTreatAsEsm: [${string}]`); + return pc.bold(`extensionsToTreatAsEsm: [${string}]`); } function validateExtensionsToTreatAsEsm( @@ -443,9 +441,7 @@ function validateExtensionsToTreatAsEsm( throw createConfigError( ` Option: ${printConfig( extensionsToTreatAsEsm, - )} includes a string that does not start with a period (${chalk.bold( - '.', - )}). + )} includes a string that does not start with a period (${pc.bold('.')}). Please change your configuration to ${printConfig( extensionsToTreatAsEsm.map(ext => (ext.startsWith('.') ? ext : `.${ext}`)), )}.`, @@ -454,17 +450,17 @@ function validateExtensionsToTreatAsEsm( if (extensionsToTreatAsEsm.includes('.js')) { throw createConfigError( - ` Option: ${printConfig(extensionsToTreatAsEsm)} includes ${chalk.bold( + ` Option: ${printConfig(extensionsToTreatAsEsm)} includes ${pc.bold( "'.js'", - )} which is always inferred based on ${chalk.bold( + )} which is always inferred based on ${pc.bold( 'type', - )} in its nearest ${chalk.bold('package.json')}.`, + )} in its nearest ${pc.bold('package.json')}.`, ); } if (extensionsToTreatAsEsm.includes('.cjs')) { throw createConfigError( - ` Option: ${printConfig(extensionsToTreatAsEsm)} includes ${chalk.bold( + ` Option: ${printConfig(extensionsToTreatAsEsm)} includes ${pc.bold( "'.cjs'", )} which is always treated as CommonJS.`, ); @@ -472,7 +468,7 @@ function validateExtensionsToTreatAsEsm( if (extensionsToTreatAsEsm.includes('.mjs')) { throw createConfigError( - ` Option: ${printConfig(extensionsToTreatAsEsm)} includes ${chalk.bold( + ` Option: ${printConfig(extensionsToTreatAsEsm)} includes ${pc.bold( "'.mjs'", )} which is always treated as an ECMAScript Module.`, ); @@ -805,7 +801,7 @@ export default async function normalize( const errorMessage = " moduleFileExtensions must include 'js':\n" + ' but instead received:\n' + - ` ${chalk.bold.red(JSON.stringify(value))}`; + ` ${pc.bold(pc.red(JSON.stringify(value)))}`; // If `js` is not included, any dependency Jest itself injects into // the environment, like jasmine or sourcemap-support, will need to @@ -852,7 +848,7 @@ export default async function normalize( typeof color !== 'string' ) { const errorMessage = - ` Option "${chalk.bold('displayName')}" must be of type:\n\n` + + ` Option "${pc.bold('displayName')}" must be of type:\n\n` + ' {\n' + ' name: string;\n' + ' color: string;\n' + @@ -871,7 +867,7 @@ export default async function normalize( case 'testTimeout': { if (oldOptions[key] < 0) { throw createConfigError( - ` Option "${chalk.bold('testTimeout')}" must be a natural number.`, + ` Option "${pc.bold('testTimeout')}" must be a natural number.`, ); } @@ -1096,8 +1092,8 @@ export default async function normalize( if (newOptions.testRegex.length > 0 && options.testMatch) { throw createConfigError( - ` Configuration options ${chalk.bold('testMatch')} and` + - ` ${chalk.bold('testRegex')} cannot be used together.`, + ` Configuration options ${pc.bold('testMatch')} and` + + ` ${pc.bold('testRegex')} cannot be used together.`, ); } diff --git a/packages/jest-config/src/resolveConfigPath.ts b/packages/jest-config/src/resolveConfigPath.ts index d6cd21da82d2..bb281e199514 100644 --- a/packages/jest-config/src/resolveConfigPath.ts +++ b/packages/jest-config/src/resolveConfigPath.ts @@ -6,8 +6,8 @@ */ import * as path from 'path'; -import chalk = require('chalk'); import * as fs from 'graceful-fs'; +import * as pc from 'picocolors'; import slash = require('slash'); import {ValidationError} from 'jest-validate'; import { @@ -88,9 +88,9 @@ const resolveConfigPathByTraversing = ( if (!isFile(absolutePath)) { throw new ValidationError( `${BULLET}Validation Error`, - ` Configuration in ${chalk.bold(packageJson)} is not valid. ` + + ` Configuration in ${pc.bold(packageJson)} is not valid. ` + `Jest expects the string configuration to point to a file, but ${absolutePath} is not. ` + - `Please check your Jest configuration in ${chalk.bold( + `Please check your Jest configuration in ${pc.bold( packageJson, )}.`, DOCUMENTATION_NOTE, @@ -171,7 +171,7 @@ function extraIfPackageJson(configPath: string) { const makeMultipleConfigsErrorMessage = ( configPaths: Array, ): [string, string, string] => [ - `${BULLET}${chalk.bold('Multiple configurations found')}`, + `${BULLET}${pc.bold('Multiple configurations found')}`, [ ...configPaths.map( configPath => diff --git a/packages/jest-config/src/utils.ts b/packages/jest-config/src/utils.ts index 78be841f767e..7f580c391467 100644 --- a/packages/jest-config/src/utils.ts +++ b/packages/jest-config/src/utils.ts @@ -6,7 +6,7 @@ */ import * as path from 'path'; -import chalk = require('chalk'); +import * as pc from 'picocolors'; import Resolver from 'jest-resolve'; import {ValidationError} from 'jest-validate'; @@ -17,10 +17,8 @@ type ResolveOptions = { optional?: boolean; }; -export const BULLET: string = chalk.bold('\u25CF '); -export const DOCUMENTATION_NOTE = ` ${chalk.bold( - 'Configuration Documentation:', -)} +export const BULLET: string = pc.bold('\u25CF '); +export const DOCUMENTATION_NOTE = ` ${pc.bold('Configuration Documentation:')} https://jestjs.io/docs/configuration `; @@ -41,10 +39,10 @@ export const resolve = ( if (!module && !optional) { throw createValidationError( - ` Module ${chalk.bold(filePath)} in the ${chalk.bold( + ` Module ${pc.bold(filePath)} in the ${pc.bold( key, )} option was not found. - ${chalk.bold('')} is: ${rootDir}`, + ${pc.bold('')} is: ${rootDir}`, ); } /// can cast as string since nulls will be thrown diff --git a/packages/jest-console/package.json b/packages/jest-console/package.json index 96cb61baabc9..ea02896761bf 100644 --- a/packages/jest-console/package.json +++ b/packages/jest-console/package.json @@ -21,9 +21,9 @@ "dependencies": { "@jest/types": "workspace:*", "@types/node": "*", - "chalk": "^4.0.0", "jest-message-util": "workspace:*", "jest-util": "workspace:*", + "picocolors": "^1.1.1", "slash": "^3.0.0" }, "devDependencies": { diff --git a/packages/jest-console/src/BufferedConsole.ts b/packages/jest-console/src/BufferedConsole.ts index 21162ac14289..5b0e06b404f6 100644 --- a/packages/jest-console/src/BufferedConsole.ts +++ b/packages/jest-console/src/BufferedConsole.ts @@ -8,7 +8,7 @@ import {AssertionError, strict as assert} from 'assert'; import {Console} from 'console'; import {type InspectOptions, format, formatWithOptions, inspect} from 'util'; -import chalk = require('chalk'); +import * as pc from 'picocolors'; import {ErrorWithStack, formatTime, invariant} from 'jest-util'; import type { ConsoleBuffer, @@ -116,7 +116,7 @@ export default class BufferedConsole extends Console { this._groupDepth++; if (title != null || rest.length > 0) { - this._log('group', chalk.bold(format(title, ...rest))); + this._log('group', pc.bold(format(title, ...rest))); } } @@ -124,7 +124,7 @@ export default class BufferedConsole extends Console { this._groupDepth++; if (title != null || rest.length > 0) { - this._log('groupCollapsed', chalk.bold(format(title, ...rest))); + this._log('groupCollapsed', pc.bold(format(title, ...rest))); } } diff --git a/packages/jest-console/src/CustomConsole.ts b/packages/jest-console/src/CustomConsole.ts index 41457aa7fc77..6fa713ce4021 100644 --- a/packages/jest-console/src/CustomConsole.ts +++ b/packages/jest-console/src/CustomConsole.ts @@ -9,7 +9,7 @@ import {AssertionError, strict as assert} from 'assert'; import {Console} from 'console'; import type {WriteStream} from 'tty'; import {type InspectOptions, format, formatWithOptions, inspect} from 'util'; -import chalk = require('chalk'); +import * as pc from 'picocolors'; import {clearLine, formatTime} from 'jest-util'; import type {LogCounters, LogMessage, LogTimers, LogType} from './types'; @@ -95,7 +95,7 @@ export default class CustomConsole extends Console { this._groupDepth++; if (title != null || args.length > 0) { - this._log('group', chalk.bold(format(title, ...args))); + this._log('group', pc.bold(format(title, ...args))); } } @@ -103,7 +103,7 @@ export default class CustomConsole extends Console { this._groupDepth++; if (title != null || args.length > 0) { - this._log('groupCollapsed', chalk.bold(format(title, ...args))); + this._log('groupCollapsed', pc.bold(format(title, ...args))); } } diff --git a/packages/jest-console/src/__tests__/CustomConsole.test.ts b/packages/jest-console/src/__tests__/CustomConsole.test.ts index 84b71ece4a39..0cecd11ec93f 100644 --- a/packages/jest-console/src/__tests__/CustomConsole.test.ts +++ b/packages/jest-console/src/__tests__/CustomConsole.test.ts @@ -7,7 +7,7 @@ import {Writable} from 'stream'; import type {WriteStream} from 'tty'; -import chalk = require('chalk'); +import * as pc from 'picocolors'; import CustomConsole from '../CustomConsole'; describe('CustomConsole', () => { @@ -142,9 +142,9 @@ describe('CustomConsole', () => { _console.group('second'); _console.log('there'); - expect(_stdout).toBe(` ${chalk.bold('first')} + expect(_stdout).toBe(` ${pc.bold('first')} hey - ${chalk.bold('second')} + ${pc.bold('second')} there `); }); diff --git a/packages/jest-console/src/__tests__/bufferedConsole.test.ts b/packages/jest-console/src/__tests__/bufferedConsole.test.ts index bf6560c73455..4ed57606be32 100644 --- a/packages/jest-console/src/__tests__/bufferedConsole.test.ts +++ b/packages/jest-console/src/__tests__/bufferedConsole.test.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); +import * as pc from 'picocolors'; import BufferedConsole from '../BufferedConsole'; describe('CustomConsole', () => { @@ -104,9 +104,9 @@ describe('CustomConsole', () => { _console.group('second'); _console.log('there'); - expect(stdout()).toBe(` ${chalk.bold('first')} + expect(stdout()).toBe(` ${pc.bold('first')} hey - ${chalk.bold('second')} + ${pc.bold('second')} there`); }); diff --git a/packages/jest-console/src/getConsoleOutput.ts b/packages/jest-console/src/getConsoleOutput.ts index 66d6ed8e4ef7..bcf5471a6675 100644 --- a/packages/jest-console/src/getConsoleOutput.ts +++ b/packages/jest-console/src/getConsoleOutput.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); +import * as pc from 'picocolors'; import type {Config} from '@jest/types'; import { type StackTraceConfig, @@ -34,13 +34,13 @@ export default function getConsoleOutput( let noCodeFrame = true; if (type === 'warn') { - message = chalk.yellow(message); - typeMessage = chalk.yellow(typeMessage); + message = pc.yellow(message); + typeMessage = pc.yellow(typeMessage); noStackTrace = globalConfig?.noStackTrace ?? false; noCodeFrame = false; } else if (type === 'error') { - message = chalk.red(message); - typeMessage = chalk.red(typeMessage); + message = pc.red(message); + typeMessage = pc.red(typeMessage); noStackTrace = globalConfig?.noStackTrace ?? false; noCodeFrame = false; } @@ -53,8 +53,8 @@ export default function getConsoleOutput( const formattedStackTrace = formatStackTrace(origin, config, options); return `${ - output + TITLE_INDENT + chalk.dim(typeMessage) - }\n${message.trimEnd()}\n${chalk.dim(formattedStackTrace.trimEnd())}\n\n`; + output + TITLE_INDENT + pc.dim(typeMessage) + }\n${message.trimEnd()}\n${pc.dim(formattedStackTrace.trimEnd())}\n\n`; }, ''); return `${logEntries.trimEnd()}\n`; diff --git a/packages/jest-core/package.json b/packages/jest-core/package.json index f07c5ecb2429..528b2f354d85 100644 --- a/packages/jest-core/package.json +++ b/packages/jest-core/package.json @@ -22,7 +22,6 @@ "@jest/types": "workspace:*", "@types/node": "*", "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", "ci-info": "^4.0.0", "exit-x": "^0.2.2", "graceful-fs": "^4.2.9", @@ -40,6 +39,7 @@ "jest-validate": "workspace:*", "jest-watcher": "workspace:*", "micromatch": "^4.0.8", + "picocolors": "^1.1.1", "pretty-format": "workspace:*", "slash": "^3.0.0", "strip-ansi": "^6.0.0" diff --git a/packages/jest-core/src/FailedTestsInteractiveMode.ts b/packages/jest-core/src/FailedTestsInteractiveMode.ts index 07caa7876572..208b4281d5e6 100644 --- a/packages/jest-core/src/FailedTestsInteractiveMode.ts +++ b/packages/jest-core/src/FailedTestsInteractiveMode.ts @@ -6,7 +6,7 @@ */ import ansiEscapes = require('ansi-escapes'); -import chalk = require('chalk'); +import * as pc from 'picocolors'; import type {AggregatedResult, AssertionLocation} from '@jest/test-result'; import {pluralize, specialChars} from 'jest-util'; import {KEYS} from 'jest-watcher'; @@ -16,10 +16,10 @@ type RunnerUpdateFunction = (failure?: AssertionLocation) => void; const {ARROW, CLEAR} = specialChars; function describeKey(key: string, description: string) { - return `${chalk.dim(`${ARROW}Press`)} ${key} ${chalk.dim(description)}`; + return `${pc.dim(`${ARROW}Press`)} ${key} ${pc.dim(description)}`; } -const TestProgressLabel = chalk.bold('Interactive Test Progress'); +const TestProgressLabel = pc.bold('Interactive Test Progress'); export default class FailedTestsInteractiveMode { private _isActive = false; @@ -105,7 +105,7 @@ export default class FailedTestsInteractiveMode { this._pipe.write(CLEAR); const messages: Array = [ - chalk.bold('Watch Usage'), + pc.bold('Watch Usage'), describeKey('Enter', 'to return to watch mode.'), ]; @@ -118,8 +118,8 @@ export default class FailedTestsInteractiveMode { let stats = `${pluralize('test', this._countPaths)} reviewed`; if (this._skippedNum > 0) { - const skippedText = chalk.bold.yellow( - `${pluralize('test', this._skippedNum)} skipped`, + const skippedText = pc.bold( + pc.yellow(`${pluralize('test', this._skippedNum)} skipped`), ); stats = `${stats}, ${skippedText}`; @@ -129,7 +129,7 @@ export default class FailedTestsInteractiveMode { TestProgressLabel, `${ARROW}${stats}`, '\n', - chalk.bold('Watch Usage'), + pc.bold('Watch Usage'), describeKey('r', 'to restart Interactive Mode.'), describeKey('q', 'to quit Interactive Mode.'), describeKey('Enter', 'to return to watch mode.'), @@ -146,8 +146,8 @@ export default class FailedTestsInteractiveMode { let stats = `${pluralize('test', numRemaining)} remaining`; if (this._skippedNum > 0) { - const skippedText = chalk.bold.yellow( - `${pluralize('test', this._skippedNum)} skipped`, + const skippedText = pc.bold( + pc.yellow(`${pluralize('test', this._skippedNum)} skipped`), ); stats = `${stats}, ${skippedText}`; @@ -157,7 +157,7 @@ export default class FailedTestsInteractiveMode { TestProgressLabel, `${ARROW}${stats}`, '\n', - chalk.bold('Watch Usage'), + pc.bold('Watch Usage'), describeKey('s', 'to skip the current test.'), describeKey('q', 'to quit Interactive Mode.'), describeKey('Enter', 'to return to watch mode.'), diff --git a/packages/jest-core/src/SnapshotInteractiveMode.ts b/packages/jest-core/src/SnapshotInteractiveMode.ts index 0f9ec0a886b5..f24b14f7423a 100644 --- a/packages/jest-core/src/SnapshotInteractiveMode.ts +++ b/packages/jest-core/src/SnapshotInteractiveMode.ts @@ -6,7 +6,7 @@ */ import ansiEscapes = require('ansi-escapes'); -import chalk = require('chalk'); +import * as pc from 'picocolors'; import type {AggregatedResult, AssertionLocation} from '@jest/test-result'; import {pluralize, specialChars} from 'jest-util'; import {KEYS} from 'jest-watcher'; @@ -48,39 +48,35 @@ export default class SnapshotInteractiveMode { const numPass = this._countPaths - this._testAssertions.length; const numRemaining = this._countPaths - numPass - this._skippedNum; - let stats = chalk.bold.dim( - `${pluralize('snapshot', numRemaining)} remaining`, + let stats = pc.bold( + pc.dim(`${pluralize('snapshot', numRemaining)} remaining`), ); if (numPass) { - stats += `, ${chalk.bold.green( - `${pluralize('snapshot', numPass)} updated`, + stats += `, ${pc.bold( + pc.green(`${pluralize('snapshot', numPass)} updated`), )}`; } if (this._skippedNum) { - stats += `, ${chalk.bold.yellow( - `${pluralize('snapshot', this._skippedNum)} skipped`, + stats += `, ${pc.bold( + pc.yellow(`${pluralize('snapshot', this._skippedNum)} skipped`), )}`; } const messages = [ - `\n${chalk.bold('Interactive Snapshot Progress')}`, + `\n${pc.bold('Interactive Snapshot Progress')}`, ARROW + stats, - `\n${chalk.bold('Watch Usage')}`, + `\n${pc.bold('Watch Usage')}`, - `${chalk.dim(`${ARROW}Press `)}u${chalk.dim( + `${pc.dim(`${ARROW}Press `)}u${pc.dim( ' to update failing snapshots for this test.', )}`, - `${chalk.dim(`${ARROW}Press `)}s${chalk.dim( - ' to skip the current test.', - )}`, + `${pc.dim(`${ARROW}Press `)}s${pc.dim(' to skip the current test.')}`, - `${chalk.dim(`${ARROW}Press `)}q${chalk.dim( + `${pc.dim(`${ARROW}Press `)}q${pc.dim( ' to quit Interactive Snapshot Mode.', )}`, - `${chalk.dim(`${ARROW}Press `)}Enter${chalk.dim( - ' to trigger a test run.', - )}`, + `${pc.dim(`${ARROW}Press `)}Enter${pc.dim(' to trigger a test run.')}`, ]; this._pipe.write(`${messages.filter(Boolean).join('\n')}\n`); @@ -90,29 +86,29 @@ export default class SnapshotInteractiveMode { this._pipe.write(CLEAR); const numPass = this._countPaths - this._testAssertions.length; - let stats = chalk.bold.dim( - `${pluralize('snapshot', this._countPaths)} reviewed`, + let stats = pc.bold( + pc.dim(`${pluralize('snapshot', this._countPaths)} reviewed`), ); if (numPass) { - stats += `, ${chalk.bold.green( - `${pluralize('snapshot', numPass)} updated`, + stats += `, ${pc.bold( + pc.green(`${pluralize('snapshot', numPass)} updated`), )}`; } if (this._skippedNum) { - stats += `, ${chalk.bold.yellow( - `${pluralize('snapshot', this._skippedNum)} skipped`, + stats += `, ${pc.bold( + pc.yellow(`${pluralize('snapshot', this._skippedNum)} skipped`), )}`; } const messages = [ - `\n${chalk.bold('Interactive Snapshot Result')}`, + `\n${pc.bold('Interactive Snapshot Result')}`, ARROW + stats, - `\n${chalk.bold('Watch Usage')}`, + `\n${pc.bold('Watch Usage')}`, - `${chalk.dim(`${ARROW}Press `)}r${chalk.dim( + `${pc.dim(`${ARROW}Press `)}r${pc.dim( ' to restart Interactive Snapshot Mode.', )}`, - `${chalk.dim(`${ARROW}Press `)}q${chalk.dim( + `${pc.dim(`${ARROW}Press `)}q${pc.dim( ' to quit Interactive Snapshot Mode.', )}`, ]; @@ -124,22 +120,20 @@ export default class SnapshotInteractiveMode { this._pipe.write(CLEAR); const numPass = this._countPaths - this._testAssertions.length; - let stats = chalk.bold.dim( - `${pluralize('snapshot', this._countPaths)} reviewed`, + let stats = pc.bold( + pc.dim(`${pluralize('snapshot', this._countPaths)} reviewed`), ); if (numPass) { - stats += `, ${chalk.bold.green( - `${pluralize('snapshot', numPass)} updated`, + stats += `, ${pc.bold( + pc.green(`${pluralize('snapshot', numPass)} updated`), )}`; } const messages = [ - `\n${chalk.bold('Interactive Snapshot Result')}`, + `\n${pc.bold('Interactive Snapshot Result')}`, ARROW + stats, - `\n${chalk.bold('Watch Usage')}`, + `\n${pc.bold('Watch Usage')}`, - `${chalk.dim(`${ARROW}Press `)}Enter${chalk.dim( - ' to return to watch mode.', - )}`, + `${pc.dim(`${ARROW}Press `)}Enter${pc.dim(' to return to watch mode.')}`, ]; this._pipe.write(`${messages.filter(Boolean).join('\n')}\n`); diff --git a/packages/jest-core/src/cli/index.ts b/packages/jest-core/src/cli/index.ts index 352cdefeb0f0..3c5e230854a9 100644 --- a/packages/jest-core/src/cli/index.ts +++ b/packages/jest-core/src/cli/index.ts @@ -7,9 +7,9 @@ import {performance} from 'perf_hooks'; import type {WriteStream} from 'tty'; -import chalk = require('chalk'); import exit = require('exit-x'); import * as fs from 'graceful-fs'; +import * as pc from 'picocolors'; import {CustomConsole} from '@jest/console'; import type {AggregatedResult, TestContext} from '@jest/test-result'; import type {Config} from '@jest/types'; @@ -129,7 +129,7 @@ export async function runCLI( const openHandlesString = pluralize('open handle', formatted.length, 's'); const message = - chalk.red( + pc.red( `\nJest has detected the following ${openHandlesString} potentially keeping Jest from exiting:\n\n`, ) + formatted.join('\n\n'); diff --git a/packages/jest-core/src/getChangedFilesPromise.ts b/packages/jest-core/src/getChangedFilesPromise.ts index 252eb67ad087..471287e350df 100644 --- a/packages/jest-core/src/getChangedFilesPromise.ts +++ b/packages/jest-core/src/getChangedFilesPromise.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); +import * as pc from 'picocolors'; import type {Config} from '@jest/types'; import { type ChangedFilesPromise, @@ -31,7 +31,7 @@ export default function getChangedFilesPromise( .filter(line => !line.includes('Command failed:')) .join('\n'); - console.error(chalk.red(`\n\n${message}`)); + console.error(pc.red(`\n\n${message}`)); process.exit(1); }); diff --git a/packages/jest-core/src/getNoTestFound.ts b/packages/jest-core/src/getNoTestFound.ts index 7d6ae6e5e7bb..ce784403cc74 100644 --- a/packages/jest-core/src/getNoTestFound.ts +++ b/packages/jest-core/src/getNoTestFound.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); +import * as pc from 'picocolors'; import type {Config} from '@jest/types'; import {pluralize} from 'jest-util'; import type {TestRunData} from './types'; @@ -26,15 +26,15 @@ export default function getNoTestFound( .map(p => `"${p}"`) .join(', ')}`; } else { - dataMessage = `Pattern: ${chalk.yellow( + dataMessage = `Pattern: ${pc.yellow( globalConfig.testPathPatterns.toPretty(), )} - 0 matches`; } if (willExitWith0) { return ( - `${chalk.bold('No tests found, exiting with code 0')}\n` + - `In ${chalk.bold(globalConfig.rootDir)}` + + `${pc.bold('No tests found, exiting with code 0')}\n` + + `In ${pc.bold(globalConfig.rootDir)}` + '\n' + ` ${pluralize('file', testFiles, 's')} checked across ${pluralize( 'project', @@ -46,10 +46,10 @@ export default function getNoTestFound( } return ( - `${chalk.bold('No tests found, exiting with code 1')}\n` + + `${pc.bold('No tests found, exiting with code 1')}\n` + 'Run with `--passWithNoTests` to exit with code 0' + '\n' + - `In ${chalk.bold(globalConfig.rootDir)}` + + `In ${pc.bold(globalConfig.rootDir)}` + '\n' + ` ${pluralize('file', testFiles, 's')} checked across ${pluralize( 'project', diff --git a/packages/jest-core/src/getNoTestFoundFailed.ts b/packages/jest-core/src/getNoTestFoundFailed.ts index acab5c62a8af..ddcaf2b09ea7 100644 --- a/packages/jest-core/src/getNoTestFoundFailed.ts +++ b/packages/jest-core/src/getNoTestFoundFailed.ts @@ -5,16 +5,16 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); +import * as pc from 'picocolors'; import type {Config} from '@jest/types'; import {isInteractive} from 'jest-util'; export default function getNoTestFoundFailed( globalConfig: Config.GlobalConfig, ): string { - let msg = chalk.bold('No failed test found.'); + let msg = pc.bold('No failed test found.'); if (isInteractive) { - msg += chalk.dim( + msg += pc.dim( `\n${ globalConfig.watch ? 'Press `f` to quit "only failed tests" mode.' diff --git a/packages/jest-core/src/getNoTestFoundPassWithNoTests.ts b/packages/jest-core/src/getNoTestFoundPassWithNoTests.ts index 768a18e96f61..053130e94e97 100644 --- a/packages/jest-core/src/getNoTestFoundPassWithNoTests.ts +++ b/packages/jest-core/src/getNoTestFoundPassWithNoTests.ts @@ -5,8 +5,8 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); +import * as pc from 'picocolors'; export default function getNoTestFoundPassWithNoTests(): string { - return chalk.bold('No tests found, exiting with code 0'); + return pc.bold('No tests found, exiting with code 0'); } diff --git a/packages/jest-core/src/getNoTestFoundRelatedToChangedFiles.ts b/packages/jest-core/src/getNoTestFoundRelatedToChangedFiles.ts index 995153f2f25b..d0eafc20f019 100644 --- a/packages/jest-core/src/getNoTestFoundRelatedToChangedFiles.ts +++ b/packages/jest-core/src/getNoTestFoundRelatedToChangedFiles.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); +import * as pc from 'picocolors'; import type {Config} from '@jest/types'; import {isInteractive} from 'jest-util'; @@ -15,10 +15,10 @@ export default function getNoTestFoundRelatedToChangedFiles( const ref = globalConfig.changedSince ? `"${globalConfig.changedSince}"` : 'last commit'; - let msg = chalk.bold(`No tests found related to files changed since ${ref}.`); + let msg = pc.bold(`No tests found related to files changed since ${ref}.`); if (isInteractive) { - msg += chalk.dim( + msg += pc.dim( `\n${ globalConfig.watch ? 'Press `a` to run all tests, or run Jest with `--watchAll`.' diff --git a/packages/jest-core/src/getNoTestFoundVerbose.ts b/packages/jest-core/src/getNoTestFoundVerbose.ts index bd5f2ab355b4..d3efbdc1d8de 100644 --- a/packages/jest-core/src/getNoTestFoundVerbose.ts +++ b/packages/jest-core/src/getNoTestFoundVerbose.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); +import * as pc from 'picocolors'; import type {Config} from '@jest/types'; import {pluralize} from 'jest-util'; import type {Stats, TestRunData} from './types'; @@ -29,7 +29,7 @@ export default function getNoTestFoundVerbose( ? value.join(', ') : String(value); const matches = pluralize('match', stats[key] || 0, 'es'); - return ` ${key}: ${chalk.yellow(valueAsString)} - ${matches}`; + return ` ${key}: ${pc.yellow(valueAsString)} - ${matches}`; } return null; }) @@ -37,7 +37,7 @@ export default function getNoTestFoundVerbose( .join('\n'); return testRun.matches.total - ? `In ${chalk.bold(config.rootDir)}\n` + + ? `In ${pc.bold(config.rootDir)}\n` + ` ${pluralize( 'file', testRun.matches.total || 0, @@ -56,19 +56,19 @@ export default function getNoTestFoundVerbose( .map(p => `"${p}"`) .join(', ')}`; } else { - dataMessage = `Pattern: ${chalk.yellow( + dataMessage = `Pattern: ${pc.yellow( globalConfig.testPathPatterns.toPretty(), )} - 0 matches`; } if (willExitWith0) { - return `${chalk.bold( + return `${pc.bold( 'No tests found, exiting with code 0', )}\n${individualResults.join('\n')}\n${dataMessage}`; } return ( - `${chalk.bold('No tests found, exiting with code 1')}\n` + + `${pc.bold('No tests found, exiting with code 1')}\n` + 'Run with `--passWithNoTests` to exit with code 0' + `\n${individualResults.join('\n')}\n${dataMessage}` ); diff --git a/packages/jest-core/src/getProjectNamesMissingWarning.ts b/packages/jest-core/src/getProjectNamesMissingWarning.ts index 6a6e1cf145aa..1796b4a2d580 100644 --- a/packages/jest-core/src/getProjectNamesMissingWarning.ts +++ b/packages/jest-core/src/getProjectNamesMissingWarning.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); +import * as pc from 'picocolors'; import type {Config} from '@jest/types'; import getProjectDisplayName from './getProjectDisplayName'; @@ -29,7 +29,7 @@ export default function getProjectNamesMissingWarning( if (opts.ignoreProjects) { args.push('--ignoreProjects'); } - return chalk.yellow( + return pc.yellow( `You provided values for ${args.join(' and ')} but ${ numberOfProjectsWithoutAName === 1 ? 'a project does not have a name' diff --git a/packages/jest-core/src/getSelectProjectsMessage.ts b/packages/jest-core/src/getSelectProjectsMessage.ts index 0d67295c32fb..c054d39dc999 100644 --- a/packages/jest-core/src/getSelectProjectsMessage.ts +++ b/packages/jest-core/src/getSelectProjectsMessage.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); +import * as pc from 'picocolors'; import type {Config} from '@jest/types'; import getProjectDisplayName from './getProjectDisplayName'; @@ -27,21 +27,21 @@ function getNoSelectionWarning(opts: { selectProjects: Array | undefined; }): string { if (opts.ignoreProjects && opts.selectProjects) { - return chalk.yellow( + return pc.yellow( 'You provided values for --selectProjects and --ignoreProjects, but no projects were found matching the selection.\n' + 'Are you ignoring all the selected projects?\n', ); } else if (opts.ignoreProjects) { - return chalk.yellow( + return pc.yellow( 'You provided values for --ignoreProjects, but no projects were found matching the selection.\n' + 'Are you ignoring all projects?\n', ); } else if (opts.selectProjects) { - return chalk.yellow( + return pc.yellow( 'You provided values for --selectProjects but no projects were found matching the selection.\n', ); } else { - return chalk.yellow('No projects were found.\n'); + return pc.yellow('No projects were found.\n'); } } @@ -51,7 +51,7 @@ function getProjectsRunningMessage( if (projectConfigs.length === 1) { const name = getProjectDisplayName(projectConfigs[0]) ?? ''; - return `Running one project: ${chalk.bold(name)}\n`; + return `Running one project: ${pc.bold(name)}\n`; } const projectsList = projectConfigs .map(getProjectNameListElement) @@ -64,6 +64,6 @@ function getProjectNameListElement( projectConfig: Config.ProjectConfig, ): string { const name = getProjectDisplayName(projectConfig); - const elementContent = name ? chalk.bold(name) : ''; + const elementContent = name ? pc.bold(name) : ''; return `- ${elementContent}`; } diff --git a/packages/jest-core/src/lib/activeFiltersMessage.ts b/packages/jest-core/src/lib/activeFiltersMessage.ts index c1c9230c6544..7ed811fa13b7 100644 --- a/packages/jest-core/src/lib/activeFiltersMessage.ts +++ b/packages/jest-core/src/lib/activeFiltersMessage.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); +import * as pc from 'picocolors'; import type {Config} from '@jest/types'; import {isNonNullable} from 'jest-util'; @@ -15,16 +15,16 @@ const activeFilters = (globalConfig: Config.GlobalConfig): string => { if (testNamePattern || testPathPatterns.isSet()) { const filters = [ testPathPatterns.isSet() - ? chalk.dim('filename ') + chalk.yellow(testPathPatterns.toPretty()) + ? pc.dim('filename ') + pc.yellow(testPathPatterns.toPretty()) : null, testNamePattern - ? chalk.dim('test name ') + chalk.yellow(`/${testNamePattern}/`) + ? pc.dim('test name ') + pc.yellow(`/${testNamePattern}/`) : null, ] .filter(isNonNullable) .join(', '); - const messages = `\n${chalk.bold('Active Filters: ')}${filters}`; + const messages = `\n${pc.bold('Active Filters: ')}${filters}`; return messages; } diff --git a/packages/jest-core/src/lib/handleDeprecationWarnings.ts b/packages/jest-core/src/lib/handleDeprecationWarnings.ts index f56c79f1509d..48edf895bacb 100644 --- a/packages/jest-core/src/lib/handleDeprecationWarnings.ts +++ b/packages/jest-core/src/lib/handleDeprecationWarnings.ts @@ -6,7 +6,7 @@ */ import type {ReadStream, WriteStream} from 'tty'; -import chalk = require('chalk'); +import * as pc from 'picocolors'; import {KEYS} from 'jest-watcher'; export default function handleDeprecationWarnings( @@ -16,9 +16,9 @@ export default function handleDeprecationWarnings( return new Promise((resolve, reject) => { if (typeof stdin.setRawMode === 'function') { const messages = [ - chalk.red('There are deprecation warnings.\n'), - `${chalk.dim(' \u203A Press ')}Enter${chalk.dim(' to continue.')}`, - `${chalk.dim(' \u203A Press ')}Esc${chalk.dim(' to exit.')}`, + pc.red('There are deprecation warnings.\n'), + `${pc.dim(' \u203A Press ')}Enter${pc.dim(' to continue.')}`, + `${pc.dim(' \u203A Press ')}Esc${pc.dim(' to exit.')}`, ]; pipe.write(messages.join('\n')); diff --git a/packages/jest-core/src/runJest.ts b/packages/jest-core/src/runJest.ts index 5f9ed2e06364..a202a5a588f8 100644 --- a/packages/jest-core/src/runJest.ts +++ b/packages/jest-core/src/runJest.ts @@ -8,9 +8,9 @@ import * as path from 'path'; import {performance} from 'perf_hooks'; import type {WriteStream} from 'tty'; -import chalk = require('chalk'); import exit = require('exit-x'); import * as fs from 'graceful-fs'; +import * as pc from 'picocolors'; import {CustomConsole} from '@jest/console'; import { type AggregatedResult, @@ -175,7 +175,7 @@ export default async function runJest({ ).every(scm => repos[scm].size === 0); if (noSCM) { process.stderr.write( - `\n${chalk.bold( + `\n${pc.bold( '--watch', )} is not supported without git/hg, please use --watchAll\n`, ); diff --git a/packages/jest-diff/package.json b/packages/jest-diff/package.json index ad6f1067d64c..5532042de0b2 100644 --- a/packages/jest-diff/package.json +++ b/packages/jest-diff/package.json @@ -19,9 +19,9 @@ "./package.json": "./package.json" }, "dependencies": { - "chalk": "^4.0.0", "diff-sequences": "workspace:*", "jest-get-type": "workspace:*", + "picocolors": "^1.1.1", "pretty-format": "workspace:*" }, "devDependencies": { diff --git a/packages/jest-diff/src/__tests__/diff.test.ts b/packages/jest-diff/src/__tests__/diff.test.ts index 64347ca05547..f2dcab02682a 100644 --- a/packages/jest-diff/src/__tests__/diff.test.ts +++ b/packages/jest-diff/src/__tests__/diff.test.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); +import * as pc from 'picocolors'; import stripAnsi = require('strip-ansi'); import {alignedAnsiStyleSerializer} from '@jest/test-utils'; import {diff} from '../'; @@ -718,7 +718,7 @@ describe('context', () => { expand: false, }; if (!validContextLines) { - options.patchColor = chalk.dim; + options.patchColor = pc.dim; } const result = diff( @@ -940,9 +940,9 @@ describe('options 7980', () => { const options = { aAnnotation: 'Original', - aColor: chalk.red, + aColor: pc.red, bAnnotation: 'Modified', - bColor: chalk.green, + bColor: pc.green, }; test('diff', () => { @@ -974,8 +974,8 @@ describe('options', () => { describe('change color', () => { const options = { - changeColor: chalk.bold, - commonColor: chalk.yellow, + changeColor: pc.bold, + commonColor: pc.yellow, }; test('diffStringsUnified', () => { @@ -1091,7 +1091,7 @@ describe('options', () => { test('diff yellowish common', () => { const options = { - commonLineTrailingSpaceColor: chalk.bgYellow, + commonLineTrailingSpaceColor: pc.bgYellow, }; expect(diff(aTrailingSpaces, bTrailingSpaces, options)).toMatchSnapshot(); diff --git a/packages/jest-diff/src/index.ts b/packages/jest-diff/src/index.ts index 4b87be7d720f..d9840b29a092 100644 --- a/packages/jest-diff/src/index.ts +++ b/packages/jest-diff/src/index.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); +import * as pc from 'picocolors'; import {getType} from 'jest-get-type'; import { type PrettyFormatOptions, @@ -85,8 +85,8 @@ export function diff(a: any, b: any, options?: DiffOptions): string | null { if (expectedType !== getType(b)) { return ( ' Comparing two different types of values.' + - ` Expected ${chalk.green(expectedType)} but ` + - `received ${chalk.red(getType(b))}.` + ` Expected ${pc.green(expectedType)} but ` + + `received ${pc.red(getType(b))}.` ); } diff --git a/packages/jest-diff/src/normalizeDiffOptions.ts b/packages/jest-diff/src/normalizeDiffOptions.ts index 3072bea01597..c6ca85fa9708 100644 --- a/packages/jest-diff/src/normalizeDiffOptions.ts +++ b/packages/jest-diff/src/normalizeDiffOptions.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); +import * as pc from 'picocolors'; import type {CompareKeys} from 'pretty-format'; import type {DiffOptions, DiffOptionsNormalized} from './types'; @@ -15,14 +15,14 @@ const DIFF_CONTEXT_DEFAULT = 5; const OPTIONS_DEFAULT: DiffOptionsNormalized = { aAnnotation: 'Expected', - aColor: chalk.green, + aColor: pc.green, aIndicator: '-', bAnnotation: 'Received', - bColor: chalk.red, + bColor: pc.red, bIndicator: '+', - changeColor: chalk.inverse, + changeColor: pc.inverse, changeLineTrailingSpaceColor: noColor, - commonColor: chalk.dim, + commonColor: pc.dim, commonIndicator: ' ', commonLineTrailingSpaceColor: noColor, compareKeys: undefined, @@ -31,7 +31,7 @@ const OPTIONS_DEFAULT: DiffOptionsNormalized = { expand: true, includeChangeCounts: false, omitAnnotationLines: false, - patchColor: chalk.yellow, + patchColor: pc.yellow, }; const getCompareKeys = (compareKeys?: CompareKeys): CompareKeys => diff --git a/packages/jest-each/package.json b/packages/jest-each/package.json index 8e4bd393b57e..d5e98dd8ed13 100644 --- a/packages/jest-each/package.json +++ b/packages/jest-each/package.json @@ -28,9 +28,9 @@ "license": "MIT", "dependencies": { "@jest/types": "workspace:*", - "chalk": "^4.0.0", "jest-get-type": "workspace:*", "jest-util": "workspace:*", + "picocolors": "^1.1.1", "pretty-format": "workspace:*" }, "engines": { diff --git a/packages/jest-each/src/validation.ts b/packages/jest-each/src/validation.ts index ffb770ca4e51..190717a1cfb6 100644 --- a/packages/jest-each/src/validation.ts +++ b/packages/jest-each/src/validation.ts @@ -6,14 +6,14 @@ * */ -import chalk = require('chalk'); +import * as pc from 'picocolors'; import type {Global} from '@jest/types'; import {format as pretty} from 'pretty-format'; type TemplateData = Global.TemplateData; -const EXPECTED_COLOR = chalk.green; -const RECEIVED_COLOR = chalk.red; +const EXPECTED_COLOR = pc.green; +const RECEIVED_COLOR = pc.red; export const validateArrayTable = (table: unknown): void => { if (!Array.isArray(table)) { diff --git a/packages/jest-jasmine2/package.json b/packages/jest-jasmine2/package.json index d3fa8c4b19eb..87d72db5dcb3 100644 --- a/packages/jest-jasmine2/package.json +++ b/packages/jest-jasmine2/package.json @@ -25,7 +25,6 @@ "@jest/test-result": "workspace:*", "@jest/types": "workspace:*", "@types/node": "*", - "chalk": "^4.0.0", "co": "^4.6.0", "is-generator-fn": "^2.0.0", "jest-each": "workspace:*", @@ -35,6 +34,7 @@ "jest-snapshot": "workspace:*", "jest-util": "workspace:*", "p-limit": "^3.1.0", + "picocolors": "^1.1.1", "pretty-format": "workspace:*" }, "devDependencies": { diff --git a/packages/jest-jasmine2/src/assertionErrorMessage.ts b/packages/jest-jasmine2/src/assertionErrorMessage.ts index 5251719466f5..f82065c43b31 100644 --- a/packages/jest-jasmine2/src/assertionErrorMessage.ts +++ b/packages/jest-jasmine2/src/assertionErrorMessage.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); +import * as pc from 'picocolors'; import { type DiffOptions, diff, @@ -56,10 +56,10 @@ const operatorMessage = (operator: string | null) => { const assertThrowingMatcherHint = (operatorName: string) => operatorName - ? chalk.dim('assert') + - chalk.dim(`.${operatorName}(`) + - chalk.red('function') + - chalk.dim(')') + ? pc.dim('assert') + + pc.dim(`.${operatorName}(`) + + pc.red('function') + + pc.dim(')') : ''; const assertMatcherHint = ( @@ -70,19 +70,15 @@ const assertMatcherHint = ( let message = ''; if (operator === '==' && expected === true) { - message = - chalk.dim('assert') + - chalk.dim('(') + - chalk.red('received') + - chalk.dim(')'); + message = pc.dim('assert') + pc.dim('(') + pc.red('received') + pc.dim(')'); } else if (operatorName) { message = - chalk.dim('assert') + - chalk.dim(`.${operatorName}(`) + - chalk.red('received') + - chalk.dim(', ') + - chalk.green('expected') + - chalk.dim(')'); + pc.dim('assert') + + pc.dim(`.${operatorName}(`) + + pc.red('received') + + pc.dim(', ') + + pc.green('expected') + + pc.dim(')'); } return message; @@ -103,9 +99,9 @@ function assertionErrorMessage( if (operatorName === 'doesNotThrow') { return `${ buildHintString(assertThrowingMatcherHint(operatorName)) + - chalk.reset('Expected the function not to throw an error.\n') + - chalk.reset('Instead, it threw:\n') - } ${printReceived(actual)}${chalk.reset( + pc.reset('Expected the function not to throw an error.\n') + + pc.reset('Instead, it threw:\n') + } ${printReceived(actual)}${pc.reset( hasCustomMessage ? `\n\nMessage:\n ${message}` : '', )}${trimmedStack}`; } @@ -114,16 +110,16 @@ function assertionErrorMessage( if (error.generatedMessage) { return ( buildHintString(assertThrowingMatcherHint(operatorName)) + - chalk.reset(error.message) + - chalk.reset(hasCustomMessage ? `\n\nMessage:\n ${message}` : '') + + pc.reset(error.message) + + pc.reset(hasCustomMessage ? `\n\nMessage:\n ${message}` : '') + trimmedStack ); } return ( buildHintString(assertThrowingMatcherHint(operatorName)) + - chalk.reset('Expected the function to throw an error.\n') + - chalk.reset("But it didn't throw anything.") + - chalk.reset(hasCustomMessage ? `\n\nMessage:\n ${message}` : '') + + pc.reset('Expected the function to throw an error.\n') + + pc.reset("But it didn't throw anything.") + + pc.reset(hasCustomMessage ? `\n\nMessage:\n ${message}` : '') + trimmedStack ); } @@ -131,17 +127,17 @@ function assertionErrorMessage( if (operatorName === 'fail') { return ( buildHintString(assertMatcherHint(operator, operatorName, expected)) + - chalk.reset(hasCustomMessage ? `Message:\n ${message}` : '') + + pc.reset(hasCustomMessage ? `Message:\n ${message}` : '') + trimmedStack ); } return `${ buildHintString(assertMatcherHint(operator, operatorName, expected)) + - chalk.reset(`Expected value ${operatorMessage(operator)}`) - } ${printExpected(expected)}\n${chalk.reset('Received:\n')} ${printReceived( + pc.reset(`Expected value ${operatorMessage(operator)}`) + } ${printExpected(expected)}\n${pc.reset('Received:\n')} ${printReceived( actual, - )}${chalk.reset(hasCustomMessage ? `\n\nMessage:\n ${message}` : '')}${ + )}${pc.reset(hasCustomMessage ? `\n\nMessage:\n ${message}` : '')}${ diffString ? `\n\nDifference:\n\n${diffString}` : '' }${trimmedStack}`; } diff --git a/packages/jest-matcher-utils/package.json b/packages/jest-matcher-utils/package.json index 5a038f758a25..cbdc4f93e19a 100644 --- a/packages/jest-matcher-utils/package.json +++ b/packages/jest-matcher-utils/package.json @@ -23,9 +23,9 @@ "./package.json": "./package.json" }, "dependencies": { - "chalk": "^4.0.0", "jest-diff": "workspace:*", "jest-get-type": "workspace:*", + "picocolors": "^1.1.1", "pretty-format": "workspace:*" }, "devDependencies": { diff --git a/packages/jest-matcher-utils/src/__tests__/index.test.ts b/packages/jest-matcher-utils/src/__tests__/index.test.ts index 2db009cf8514..79922e6040a6 100644 --- a/packages/jest-matcher-utils/src/__tests__/index.test.ts +++ b/packages/jest-matcher-utils/src/__tests__/index.test.ts @@ -6,7 +6,7 @@ * */ -import chalk = require('chalk'); +import * as pc from 'picocolors'; import {alignedAnsiStyleSerializer} from '@jest/test-utils'; import {format as prettyFormat} from 'pretty-format'; import { @@ -329,19 +329,19 @@ describe('matcherHint', () => { {expectedColor, secondArgument: '...expected'}, ); - const substringNegative = chalk.green(expectedArgument); + const substringNegative = pc.green(expectedArgument); expect(received).not.toMatch(substringNegative); }); test('receivedColor', () => { - const receivedColor = chalk.cyan.bgAnsi256(158); + const receivedColor = (arg: string): string => pc.cyan(pc.bgBlue(arg)); const receivedArgument = 'received'; const received = matcherHint('toMatchSnapshot', receivedArgument, '', { receivedColor, }); - const substringNegative = chalk.red(receivedArgument); + const substringNegative = pc.red(receivedArgument); const substringPositive = receivedColor(receivedArgument); expect(received).not.toMatch(substringNegative); @@ -349,14 +349,14 @@ describe('matcherHint', () => { }); test('secondArgumentColor', () => { - const secondArgumentColor = chalk.bold; + const secondArgumentColor = pc.bold; const secondArgument = 'hint'; const received = matcherHint('toMatchSnapshot', undefined, 'properties', { secondArgument, secondArgumentColor, }); - const substringNegative = chalk.green(secondArgument); + const substringNegative = pc.green(secondArgument); const substringPositive = secondArgumentColor(secondArgument); expect(received).not.toMatch(substringNegative); diff --git a/packages/jest-matcher-utils/src/index.ts b/packages/jest-matcher-utils/src/index.ts index e8f2a8b25032..1183809a5f4d 100644 --- a/packages/jest-matcher-utils/src/index.ts +++ b/packages/jest-matcher-utils/src/index.ts @@ -7,7 +7,7 @@ /* eslint-disable local/ban-types-eventually */ -import chalk = require('chalk'); +import * as pc from 'picocolors'; import { DIFF_DELETE, DIFF_EQUAL, @@ -48,7 +48,7 @@ const PLUGINS = [ AsymmetricMatcher, ]; -type MatcherHintColor = (arg: string) => string; // subset of Chalk type +type MatcherHintColor = (arg: string) => string; // subset of pc type export type MatcherHintOptions = { comment?: string; @@ -63,11 +63,11 @@ export type MatcherHintOptions = { export type DiffOptions = ImportDiffOptions; -export const EXPECTED_COLOR = chalk.green; -export const RECEIVED_COLOR = chalk.red; -export const INVERTED_COLOR = chalk.inverse; -export const BOLD_WEIGHT = chalk.bold; -export const DIM_COLOR = chalk.dim; +export const EXPECTED_COLOR = pc.green; +export const RECEIVED_COLOR = pc.red; +export const INVERTED_COLOR = pc.inverse; +export const BOLD_WEIGHT = pc.bold; +export const DIM_COLOR = pc.dim; const MULTILINE_REGEXP = /\n/; const SPACE_SYMBOL = '\u{00B7}'; // middle dot @@ -89,7 +89,7 @@ const NUMBERS = [ 'thirteen', ]; -export const SUGGEST_TO_CONTAIN_EQUAL = chalk.dim( +export const SUGGEST_TO_CONTAIN_EQUAL = pc.dim( 'Looks like you wanted to test for object/array equality with the stricter `toContain` matcher. You probably need to use `toContainEqual` instead.', ); @@ -128,7 +128,7 @@ export const stringify = ( }; export const highlightTrailingWhitespace = (text: string): string => - text.replaceAll(/\s+$/gm, chalk.inverse('$&')); + text.replaceAll(/\s+$/gm, pc.inverse('$&')); // Instead of inverse highlight which now implies a change, // replace common spaces with middle dot at the end of any line. @@ -339,8 +339,8 @@ export const printDiffOrStringify = ( return diffStringsUnified(expected, received, { aAnnotation: expectedLabel, bAnnotation: receivedLabel, - changeLineTrailingSpaceColor: chalk.bgYellow, - commonLineTrailingSpaceColor: chalk.bgYellow, + changeLineTrailingSpaceColor: pc.bgYellow, + commonLineTrailingSpaceColor: pc.bgYellow, emptyFirstOrLastLinePlaceholder: '↵', // U+21B5 expand, includeChangeCounts: true, @@ -516,7 +516,7 @@ export const matcherErrorMessage = ( generic: string, // condition which correct value must fulfill specific?: string, // incorrect value returned from call to printWithType ): string => - `${hint}\n\n${chalk.bold('Matcher error')}: ${generic}${ + `${hint}\n\n${pc.bold('Matcher error')}: ${generic}${ typeof specific === 'string' ? `\n\n${specific}` : '' }`; diff --git a/packages/jest-message-util/package.json b/packages/jest-message-util/package.json index b64545a664b7..007dff53eb18 100644 --- a/packages/jest-message-util/package.json +++ b/packages/jest-message-util/package.json @@ -25,9 +25,9 @@ "@babel/code-frame": "^7.12.13", "@jest/types": "workspace:*", "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.8", + "picocolors": "^1.1.1", "pretty-format": "workspace:*", "slash": "^3.0.0", "stack-utils": "^2.0.3" diff --git a/packages/jest-message-util/src/index.ts b/packages/jest-message-util/src/index.ts index fd6efbb88e30..aa4baca11955 100644 --- a/packages/jest-message-util/src/index.ts +++ b/packages/jest-message-util/src/index.ts @@ -9,9 +9,9 @@ import * as path from 'path'; import {fileURLToPath} from 'url'; import {types} from 'util'; import {codeFrameColumns} from '@babel/code-frame'; -import chalk = require('chalk'); import * as fs from 'graceful-fs'; import micromatch = require('micromatch'); +import * as pc from 'picocolors'; import slash = require('slash'); import StackUtils = require('stack-utils'); import type {Config, TestResult} from '@jest/types'; @@ -58,8 +58,8 @@ const TITLE_INDENT = ' '; const MESSAGE_INDENT = ' '; const STACK_INDENT = ' '; const ANCESTRY_SEPARATOR = ' \u203A '; -const TITLE_BULLET = chalk.bold('\u25CF '); -const STACK_TRACE_COLOR = chalk.dim; +const TITLE_BULLET = pc.bold('\u25CF '); +const STACK_TRACE_COLOR = pc.dim; const STACK_PATH_REGEXP = /\s*at.*\(?(:\d*:\d*|native)\)?/; const EXEC_ERROR_MESSAGE = 'Test suite failed to run'; const NOT_EMPTY_LINE_REGEXP = /^(?!$)/gm; @@ -111,10 +111,14 @@ function checkForCommonEnvironmentErrors(error: string) { function warnAboutWrongTestEnvironment(error: string, env: 'jsdom' | 'node') { return ( - chalk.bold.red( - `The error below may be caused by using the wrong test environment, see ${chalk.dim.underline( - 'https://jestjs.io/docs/configuration#testenvironment-string', - )}.\nConsider using the "${env}" test environment.\n\n`, + pc.bold( + pc.red( + `The error below may be caused by using the wrong test environment, see ${pc.dim( + pc.underline( + 'https://jestjs.io/docs/configuration#testenvironment-string', + ), + )}.\nConsider using the "${env}" test environment.\n\n`, + ), ) + error ); } @@ -305,7 +309,7 @@ export const formatPath = ( micromatch([filePath], config.testMatch).length > 0) || filePath === relativeTestPath ) { - filePath = chalk.reset.cyan(filePath); + filePath = pc.reset(pc.cyan(filePath)); } return STACK_TRACE_COLOR(match[1]) + filePath + STACK_TRACE_COLOR(match[3]); }; @@ -488,12 +492,14 @@ export const formatResultsErrors = ( content, ); - const title = `${chalk.bold.red( - TITLE_INDENT + - TITLE_BULLET + - result.ancestorTitles.join(ANCESTRY_SEPARATOR) + - (result.ancestorTitles.length > 0 ? ANCESTRY_SEPARATOR : '') + - result.title, + const title = `${pc.bold( + pc.red( + TITLE_INDENT + + TITLE_BULLET + + result.ancestorTitles.join(ANCESTRY_SEPARATOR) + + (result.ancestorTitles.length > 0 ? ANCESTRY_SEPARATOR : '') + + result.title, + ), )}\n`; return `${title}\n${formatErrorStack( diff --git a/packages/jest-repl/package.json b/packages/jest-repl/package.json index e231a387e742..b51fca6de8be 100644 --- a/packages/jest-repl/package.json +++ b/packages/jest-repl/package.json @@ -25,11 +25,11 @@ "@jest/environment": "workspace:*", "@jest/transform": "workspace:*", "@jest/types": "workspace:*", - "chalk": "^4.0.0", "jest-config": "workspace:*", "jest-runtime": "workspace:*", "jest-util": "workspace:*", "jest-validate": "workspace:*", + "picocolors": "^1.1.1", "repl": "^0.1.3", "yargs": "^17.3.1" }, diff --git a/packages/jest-repl/src/cli/runtime-cli.ts b/packages/jest-repl/src/cli/runtime-cli.ts index 5997b040a769..9c0fcff16abb 100644 --- a/packages/jest-repl/src/cli/runtime-cli.ts +++ b/packages/jest-repl/src/cli/runtime-cli.ts @@ -12,7 +12,7 @@ import { } from 'os'; import * as path from 'path'; import * as util from 'util'; -import chalk = require('chalk'); +import * as pc from 'picocolors'; import yargs = require('yargs'); import {CustomConsole} from '@jest/console'; import type {JestEnvironment} from '@jest/environment'; @@ -142,7 +142,7 @@ export async function run( } } catch (error: any) { console.error( - chalk.red(util.types.isNativeError(error) ? error.stack : error), + pc.red(util.types.isNativeError(error) ? error.stack : error), ); process.on('exit', () => { process.exitCode = 1; diff --git a/packages/jest-reporters/package.json b/packages/jest-reporters/package.json index 6139af2073dc..ee68082bb0b2 100644 --- a/packages/jest-reporters/package.json +++ b/packages/jest-reporters/package.json @@ -21,7 +21,6 @@ "@jest/types": "workspace:*", "@jridgewell/trace-mapping": "^0.3.18", "@types/node": "*", - "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", "exit-x": "^0.2.2", "glob": "^10.3.10", @@ -34,6 +33,7 @@ "jest-message-util": "workspace:*", "jest-util": "workspace:*", "jest-worker": "workspace:*", + "picocolors": "^1.1.1", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", diff --git a/packages/jest-reporters/src/CoverageReporter.ts b/packages/jest-reporters/src/CoverageReporter.ts index 39b8636e39fa..5bb291b9e664 100644 --- a/packages/jest-reporters/src/CoverageReporter.ts +++ b/packages/jest-reporters/src/CoverageReporter.ts @@ -8,13 +8,13 @@ import * as path from 'path'; import {mergeProcessCovs} from '@bcoe/v8-coverage'; import type {EncodedSourceMap} from '@jridgewell/trace-mapping'; -import chalk = require('chalk'); import {glob} from 'glob'; import * as fs from 'graceful-fs'; import istanbulCoverage = require('istanbul-lib-coverage'); import istanbulReport = require('istanbul-lib-report'); import libSourceMaps = require('istanbul-lib-source-maps'); import istanbulReports = require('istanbul-reports'); +import * as pc from 'picocolors'; import v8toIstanbul = require('v8-to-istanbul'); import type { AggregatedResult, @@ -33,9 +33,6 @@ import type {ReporterContext} from './types'; type CoverageWorker = typeof import('./CoverageWorker'); -const FAIL_COLOR = chalk.bold.red; -const RUNNING_TEST_COLOR = chalk.bold.dim; - export default class CoverageReporter extends BaseReporter { private readonly _context: ReporterContext; private readonly _coverageMap: istanbulCoverage.CoverageMap; @@ -93,7 +90,7 @@ export default class CoverageReporter extends BaseReporter { aggregatedResults.coverageMap = map; } catch (error: any) { console.error( - chalk.red(` + pc.red(` Failed to write coverage reports: ERROR: ${error.toString()} STACK: ${error.stack} @@ -132,7 +129,7 @@ export default class CoverageReporter extends BaseReporter { if (isInteractive) { process.stderr.write( - RUNNING_TEST_COLOR('Running coverage on untested files...'), + pc.dim(pc.bold('Running coverage on untested files...')), ); } @@ -192,7 +189,7 @@ export default class CoverageReporter extends BaseReporter { } } catch (error: any) { console.error( - chalk.red( + pc.red( [ `Failed to collect coverage from ${filename}`, `ERROR: ${error.message}`, @@ -426,7 +423,7 @@ export default class CoverageReporter extends BaseReporter { ); if (errors.length > 0) { - this.log(`${FAIL_COLOR(errors.join('\n'))}`); + this.log(`${pc.bold(pc.red(errors.join('\n')))}`); this._setError(new Error(errors.join('\n'))); } } diff --git a/packages/jest-reporters/src/DefaultReporter.ts b/packages/jest-reporters/src/DefaultReporter.ts index f0f3f0bf680e..a3dd32d60211 100644 --- a/packages/jest-reporters/src/DefaultReporter.ts +++ b/packages/jest-reporters/src/DefaultReporter.ts @@ -6,7 +6,7 @@ */ import type {WriteStream} from 'tty'; -import chalk = require('chalk'); +import * as pc from 'picocolors'; import {getConsoleOutput} from '@jest/console'; import type { AggregatedResult, @@ -30,7 +30,7 @@ import type {ReporterOnStartOptions} from './types'; type write = WriteStream['write']; type FlushBufferedOutput = () => void; -const TITLE_BULLET = chalk.bold('\u25CF '); +const TITLE_BULLET = pc.bold('\u25CF '); export default class DefaultReporter extends BaseReporter { private _clear: string; // ANSI clear sequence for the last printed status @@ -206,20 +206,20 @@ export default class DefaultReporter extends BaseReporter { const testRetryReasons = testResult.retryReasons; if (testRetryReasons && testRetryReasons.length > 0) { this.log( - `${chalk.reset.inverse.bold.yellow(' LOGGING RETRY ERRORS ')} ${chalk.bold(testResult.fullName)}`, + `${pc.reset(pc.inverse(pc.bold(pc.yellow(' LOGGING RETRY ERRORS '))))} ${pc.bold(testResult.fullName)}`, ); for (const [index, retryReasons] of testRetryReasons.entries()) { let {message, stack} = separateMessageFromStack(retryReasons); stack = this._globalConfig.noStackTrace ? '' - : chalk.dim( + : pc.dim( formatStackTrace(stack, config, this._globalConfig, testPath), ); message = indentAllLines(message); this.log( - `${chalk.reset.inverse.bold.blueBright(` RETRY ${index + 1} `)}\n`, + `${pc.reset(pc.inverse(pc.bold(pc.blueBright(` RETRY ${index + 1} `))))}\n`, ); this.log(`${message}\n${stack}\n`); } diff --git a/packages/jest-reporters/src/GitHubActionsReporter.ts b/packages/jest-reporters/src/GitHubActionsReporter.ts index 5bd47a3ccac6..53e39854ed9e 100644 --- a/packages/jest-reporters/src/GitHubActionsReporter.ts +++ b/packages/jest-reporters/src/GitHubActionsReporter.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); +import * as pc from 'picocolors'; import stripAnsi = require('strip-ansi'); import type { AggregatedResult, @@ -314,15 +314,15 @@ export default class GitHubActionsReporter extends BaseReporter { private printResultTree(resultTree: ResultTree): void { let perfMs; if (resultTree.performanceInfo.slow) { - perfMs = ` (${chalk.red.inverse( - `${resultTree.performanceInfo.runtime} ms`, + perfMs = ` (${pc.red( + pc.inverse(`${resultTree.performanceInfo.runtime} ms`), )})`; } else { perfMs = ` (${resultTree.performanceInfo.runtime} ms)`; } if (resultTree.passed) { this.startGroup( - `${chalk.bold.green.inverse('PASS')} ${resultTree.name}${perfMs}`, + `${pc.bold(pc.green(pc.inverse('PASS')))} ${resultTree.name}${perfMs}`, ); for (const child of resultTree.children) { this.recursivePrintResultTree(child, true, 1); @@ -330,7 +330,7 @@ export default class GitHubActionsReporter extends BaseReporter { this.endGroup(); } else { this.log( - ` ${chalk.bold.red.inverse('FAIL')} ${resultTree.name}${perfMs}`, + ` ${pc.bold(pc.red(pc.inverse('FAIL')))} ${resultTree.name}${perfMs}`, ); for (const child of resultTree.children) { this.recursivePrintResultTree(child, false, 1); @@ -355,17 +355,17 @@ export default class GitHubActionsReporter extends BaseReporter { let resultSymbol; switch (resultTree.status) { case 'passed': - resultSymbol = chalk.green(ICONS.success); + resultSymbol = pc.green(ICONS.success); break; case 'failed': - resultSymbol = chalk.red(ICONS.failed); + resultSymbol = pc.red(ICONS.failed); break; case 'todo': - resultSymbol = chalk.magenta(ICONS.todo); + resultSymbol = pc.magenta(ICONS.todo); break; case 'pending': case 'skipped': - resultSymbol = chalk.yellow(ICONS.pending); + resultSymbol = pc.yellow(ICONS.pending); break; } this.log( diff --git a/packages/jest-reporters/src/Status.ts b/packages/jest-reporters/src/Status.ts index 8659c6e750c0..de309b0cd0d4 100644 --- a/packages/jest-reporters/src/Status.ts +++ b/packages/jest-reporters/src/Status.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); +import * as pc from 'picocolors'; import stringLength = require('string-length'); import type { AggregatedResult, @@ -21,7 +21,7 @@ import type {ReporterOnStartOptions} from './types'; import wrapAnsiString from './wrapAnsiString'; const RUNNING_TEXT = ' RUNS '; -const RUNNING = `${chalk.reset.inverse.yellow.bold(RUNNING_TEXT)} `; +const RUNNING = `${pc.reset(pc.inverse(pc.yellow(pc.bold(RUNNING_TEXT))))} `; /** * This class is a perf optimization for sorting the list of currently diff --git a/packages/jest-reporters/src/SummaryReporter.ts b/packages/jest-reporters/src/SummaryReporter.ts index 14a8884b27d3..939e91ae55c1 100644 --- a/packages/jest-reporters/src/SummaryReporter.ts +++ b/packages/jest-reporters/src/SummaryReporter.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); +import * as pc from 'picocolors'; import type { AggregatedResult, SnapshotSummary, @@ -131,7 +131,7 @@ export default class SummaryReporter extends BaseReporter { if (!this._globalConfig.silent) { message += `\n${ wasInterrupted - ? chalk.bold.red('Test run was interrupted.') + ? pc.bold(pc.red('Test run was interrupted.')) : this._getTestSummary(testContexts, this._globalConfig) }`; } @@ -194,7 +194,7 @@ export default class SummaryReporter extends BaseReporter { failedTests + runtimeErrors > 0 && aggregatedResults.numTotalTestSuites > this._summaryThreshold ) { - this.log(chalk.bold('Summary of all failing tests')); + this.log(pc.bold('Summary of all failing tests')); for (const testResult of aggregatedResults.testResults) { const {failureMessage} = testResult; if (failureMessage) { @@ -218,15 +218,15 @@ export default class SummaryReporter extends BaseReporter { ? ' related to files matching ' : ' matching '; - return chalk.dim(prefix) + testPathPatterns.toPretty(); + return pc.dim(prefix) + testPathPatterns.toPretty(); }; let testInfo = ''; if (globalConfig.runTestsByPath) { - testInfo = chalk.dim(' within paths'); + testInfo = pc.dim(' within paths'); } else if (globalConfig.onlyChanged) { - testInfo = chalk.dim(' related to changed files'); + testInfo = pc.dim(' related to changed files'); } else if (testPathPatterns.isSet()) { testInfo = getMatchingTestsInfo(); } @@ -236,22 +236,22 @@ export default class SummaryReporter extends BaseReporter { if (globalConfig.runTestsByPath) { nameInfo = ` ${globalConfig.nonFlagArgs.map(p => `"${p}"`).join(', ')}`; } else if (globalConfig.testNamePattern) { - nameInfo = `${chalk.dim(' with tests matching ')}"${ + nameInfo = `${pc.dim(' with tests matching ')}"${ globalConfig.testNamePattern }"`; } const contextInfo = testContexts.size > 1 - ? chalk.dim(' in ') + testContexts.size + chalk.dim(' projects') + ? pc.dim(' in ') + testContexts.size + pc.dim(' projects') : ''; return ( - chalk.dim('Ran all test suites') + + pc.dim('Ran all test suites') + testInfo + nameInfo + contextInfo + - chalk.dim('.') + pc.dim('.') ); } } diff --git a/packages/jest-reporters/src/VerboseReporter.ts b/packages/jest-reporters/src/VerboseReporter.ts index 3979c75bcad2..8b4d909895cb 100644 --- a/packages/jest-reporters/src/VerboseReporter.ts +++ b/packages/jest-reporters/src/VerboseReporter.ts @@ -6,7 +6,7 @@ */ import type {WriteStream} from 'tty'; -import chalk = require('chalk'); +import * as pc from 'picocolors'; import type { AggregatedResult, AssertionResult, @@ -115,13 +115,13 @@ export default class VerboseReporter extends DefaultReporter { private _getIcon(status: string) { if (status === 'failed') { - return chalk.red(ICONS.failed); + return pc.red(ICONS.failed); } else if (status === 'pending') { - return chalk.yellow(ICONS.pending); + return pc.yellow(ICONS.pending); } else if (status === 'todo') { - return chalk.magenta(ICONS.todo); + return pc.magenta(ICONS.todo); } else { - return chalk.green(ICONS.success); + return pc.green(ICONS.success); } } @@ -130,7 +130,7 @@ export default class VerboseReporter extends DefaultReporter { const time = test.duration ? ` (${formatTime(Math.round(test.duration))})` : ''; - this._logLine(`${status} ${chalk.dim(test.title + time)}`, indentLevel); + this._logLine(`${status} ${pc.dim(test.title + time)}`, indentLevel); } private _logTests(tests: Array, indentLevel: number) { @@ -171,7 +171,7 @@ export default class VerboseReporter extends DefaultReporter { const printedTestStatus = test.status === 'pending' ? 'skipped' : test.status; const icon = this._getIcon(test.status); - const text = chalk.dim(`${printedTestStatus} ${test.title}`); + const text = pc.dim(`${printedTestStatus} ${test.title}`); this._logLine(`${icon} ${text}`, indentLevel); }; } diff --git a/packages/jest-reporters/src/__tests__/utils.test.ts b/packages/jest-reporters/src/__tests__/utils.test.ts index 68444f537ee2..f945ced66b02 100644 --- a/packages/jest-reporters/src/__tests__/utils.test.ts +++ b/packages/jest-reporters/src/__tests__/utils.test.ts @@ -6,7 +6,7 @@ */ import * as path from 'path'; -import chalk = require('chalk'); +import * as pc from 'picocolors'; import stripAnsi = require('strip-ansi'); import {makeProjectConfig} from '@jest/test-utils'; import printDisplayName from '../printDisplayName'; @@ -16,10 +16,10 @@ import wrapAnsiString from '../wrapAnsiString'; describe('wrapAnsiString()', () => { it('wraps a long string containing ansi chars', () => { const string = - `abcde ${chalk.red.bold('red-bold')} 1234456` + - `${chalk.dim('bcd')} ` + + `abcde ${pc.red(pc.bold('red-bold'))} 1234456` + + `${pc.dim('bcd')} ` + '123ttttttththththththththththththththththththththth' + - `tetetetetettetetetetetetetete${chalk.underline.bold('stnhsnthsnth')}` + + `tetetetetettetetetetetetetete${pc.underline(pc.bold('stnhsnthsnth'))}` + 'ssot'; expect(wrapAnsiString(string, 10)).toMatchSnapshot(); expect(stripAnsi(wrapAnsiString(string, 10))).toMatchSnapshot(); diff --git a/packages/jest-reporters/src/formatTestPath.ts b/packages/jest-reporters/src/formatTestPath.ts index faed8e0d002c..9423b7c587e2 100644 --- a/packages/jest-reporters/src/formatTestPath.ts +++ b/packages/jest-reporters/src/formatTestPath.ts @@ -6,7 +6,7 @@ */ import * as path from 'path'; -import chalk = require('chalk'); +import * as pc from 'picocolors'; import slash = require('slash'); import type {Config} from '@jest/types'; import relativePath from './relativePath'; @@ -16,5 +16,5 @@ export default function formatTestPath( testPath: string, ): string { const {dirname, basename} = relativePath(config, testPath); - return slash(chalk.dim(dirname + path.sep) + chalk.bold(basename)); + return slash(pc.dim(dirname + path.sep) + pc.bold(basename)); } diff --git a/packages/jest-reporters/src/getResultHeader.ts b/packages/jest-reporters/src/getResultHeader.ts index 9126143918c6..a61200e675ca 100644 --- a/packages/jest-reporters/src/getResultHeader.ts +++ b/packages/jest-reporters/src/getResultHeader.ts @@ -5,25 +5,25 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); +import * as pc from 'picocolors'; import type {TestResult} from '@jest/test-result'; import type {Config} from '@jest/types'; import {formatTime} from 'jest-util'; import formatTestPath from './formatTestPath'; import printDisplayName from './printDisplayName'; -const LONG_TEST_COLOR = chalk.reset.bold.bgRed; +const LONG_TEST_COLOR = (str: string) => pc.reset(pc.bold(pc.bgRed(str))); // Explicitly reset for these messages since they can get written out in the // middle of error logging const FAIL_TEXT = 'FAIL'; const PASS_TEXT = 'PASS'; -const FAIL = chalk.supportsColor - ? chalk.reset.inverse.bold.red(` ${FAIL_TEXT} `) +const FAIL = pc.isColorSupported + ? pc.reset(pc.inverse(pc.bold(pc.red(` ${FAIL_TEXT} `)))) : FAIL_TEXT; -const PASS = chalk.supportsColor - ? chalk.reset.inverse.bold.green(` ${PASS_TEXT} `) +const PASS = pc.isColorSupported + ? pc.reset(pc.inverse(pc.bold(pc.green(` ${PASS_TEXT} `)))) : PASS_TEXT; export default function getResultHeader( diff --git a/packages/jest-reporters/src/getSnapshotStatus.ts b/packages/jest-reporters/src/getSnapshotStatus.ts index 9a58f3d33387..8c09e815a034 100644 --- a/packages/jest-reporters/src/getSnapshotStatus.ts +++ b/packages/jest-reporters/src/getSnapshotStatus.ts @@ -5,16 +5,16 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); +import * as pc from 'picocolors'; import type {TestResult} from '@jest/test-result'; import {pluralize} from 'jest-util'; const ARROW = ' \u203A '; const DOT = ' \u2022 '; -const FAIL_COLOR = chalk.bold.red; -const SNAPSHOT_ADDED = chalk.bold.green; -const SNAPSHOT_UPDATED = chalk.bold.green; -const SNAPSHOT_OUTDATED = chalk.bold.yellow; +const FAIL_COLOR = (str: string) => pc.bold(pc.red(str)); +const SNAPSHOT_ADDED = (str: string) => pc.bold(pc.green(str)); +const SNAPSHOT_UPDATED = (str: string) => pc.bold(pc.green(str)); +const SNAPSHOT_OUTDATED = (str: string) => pc.bold(pc.yellow(str)); export default function getSnapshotStatus( snapshot: TestResult['snapshot'], diff --git a/packages/jest-reporters/src/getSnapshotSummary.ts b/packages/jest-reporters/src/getSnapshotSummary.ts index 535b3f3f36d6..4682649f8c15 100644 --- a/packages/jest-reporters/src/getSnapshotSummary.ts +++ b/packages/jest-reporters/src/getSnapshotSummary.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); +import * as pc from 'picocolors'; import type {SnapshotSummary} from '@jest/test-result'; import type {Config} from '@jest/types'; import {pluralize} from 'jest-util'; @@ -14,13 +14,13 @@ import formatTestPath from './formatTestPath'; const ARROW = ' \u203A '; const DOWN_ARROW = ' \u21B3 '; const DOT = ' \u2022 '; -const FAIL_COLOR = chalk.bold.red; -const OBSOLETE_COLOR = chalk.bold.yellow; -const SNAPSHOT_ADDED = chalk.bold.green; -const SNAPSHOT_NOTE = chalk.dim; -const SNAPSHOT_REMOVED = chalk.bold.green; -const SNAPSHOT_SUMMARY = chalk.bold; -const SNAPSHOT_UPDATED = chalk.bold.green; +const FAIL_COLOR = (str: string) => pc.bold(pc.red(str)); +const OBSOLETE_COLOR = (str: string) => pc.bold(pc.yellow(str)); +const SNAPSHOT_ADDED = (str: string) => pc.bold(pc.green(str)); +const SNAPSHOT_NOTE = pc.dim; +const SNAPSHOT_REMOVED = (str: string) => pc.bold(pc.green(str)); +const SNAPSHOT_SUMMARY = pc.bold; +const SNAPSHOT_UPDATED = (str: string) => pc.bold(pc.green(str)); export default function getSnapshotSummary( snapshots: SnapshotSummary, diff --git a/packages/jest-reporters/src/getSummary.ts b/packages/jest-reporters/src/getSummary.ts index 6e2bb5fe3725..e2db11d991ca 100644 --- a/packages/jest-reporters/src/getSummary.ts +++ b/packages/jest-reporters/src/getSummary.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); +import * as pc from 'picocolors'; import type {AggregatedResult, Test, TestCaseResult} from '@jest/test-result'; import {formatTime, pluralize} from 'jest-util'; import type {SummaryOptions} from './types'; @@ -55,9 +55,9 @@ function renderTime(runTime: number, estimatedTime: number, width: number) { // If we are more than one second over the estimated time, highlight it. const renderedTime = estimatedTime && runTime >= estimatedTime + 1 - ? chalk.bold.yellow(formatTime(runTime, 0)) + ? pc.bold(pc.yellow(formatTime(runTime, 0))) : formatTime(runTime, 0); - let time = `${chalk.bold('Time:')} ${renderedTime}`; + let time = `${pc.bold('Time:')} ${renderedTime}`; if (runTime < estimatedTime) { time += `, estimated ${formatTime(estimatedTime, 0)}`; } @@ -71,7 +71,7 @@ function renderTime(runTime: number, estimatedTime: number, width: number) { availableWidth, ); if (availableWidth >= 2) { - time += `\n${chalk.green('█').repeat(length)}${chalk + time += `\n${pc.green('█').repeat(length)}${pc .white('█') .repeat(availableWidth - length)}`; } @@ -121,16 +121,16 @@ export default function getSummary( if (seed === undefined) { throw new Error('Attempted to display seed but seed value is undefined'); } - optionalLines.push(`${chalk.bold('Seed: ') + seed}`); + optionalLines.push(`${pc.bold('Seed: ') + seed}`); } const suites = `${ - chalk.bold('Test Suites: ') + - (suitesFailed ? `${chalk.bold.red(`${suitesFailed} failed`)}, ` : '') + + pc.bold('Test Suites: ') + + (suitesFailed ? `${pc.bold(pc.red(`${suitesFailed} failed`))}, ` : '') + (suitesPending - ? `${chalk.bold.yellow(`${suitesPending} skipped`)}, ` + ? `${pc.bold(pc.yellow(`${suitesPending} skipped`))}, ` : '') + - (suitesPassed ? `${chalk.bold.green(`${suitesPassed} passed`)}, ` : '') + + (suitesPassed ? `${pc.bold(pc.green(`${suitesPassed} passed`))}, ` : '') + (suitesRun === suitesTotal ? suitesTotal : `${suitesRun} of ${suitesTotal}`) } total`; @@ -145,50 +145,50 @@ export default function getSummary( testsTotal + valuesForCurrentTestCases.numTotalTests; const tests = `${ - chalk.bold('Tests: ') + + pc.bold('Tests: ') + (updatedTestsFailed > 0 - ? `${chalk.bold.red(`${updatedTestsFailed} failed`)}, ` + ? `${pc.bold(pc.red(`${updatedTestsFailed} failed`))}, ` : '') + (updatedTestsPending > 0 - ? `${chalk.bold.yellow(`${updatedTestsPending} skipped`)}, ` + ? `${pc.bold(pc.yellow(`${updatedTestsPending} skipped`))}, ` : '') + (updatedTestsTodo > 0 - ? `${chalk.bold.magenta(`${updatedTestsTodo} todo`)}, ` + ? `${pc.bold(pc.magenta(`${updatedTestsTodo} todo`))}, ` : '') + (updatedTestsPassed > 0 - ? `${chalk.bold.green(`${updatedTestsPassed} passed`)}, ` + ? `${pc.bold(pc.green(`${updatedTestsPassed} passed`))}, ` : '') }${updatedTestsTotal} total`; const snapshots = `${ - chalk.bold('Snapshots: ') + + pc.bold('Snapshots: ') + (snapshotsFailed - ? `${chalk.bold.red(`${snapshotsFailed} failed`)}, ` + ? `${pc.bold(pc.red(`${snapshotsFailed} failed`))}, ` : '') + (snapshotsOutdated && !snapshotsDidUpdate - ? `${chalk.bold.yellow(`${snapshotsOutdated} obsolete`)}, ` + ? `${pc.bold(pc.yellow(`${snapshotsOutdated} obsolete`))}, ` : '') + (snapshotsOutdated && snapshotsDidUpdate - ? `${chalk.bold.green(`${snapshotsOutdated} removed`)}, ` + ? `${pc.bold(pc.green(`${snapshotsOutdated} removed`))}, ` : '') + (snapshotsFilesRemoved && !snapshotsDidUpdate - ? `${chalk.bold.yellow( - `${pluralize('file', snapshotsFilesRemoved)} obsolete`, + ? `${pc.bold( + pc.yellow(`${pluralize('file', snapshotsFilesRemoved)} obsolete`), )}, ` : '') + (snapshotsFilesRemoved && snapshotsDidUpdate - ? `${chalk.bold.green( - `${pluralize('file', snapshotsFilesRemoved)} removed`, + ? `${pc.bold( + pc.green(`${pluralize('file', snapshotsFilesRemoved)} removed`), )}, ` : '') + (snapshotsUpdated - ? `${chalk.bold.green(`${snapshotsUpdated} updated`)}, ` + ? `${pc.bold(pc.green(`${snapshotsUpdated} updated`))}, ` : '') + (snapshotsAdded - ? `${chalk.bold.green(`${snapshotsAdded} written`)}, ` + ? `${pc.bold(pc.green(`${snapshotsAdded} written`))}, ` : '') + (snapshotsPassed - ? `${chalk.bold.green(`${snapshotsPassed} passed`)}, ` + ? `${pc.bold(pc.green(`${snapshotsPassed} passed`))}, ` : '') }${snapshotsTotal} total`; diff --git a/packages/jest-reporters/src/printDisplayName.ts b/packages/jest-reporters/src/printDisplayName.ts index 02b14069f2df..456302ac0a7e 100644 --- a/packages/jest-reporters/src/printDisplayName.ts +++ b/packages/jest-reporters/src/printDisplayName.ts @@ -5,17 +5,18 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); +import * as pc from 'picocolors'; import type {Config} from '@jest/types'; export default function printDisplayName(config: Config.ProjectConfig): string { const {displayName} = config; - const white = chalk.reset.inverse.white; + const white = (str: string) => pc.reset(pc.inverse(pc.white(str))); if (!displayName) { return ''; } const {name, color} = displayName; - const chosenColor = chalk.reset.inverse[color] ?? white; - return chalk.supportsColor ? chosenColor(` ${name} `) : name; + const chosenColor = (str: string) => + color ? pc.reset(pc.inverse(pc.createColors()[color](str))) : white(str); + return pc.isColorSupported ? chosenColor(` ${name} `) : name; } diff --git a/packages/jest-reporters/src/trimAndFormatPath.ts b/packages/jest-reporters/src/trimAndFormatPath.ts index 3a54bd9bca00..a220f965dbdd 100644 --- a/packages/jest-reporters/src/trimAndFormatPath.ts +++ b/packages/jest-reporters/src/trimAndFormatPath.ts @@ -6,7 +6,7 @@ */ import * as path from 'path'; -import chalk = require('chalk'); +import * as pc from 'picocolors'; import slash = require('slash'); import type {Config} from '@jest/types'; import relativePath from './relativePath'; @@ -24,7 +24,7 @@ export default function trimAndFormatPath( // length is ok if ((dirname + path.sep + basename).length <= maxLength) { - return slash(chalk.dim(dirname + path.sep) + chalk.bold(basename)); + return slash(pc.dim(dirname + path.sep) + pc.bold(basename)); } // we can fit trimmed dirname and full basename @@ -32,15 +32,15 @@ export default function trimAndFormatPath( if (basenameLength + 4 < maxLength) { const dirnameLength = maxLength - 4 - basenameLength; dirname = `...${dirname.slice(dirname.length - dirnameLength)}`; - return slash(chalk.dim(dirname + path.sep) + chalk.bold(basename)); + return slash(pc.dim(dirname + path.sep) + pc.bold(basename)); } if (basenameLength + 4 === maxLength) { - return slash(chalk.dim(`...${path.sep}`) + chalk.bold(basename)); + return slash(pc.dim(`...${path.sep}`) + pc.bold(basename)); } // can't fit dirname, but can fit trimmed basename return slash( - chalk.bold(`...${basename.slice(basename.length - maxLength - 4)}`), + pc.bold(`...${basename.slice(basename.length - maxLength - 4)}`), ); } diff --git a/packages/jest-resolve/package.json b/packages/jest-resolve/package.json index b49593aaa057..45dda004c06a 100644 --- a/packages/jest-resolve/package.json +++ b/packages/jest-resolve/package.json @@ -19,12 +19,12 @@ "./package.json": "./package.json" }, "dependencies": { - "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "jest-haste-map": "workspace:*", "jest-pnp-resolver": "^1.2.2", "jest-util": "workspace:*", "jest-validate": "workspace:*", + "picocolors": "^1.1.1", "resolve": "^1.20.0", "resolve.exports": "^2.0.0", "slash": "^3.0.0" diff --git a/packages/jest-resolve/src/__tests__/isBuiltinModule.test.ts b/packages/jest-resolve/src/__tests__/isBuiltinModule.test.ts index 5d8412b27131..427717f8fa96 100644 --- a/packages/jest-resolve/src/__tests__/isBuiltinModule.test.ts +++ b/packages/jest-resolve/src/__tests__/isBuiltinModule.test.ts @@ -12,8 +12,8 @@ describe('isBuiltinModule', () => { expect(isBuiltinModule('path')).toBe(true); }); - it('should return false for the `chalk` module', () => { - expect(isBuiltinModule('chalk')).toBe(false); + it('should return false for the `picocolors` module', () => { + expect(isBuiltinModule('picocolors')).toBe(false); }); it('should return true for the `_http_common` module', () => { diff --git a/packages/jest-resolve/src/resolver.ts b/packages/jest-resolve/src/resolver.ts index 32bb4d8cd9f9..32f7abf3d30a 100644 --- a/packages/jest-resolve/src/resolver.ts +++ b/packages/jest-resolve/src/resolver.ts @@ -6,7 +6,7 @@ */ import * as path from 'path'; -import chalk = require('chalk'); +import * as pc from 'picocolors'; import slash = require('slash'); import type {IModuleMap} from 'jest-haste-map'; import {tryRealpath} from 'jest-util'; @@ -838,17 +838,17 @@ const createNoMappedModuleFoundError = ( : mappedModuleName; const error = new Error( - chalk.red(`${chalk.bold('Configuration error')}: + pc.red(`${pc.bold('Configuration error')}: -Could not locate module ${chalk.bold(moduleName)} mapped as: -${chalk.bold(mappedAs)}. +Could not locate module ${pc.bold(moduleName)} mapped as: +${pc.bold(mappedAs)}. Please check your configuration for these entries: { "moduleNameMapper": { - "${regex.toString()}": "${chalk.bold(original)}" + "${regex.toString()}": "${pc.bold(original)}" }, - "resolver": ${chalk.bold(String(resolver))} + "resolver": ${pc.bold(String(resolver))} }`), ); diff --git a/packages/jest-resolve/src/utils.ts b/packages/jest-resolve/src/utils.ts index 979a2f0921ac..f82f46cf7cf7 100644 --- a/packages/jest-resolve/src/utils.ts +++ b/packages/jest-resolve/src/utils.ts @@ -6,12 +6,12 @@ */ import * as path from 'path'; -import chalk = require('chalk'); +import * as pc from 'picocolors'; import {ValidationError} from 'jest-validate'; import Resolver from './resolver'; -const BULLET: string = chalk.bold('\u25CF '); -const DOCUMENTATION_NOTE = ` ${chalk.bold('Configuration Documentation:')} +const BULLET: string = pc.bold('\u25CF '); +const DOCUMENTATION_NOTE = ` ${pc.bold('Configuration Documentation:')} https://jestjs.io/docs/configuration `; @@ -73,9 +73,9 @@ const resolveWithPrefix = ( } catch {} throw createValidationError( - ` ${humanOptionName} ${chalk.bold( + ` ${humanOptionName} ${pc.bold( fileName, - )} cannot be found. Make sure the ${chalk.bold( + )} cannot be found. Make sure the ${pc.bold( optionName, )} configuration option points to an existing node module.`, ); diff --git a/packages/jest-runner/package.json b/packages/jest-runner/package.json index 6ff6584a8659..8c5eb332a2a3 100644 --- a/packages/jest-runner/package.json +++ b/packages/jest-runner/package.json @@ -25,7 +25,6 @@ "@jest/transform": "workspace:*", "@jest/types": "workspace:*", "@types/node": "*", - "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", "jest-docblock": "workspace:*", @@ -39,6 +38,7 @@ "jest-watcher": "workspace:*", "jest-worker": "workspace:*", "p-limit": "^3.1.0", + "picocolors": "^1.1.1", "source-map-support": "0.5.13" }, "devDependencies": { diff --git a/packages/jest-runner/src/index.ts b/packages/jest-runner/src/index.ts index f55f2791f262..e3c0bb13aca3 100644 --- a/packages/jest-runner/src/index.ts +++ b/packages/jest-runner/src/index.ts @@ -5,9 +5,9 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); import Emittery = require('emittery'); import pLimit = require('p-limit'); +import * as pc from 'picocolors'; import type { Test, TestEvents, @@ -184,7 +184,7 @@ export default class TestRunner extends EmittingTestRunner { const {forceExited} = await worker.end(); if (forceExited) { console.error( - chalk.yellow( + pc.yellow( 'A worker process has failed to exit gracefully and has been force exited. ' + 'This is likely caused by tests leaking due to improper teardown. ' + 'Try running with --detectOpenHandles to find leaks. ' + diff --git a/packages/jest-runner/src/runTest.ts b/packages/jest-runner/src/runTest.ts index 5a20296dd21e..294812c3e297 100644 --- a/packages/jest-runner/src/runTest.ts +++ b/packages/jest-runner/src/runTest.ts @@ -7,8 +7,8 @@ */ import {runInContext} from 'node:vm'; -import chalk = require('chalk'); import * as fs from 'graceful-fs'; +import * as pc from 'picocolors'; import sourcemapSupport = require('source-map-support'); import { BufferedConsole, @@ -46,8 +46,8 @@ function freezeConsole( message: LogMessage, ) { const error = new ErrorWithStack( - `${chalk.red( - `${chalk.bold( + `${pc.red( + `${pc.bold( 'Cannot log after tests are done.', )} Did you forget to wait for something async in your test?`, )}\nAttempted to log "${message}".`, diff --git a/packages/jest-runtime/package.json b/packages/jest-runtime/package.json index fab7dca046ce..292fb759028f 100644 --- a/packages/jest-runtime/package.json +++ b/packages/jest-runtime/package.json @@ -27,7 +27,6 @@ "@jest/transform": "workspace:*", "@jest/types": "workspace:*", "@types/node": "*", - "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", "glob": "^10.3.10", @@ -39,6 +38,7 @@ "jest-resolve": "workspace:*", "jest-snapshot": "workspace:*", "jest-util": "workspace:*", + "picocolors": "^1.1.1", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts index e054e894d211..f33d4127f27a 100644 --- a/packages/jest-runtime/src/index.ts +++ b/packages/jest-runtime/src/index.ts @@ -112,7 +112,9 @@ type ModuleRegistry = Map; // users who require one of these modules in their tests will still get the module from inside the VM. // Prefer listing a module here only if it is impractical to use the jest-resolve-outside-vm-option where it is required, // e.g. because there are many require sites spread across the dependency graph. -const INTERNAL_MODULE_REQUIRE_OUTSIDE_OPTIMIZED_MODULES = new Set(['chalk']); +const INTERNAL_MODULE_REQUIRE_OUTSIDE_OPTIMIZED_MODULES = new Set([ + 'picocolors', +]); const JEST_RESOLVE_OUTSIDE_VM_OPTION = Symbol.for( 'jest-resolve-outside-vm-option', ); diff --git a/packages/jest-snapshot-utils/package.json b/packages/jest-snapshot-utils/package.json index 9e9ff0c3136e..142985e128ca 100644 --- a/packages/jest-snapshot-utils/package.json +++ b/packages/jest-snapshot-utils/package.json @@ -20,9 +20,9 @@ }, "dependencies": { "@jest/types": "workspace:*", - "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "natural-compare": "^1.4.0" + "natural-compare": "^1.4.0", + "picocolors": "^1.1.1" }, "devDependencies": { "@types/graceful-fs": "^4.1.3", diff --git a/packages/jest-snapshot-utils/src/__tests__/utils.test.ts b/packages/jest-snapshot-utils/src/__tests__/utils.test.ts index 62c0d6cb339d..286d2bf98afe 100644 --- a/packages/jest-snapshot-utils/src/__tests__/utils.test.ts +++ b/packages/jest-snapshot-utils/src/__tests__/utils.test.ts @@ -11,8 +11,8 @@ jest.mock('graceful-fs', () => ({ })); import * as path from 'path'; -import chalk = require('chalk'); import * as fs from 'graceful-fs'; +import pc = require('picocolors'); import { SNAPSHOT_GUIDE_LINK, SNAPSHOT_VERSION, @@ -72,8 +72,8 @@ test('getSnapshotData() throws when no snapshot version', () => { const update = 'none'; expect(() => getSnapshotData(filename, update)).toThrow( - chalk.red( - `${chalk.bold('Outdated snapshot')}: No snapshot header found. ` + + pc.red( + `${pc.bold('Outdated snapshot')}: No snapshot header found. ` + 'Jest 19 introduced versioned snapshots to ensure all developers on ' + 'a project are using the same version of Jest. ' + 'Please update all snapshots during this upgrade of Jest.\n\n', @@ -92,8 +92,8 @@ test('getSnapshotData() throws for older snapshot version', () => { const update = 'none'; expect(() => getSnapshotData(filename, update)).toThrow( - `${chalk.red( - `${chalk.red.bold('Outdated snapshot')}: The version of the snapshot ` + + `${pc.red( + `${pc.red(pc.bold('Outdated snapshot'))}: The version of the snapshot ` + 'file associated with this test is outdated. The snapshot file ' + 'version ensures that all developers on a project are using ' + 'the same version of Jest. ' + @@ -114,8 +114,8 @@ test('getSnapshotData() throws for newer snapshot version', () => { const update = 'none'; expect(() => getSnapshotData(filename, update)).toThrow( - `${chalk.red( - `${chalk.red.bold('Outdated Jest version')}: The version of this ` + + `${pc.red( + `${pc.red(pc.bold('Outdated Jest version'))}: The version of this ` + 'snapshot file indicates that this project is meant to be used ' + 'with a newer version of Jest. ' + 'The snapshot file version ensures that all developers on a project ' + diff --git a/packages/jest-snapshot-utils/src/utils.ts b/packages/jest-snapshot-utils/src/utils.ts index 2c81b4a9c52f..bb7c1b488112 100644 --- a/packages/jest-snapshot-utils/src/utils.ts +++ b/packages/jest-snapshot-utils/src/utils.ts @@ -6,17 +6,17 @@ */ import * as path from 'path'; -import chalk = require('chalk'); import * as fs from 'graceful-fs'; import naturalCompare = require('natural-compare'); +import pc = require('picocolors'); import type {Config} from '@jest/types'; import type {SnapshotData} from './types'; export const SNAPSHOT_VERSION = '1'; const SNAPSHOT_VERSION_REGEXP = /^\/\/ Jest Snapshot v(.+),/; export const SNAPSHOT_GUIDE_LINK = 'https://goo.gl/fbAQLP'; -export const SNAPSHOT_VERSION_WARNING = chalk.yellow( - `${chalk.bold('Warning')}: Before you upgrade snapshots, ` + +export const SNAPSHOT_VERSION_WARNING = pc.yellow( + `${pc.bold('Warning')}: Before you upgrade snapshots, ` + 'we recommend that you revert any local changes to tests or other code, ' + 'to ensure that you do not store invalid state.', ); @@ -30,8 +30,8 @@ const validateSnapshotVersion = (snapshotContents: string) => { if (!version) { return new Error( - chalk.red( - `${chalk.bold('Outdated snapshot')}: No snapshot header found. ` + + pc.red( + `${pc.bold('Outdated snapshot')}: No snapshot header found. ` + 'Jest 19 introduced versioned snapshots to ensure all developers ' + 'on a project are using the same version of Jest. ' + 'Please update all snapshots during this upgrade of Jest.\n\n', @@ -42,8 +42,8 @@ const validateSnapshotVersion = (snapshotContents: string) => { if (version < SNAPSHOT_VERSION) { return new Error( // eslint-disable-next-line prefer-template - chalk.red( - `${chalk.red.bold('Outdated snapshot')}: The version of the snapshot ` + + pc.red( + `${pc.red(pc.bold('Outdated snapshot'))}: The version of the snapshot ` + 'file associated with this test is outdated. The snapshot file ' + 'version ensures that all developers on a project are using ' + 'the same version of Jest. ' + @@ -59,8 +59,8 @@ const validateSnapshotVersion = (snapshotContents: string) => { if (version > SNAPSHOT_VERSION) { return new Error( // eslint-disable-next-line prefer-template - chalk.red( - `${chalk.red.bold('Outdated Jest version')}: The version of this ` + + pc.red( + `${pc.red(pc.bold('Outdated Jest version'))}: The version of this ` + 'snapshot file indicates that this project is meant to be used ' + 'with a newer version of Jest. The snapshot file version ensures ' + 'that all developers on a project are using the same version of ' + diff --git a/packages/jest-transform/package.json b/packages/jest-transform/package.json index ac7ee5d31841..68a19a705a9a 100644 --- a/packages/jest-transform/package.json +++ b/packages/jest-transform/package.json @@ -23,7 +23,6 @@ "@jest/types": "workspace:*", "@jridgewell/trace-mapping": "^0.3.18", "babel-plugin-istanbul": "^7.0.0", - "chalk": "^4.0.0", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", @@ -31,6 +30,7 @@ "jest-regex-util": "workspace:*", "jest-util": "workspace:*", "micromatch": "^4.0.8", + "picocolors": "^1.1.1", "pirates": "^4.0.4", "slash": "^3.0.0", "write-file-atomic": "^5.0.0" diff --git a/packages/jest-transform/src/enhanceUnexpectedTokenMessage.ts b/packages/jest-transform/src/enhanceUnexpectedTokenMessage.ts index 14cda0cbc3ef..0432ed4a6591 100644 --- a/packages/jest-transform/src/enhanceUnexpectedTokenMessage.ts +++ b/packages/jest-transform/src/enhanceUnexpectedTokenMessage.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); +import pc = require('picocolors'); const DOT = ' \u2022 '; @@ -32,7 +32,7 @@ export default function handlePotentialSyntaxError( } export function enhanceUnexpectedTokenMessage(e: Error): Error { - e.stack = `${chalk.bold.red('Jest encountered an unexpected token')} + e.stack = `${pc.bold(pc.red('Jest encountered an unexpected token'))} Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax. @@ -41,28 +41,28 @@ Out of the box Jest supports Babel, which will be used to transform your files i By default "node_modules" folder is ignored by transformers. Here's what you can do: -${DOT}If you are trying to use ECMAScript Modules, see ${chalk.underline( +${DOT}If you are trying to use ECMAScript Modules, see ${pc.underline( 'https://jestjs.io/docs/ecmascript-modules', )} for how to enable it. -${DOT}If you are trying to use TypeScript, see ${chalk.underline( +${DOT}If you are trying to use TypeScript, see ${pc.underline( 'https://jestjs.io/docs/getting-started#using-typescript', )} -${DOT}To have some of your "node_modules" files transformed, you can specify a custom ${chalk.bold( +${DOT}To have some of your "node_modules" files transformed, you can specify a custom ${pc.bold( '"transformIgnorePatterns"', )} in your config. -${DOT}If you need a custom transformation, specify a ${chalk.bold( +${DOT}If you need a custom transformation, specify a ${pc.bold( '"transform"', )} option in your config. -${DOT}If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the ${chalk.bold( +${DOT}If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the ${pc.bold( '"moduleNameMapper"', )} config option. You'll find more details and examples of these config options in the docs: -${chalk.cyan('https://jestjs.io/docs/configuration')} +${pc.cyan('https://jestjs.io/docs/configuration')} For information about custom transformations, see: -${chalk.cyan('https://jestjs.io/docs/code-transformation')} +${pc.cyan('https://jestjs.io/docs/code-transformation')} -${chalk.bold.red('Details:')} +${pc.bold(pc.red('Details:'))} ${e.stack ?? ''}`.trimEnd(); diff --git a/packages/jest-transform/src/runtimeErrorsAndWarnings.ts b/packages/jest-transform/src/runtimeErrorsAndWarnings.ts index 14173e22c753..b6dac8e29ac2 100644 --- a/packages/jest-transform/src/runtimeErrorsAndWarnings.ts +++ b/packages/jest-transform/src/runtimeErrorsAndWarnings.ts @@ -5,25 +5,23 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); +import pc = require('picocolors'); import slash = require('slash'); const BULLET = '\u25CF '; -const DOCUMENTATION_NOTE = ` ${chalk.bold( - 'Code Transformation Documentation:', -)} +const DOCUMENTATION_NOTE = ` ${pc.bold('Code Transformation Documentation:')} https://jestjs.io/docs/code-transformation `; -const UPGRADE_NOTE = ` ${chalk.bold( +const UPGRADE_NOTE = ` ${pc.bold( 'This error may be caused by a breaking change in Jest 28:', )} https://jest-archive-august-2023.netlify.app/docs/28.x/upgrading-to-jest28#transformer `; export const makeInvalidReturnValueError = (transformPath: string): string => - chalk.red( + pc.red( [ - chalk.bold(`${BULLET}Invalid return value:`), + pc.bold(`${BULLET}Invalid return value:`), ' `process()` or/and `processAsync()` method of code transformer found at ', ` "${slash(transformPath)}" `, ' should return an object or a Promise resolving to an object. The object ', @@ -38,9 +36,9 @@ export const makeInvalidSourceMapWarning = ( filename: string, transformPath: string, ): string => - chalk.yellow( + pc.yellow( [ - chalk.bold(`${BULLET}Invalid source map:`), + pc.bold(`${BULLET}Invalid source map:`), ` The source map for "${slash(filename)}" returned by "${slash( transformPath, )}" is invalid.`, @@ -51,9 +49,9 @@ export const makeInvalidSourceMapWarning = ( export const makeInvalidSyncTransformerError = ( transformPath: string, ): string => - chalk.red( + pc.red( [ - chalk.bold(`${BULLET}Invalid synchronous transformer module:`), + pc.bold(`${BULLET}Invalid synchronous transformer module:`), ` "${slash( transformPath, )}" specified in the "transform" object of Jest configuration`, @@ -63,9 +61,9 @@ export const makeInvalidSyncTransformerError = ( ); export const makeInvalidTransformerError = (transformPath: string): string => - chalk.red( + pc.red( [ - chalk.bold(`${BULLET}Invalid transformer module:`), + pc.bold(`${BULLET}Invalid transformer module:`), ` "${slash( transformPath, )}" specified in the "transform" object of Jest configuration`, diff --git a/packages/jest-types/package.json b/packages/jest-types/package.json index 06d9da2267b2..8f5b0109e1d1 100644 --- a/packages/jest-types/package.json +++ b/packages/jest-types/package.json @@ -26,7 +26,7 @@ "@types/istanbul-reports": "^3.0.0", "@types/node": "*", "@types/yargs": "^17.0.8", - "chalk": "^4.0.0" + "picocolors": "^1.1.1" }, "publishConfig": { "access": "public" diff --git a/packages/jest-types/src/Config.ts b/packages/jest-types/src/Config.ts index 154e4bfc1043..2f477fe5850a 100644 --- a/packages/jest-types/src/Config.ts +++ b/packages/jest-types/src/Config.ts @@ -5,7 +5,6 @@ * LICENSE file in the root directory of this source tree. */ -import type {ForegroundColor} from 'chalk'; import type {ReportOptions} from 'istanbul-reports'; import type {Arguments} from 'yargs'; import type {TestPathPatterns} from '@jest/pattern'; @@ -216,7 +215,15 @@ export type DefaultOptions = { export type DisplayName = { name: string; - color: typeof ForegroundColor; + color: + | 'black' + | 'red' + | 'green' + | 'yellow' + | 'blue' + | 'magenta' + | 'cyan' + | 'white'; }; export type InitialOptionsWithRootDir = InitialOptions & diff --git a/packages/jest-util/package.json b/packages/jest-util/package.json index 70a2d6c388a1..51c9065bb845 100644 --- a/packages/jest-util/package.json +++ b/packages/jest-util/package.json @@ -21,9 +21,9 @@ "dependencies": { "@jest/types": "workspace:*", "@types/node": "*", - "chalk": "^4.0.0", "ci-info": "^4.0.0", "graceful-fs": "^4.2.9", + "picocolors": "^1.1.1", "picomatch": "^4.0.0" }, "devDependencies": { diff --git a/packages/jest-util/src/preRunMessage.ts b/packages/jest-util/src/preRunMessage.ts index a1597797a651..4501df2adad9 100644 --- a/packages/jest-util/src/preRunMessage.ts +++ b/packages/jest-util/src/preRunMessage.ts @@ -6,13 +6,13 @@ */ import type {WriteStream} from 'tty'; -import chalk = require('chalk'); +import pc = require('picocolors'); import clearLine from './clearLine'; import isInteractive from './isInteractive'; export function print(stream: WriteStream): void { if (isInteractive) { - stream.write(chalk.bold.dim('Determining test suites to run...')); + stream.write(pc.bold(pc.dim('Determining test suites to run...'))); } } diff --git a/packages/jest-validate/package.json b/packages/jest-validate/package.json index a86ed0884911..4a7d8c3afe9d 100644 --- a/packages/jest-validate/package.json +++ b/packages/jest-validate/package.json @@ -21,9 +21,9 @@ "dependencies": { "@jest/types": "workspace:*", "camelcase": "^6.2.0", - "chalk": "^4.0.0", "jest-get-type": "workspace:*", "leven": "^3.1.0", + "picocolors": "^1.1.1", "pretty-format": "workspace:*" }, "devDependencies": { diff --git a/packages/jest-validate/src/__tests__/__fixtures__/jestConfig.ts b/packages/jest-validate/src/__tests__/__fixtures__/jestConfig.ts index 67582d930575..acf686390654 100644 --- a/packages/jest-validate/src/__tests__/__fixtures__/jestConfig.ts +++ b/packages/jest-validate/src/__tests__/__fixtures__/jestConfig.ts @@ -7,7 +7,7 @@ import {tmpdir} from 'os'; import * as path from 'path'; -import chalk = require('chalk'); +import pc = require('picocolors'); const NODE_MODULES = `${path.sep}node_modules${path.sep}`; const replacePathSepForRegex = (string: string) => { @@ -127,15 +127,15 @@ const format = (value: string) => export const deprecatedConfig = { preprocessorIgnorePatterns: (config: Record) => - ` Option ${chalk.bold( + ` Option ${pc.bold( 'preprocessorIgnorePatterns', - )} was replaced by ${chalk.bold( + )} was replaced by ${pc.bold( 'transformIgnorePatterns', )}, which support multiple preprocessors. Jest now treats your current configuration as: { - ${chalk.bold('"transformIgnorePatterns"')}: ${chalk.bold( + ${pc.bold('"transformIgnorePatterns"')}: ${pc.bold( `${format(config.preprocessorIgnorePatterns as string)}`, )} } @@ -143,13 +143,13 @@ export const deprecatedConfig = { Please update your configuration.`, scriptPreprocessor: (config: Record) => - ` Option ${chalk.bold('scriptPreprocessor')} was replaced by ${chalk.bold( + ` Option ${pc.bold('scriptPreprocessor')} was replaced by ${pc.bold( 'transform', )}, which support multiple preprocessors. Jest now treats your current configuration as: { - ${chalk.bold('"transform"')}: ${chalk.bold( + ${pc.bold('"transform"')}: ${pc.bold( `{".*": ${format(config.scriptPreprocessor as string)}}`, )} } diff --git a/packages/jest-validate/src/errors.ts b/packages/jest-validate/src/errors.ts index 2f14a0ff0fc7..f159a6785168 100644 --- a/packages/jest-validate/src/errors.ts +++ b/packages/jest-validate/src/errors.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); +import pc = require('picocolors'); import {getType} from 'jest-get-type'; import {getValues} from './condition'; import type {ValidationOptions} from './types'; @@ -21,12 +21,12 @@ export const errorMessage = ( const conditions = getValues(defaultValue); const validTypes: Array = [...new Set(conditions.map(getType))]; - const message = ` Option ${chalk.bold( + const message = ` Option ${pc.bold( `"${path && path.length > 0 ? `${path.join('.')}.` : ''}${option}"`, )} must be of type: - ${validTypes.map(e => chalk.bold.green(e)).join(' or ')} + ${validTypes.map(e => pc.bold(pc.green(e))).join(' or ')} but instead received: - ${chalk.bold.red(getType(received))} + ${pc.bold(pc.red(getType(received)))} Example: ${formatExamples(option, conditions)}`; @@ -40,7 +40,7 @@ ${formatExamples(option, conditions)}`; function formatExamples(option: string, examples: Array) { return examples.map( e => ` { - ${chalk.bold(`"${option}"`)}: ${chalk.bold(formatPrettyObject(e))} + ${pc.bold(`"${option}"`)}: ${pc.bold(formatPrettyObject(e))} }`, ).join(` diff --git a/packages/jest-validate/src/utils.ts b/packages/jest-validate/src/utils.ts index e5719da62c70..59b1db27ec22 100644 --- a/packages/jest-validate/src/utils.ts +++ b/packages/jest-validate/src/utils.ts @@ -5,11 +5,11 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); import leven from 'leven'; +import pc = require('picocolors'); import {format as prettyFormat} from 'pretty-format'; -const BULLET: string = chalk.bold('\u25CF'); +const BULLET: string = pc.bold('\u25CF'); export const DEPRECATION = `${BULLET} Deprecation Warning`; export const ERROR = `${BULLET} Validation Error`; export const WARNING = `${BULLET} Validation Warning`; @@ -34,7 +34,7 @@ export class ValidationError extends Error { super(); comment = comment ? `\n\n${comment}` : '\n'; this.name = ''; - this.message = chalk.red(`${chalk.bold(name)}:\n\n${message}${comment}`); + this.message = pc.red(`${pc.bold(name)}:\n\n${message}${comment}`); // eslint-disable-next-line @typescript-eslint/no-empty-function Error.captureStackTrace(this, () => {}); } @@ -46,7 +46,7 @@ export const logValidationWarning = ( comment?: string | null, ): void => { comment = comment ? `\n\n${comment}` : '\n'; - console.warn(chalk.yellow(`${chalk.bold(name)}:\n\n${message}${comment}`)); + console.warn(pc.yellow(`${pc.bold(name)}:\n\n${message}${comment}`)); }; export const createDidYouMeanMessage = ( @@ -58,5 +58,5 @@ export const createDidYouMeanMessage = ( return steps < 3; }); - return suggestion ? `Did you mean ${chalk.bold(format(suggestion))}?` : ''; + return suggestion ? `Did you mean ${pc.bold(format(suggestion))}?` : ''; }; diff --git a/packages/jest-validate/src/validateCLIOptions.ts b/packages/jest-validate/src/validateCLIOptions.ts index e26ea3adbd12..3a38ca366e14 100644 --- a/packages/jest-validate/src/validateCLIOptions.ts +++ b/packages/jest-validate/src/validateCLIOptions.ts @@ -6,7 +6,7 @@ */ import camelcase = require('camelcase'); -import chalk = require('chalk'); +import pc = require('picocolors'); import type {Options} from 'yargs'; import type {Config} from '@jest/types'; import type { @@ -21,8 +21,8 @@ import { logValidationWarning, } from './utils'; -const BULLET: string = chalk.bold('\u25CF'); -export const DOCUMENTATION_NOTE = ` ${chalk.bold('CLI Options Documentation:')} +const BULLET: string = pc.bold('\u25CF'); +export const DOCUMENTATION_NOTE = ` ${pc.bold('CLI Options Documentation:')} https://jestjs.io/docs/cli `; @@ -33,7 +33,7 @@ const createCLIValidationError = ( let title = `${BULLET} Unrecognized CLI Parameter`; let message; const comment = - ` ${chalk.bold('CLI Options Documentation')}:\n` + + ` ${pc.bold('CLI Options Documentation')}:\n` + ' https://jestjs.io/docs/cli\n'; if (unrecognizedOptions.length === 1) { @@ -42,14 +42,14 @@ const createCLIValidationError = ( unrecognized.length > 1 ? createDidYouMeanMessage(unrecognized, [...allowedOptions]) : ''; - message = ` Unrecognized option ${chalk.bold(format(unrecognized))}.${ + message = ` Unrecognized option ${pc.bold(format(unrecognized))}.${ didYouMeanMessage ? ` ${didYouMeanMessage}` : '' }`; } else { title += 's'; message = ' Following options were not recognized:\n' + - ` ${chalk.bold(format(unrecognizedOptions))}`; + ` ${pc.bold(format(unrecognizedOptions))}`; } return new ValidationError(title, message, comment); diff --git a/packages/jest-validate/src/warnings.ts b/packages/jest-validate/src/warnings.ts index 6dee9f6b1814..a82896361c73 100644 --- a/packages/jest-validate/src/warnings.ts +++ b/packages/jest-validate/src/warnings.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); +import pc = require('picocolors'); import type {ValidationOptions} from './types'; import { WARNING, @@ -25,9 +25,9 @@ export const unknownOptionWarning = ( option, Object.keys(exampleConfig), ); - const message = ` Unknown option ${chalk.bold( + const message = ` Unknown option ${pc.bold( `"${path && path.length > 0 ? `${path.join('.')}.` : ''}${option}"`, - )} with value ${chalk.bold(format(config[option]))} was found.${ + )} with value ${pc.bold(format(config[option]))} was found.${ didYouMean && ` ${didYouMean}` }\n This is probably a typing mistake. Fixing it will remove this message.`; diff --git a/packages/jest-watcher/package.json b/packages/jest-watcher/package.json index 1b6e2c2dfd3b..854bec0d3ffe 100644 --- a/packages/jest-watcher/package.json +++ b/packages/jest-watcher/package.json @@ -18,9 +18,9 @@ "@jest/types": "workspace:*", "@types/node": "*", "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", "emittery": "^0.13.1", "jest-util": "workspace:*", + "picocolors": "^1.1.1", "string-length": "^4.0.1" }, "repository": { diff --git a/packages/jest-watcher/src/PatternPrompt.ts b/packages/jest-watcher/src/PatternPrompt.ts index c05cd7141486..cea03bced27c 100644 --- a/packages/jest-watcher/src/PatternPrompt.ts +++ b/packages/jest-watcher/src/PatternPrompt.ts @@ -6,7 +6,7 @@ */ import ansiEscapes = require('ansi-escapes'); -import chalk = require('chalk'); +import pc = require('picocolors'); import {specialChars} from 'jest-util'; import type Prompt from './lib/Prompt'; import type {ScrollOptions} from './types'; @@ -14,10 +14,10 @@ import type {ScrollOptions} from './types'; const {CLEAR} = specialChars; const usage = (entity: string) => - `\n${chalk.bold('Pattern Mode Usage')}\n` + - ` ${chalk.dim('\u203A Press')} Esc ${chalk.dim('to exit pattern mode.')}\n` + - ` ${chalk.dim('\u203A Press')} Enter ` + - `${chalk.dim(`to filter by a ${entity} regex pattern.`)}\n` + + `\n${pc.bold('Pattern Mode Usage')}\n` + + ` ${pc.dim('\u203A Press')} Esc ${pc.dim('to exit pattern mode.')}\n` + + ` ${pc.dim('\u203A Press')} Enter ` + + `${pc.dim(`to filter by a ${entity} regex pattern.`)}\n` + '\n'; const usageRows = usage('').split('\n').length; diff --git a/packages/jest-watcher/src/lib/colorize.ts b/packages/jest-watcher/src/lib/colorize.ts index ef2b27aa3afc..47197517e2bf 100644 --- a/packages/jest-watcher/src/lib/colorize.ts +++ b/packages/jest-watcher/src/lib/colorize.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); +import pc = require('picocolors'); export default function colorize( str: string, @@ -13,8 +13,8 @@ export default function colorize( end: number, ): string { return ( - chalk.dim(str.slice(0, start)) + - chalk.reset(str.slice(start, end)) + - chalk.dim(str.slice(end)) + pc.dim(str.slice(0, start)) + + pc.reset(str.slice(start, end)) + + pc.dim(str.slice(end)) ); } diff --git a/packages/jest-watcher/src/lib/formatTestNameByPattern.ts b/packages/jest-watcher/src/lib/formatTestNameByPattern.ts index ee2e269fbfd7..b8bbc6179afa 100644 --- a/packages/jest-watcher/src/lib/formatTestNameByPattern.ts +++ b/packages/jest-watcher/src/lib/formatTestNameByPattern.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import chalk = require('chalk'); +import pc = require('picocolors'); import colorize from './colorize'; const DOTS = '...'; @@ -23,13 +23,13 @@ export default function formatTestNameByPattern( try { regexp = new RegExp(pattern, 'i'); } catch { - return chalk.dim(inlineTestName); + return pc.dim(inlineTestName); } const match = inlineTestName.match(regexp); if (!match) { - return chalk.dim(inlineTestName); + return pc.dim(inlineTestName); } const startPatternIndex = Math.max(match.index ?? 0, 0); @@ -57,5 +57,5 @@ export default function formatTestNameByPattern( } } - return `${chalk.dim(slicedTestName)}${chalk.reset(DOTS)}`; + return `${pc.dim(slicedTestName)}${pc.reset(DOTS)}`; } diff --git a/packages/jest-watcher/src/lib/patternModeHelpers.ts b/packages/jest-watcher/src/lib/patternModeHelpers.ts index 20f556cba0e5..aab4195f8677 100644 --- a/packages/jest-watcher/src/lib/patternModeHelpers.ts +++ b/packages/jest-watcher/src/lib/patternModeHelpers.ts @@ -6,14 +6,14 @@ */ import ansiEscapes = require('ansi-escapes'); -import chalk = require('chalk'); +import pc = require('picocolors'); import stringLength = require('string-length'); export function printPatternCaret( pattern: string, pipe: NodeJS.WritableStream, ): void { - const inputText = `${chalk.dim(' pattern \u203A')} ${pattern}`; + const inputText = `${pc.dim(' pattern \u203A')} ${pattern}`; pipe.write(ansiEscapes.eraseDown); pipe.write(inputText); @@ -25,7 +25,7 @@ export function printRestoredPatternCaret( currentUsageRows: number, pipe: NodeJS.WritableStream, ): void { - const inputText = `${chalk.dim(' pattern \u203A')} ${pattern}`; + const inputText = `${pc.dim(' pattern \u203A')} ${pattern}`; pipe.write( ansiEscapes.cursorTo(stringLength(inputText), currentUsageRows - 1), diff --git a/scripts/build.mjs b/scripts/build.mjs index 0f919d1a869c..aa677327f178 100644 --- a/scripts/build.mjs +++ b/scripts/build.mjs @@ -9,9 +9,9 @@ import {strict as assert} from 'assert'; import {createRequire} from 'module'; import * as path from 'path'; import util from 'util'; -import chalk from 'chalk'; import dedent from 'dedent'; import fs from 'graceful-fs'; +import pc from 'picocolors'; import webpack from 'webpack'; import { ERROR, @@ -24,7 +24,7 @@ import { const require = createRequire(import.meta.url); async function buildNodePackages() { - process.stdout.write(chalk.inverse(' Bundling packages \n')); + process.stdout.write(pc.inverse(' Bundling packages \n')); const buildConfigs = createBuildConfigs(); diff --git a/scripts/buildTs.mjs b/scripts/buildTs.mjs index bdd931651815..7e439a15bfe1 100644 --- a/scripts/buildTs.mjs +++ b/scripts/buildTs.mjs @@ -8,11 +8,11 @@ import {strict as assert} from 'assert'; import * as os from 'os'; import * as path from 'path'; -import chalk from 'chalk'; import execa from 'execa'; import {glob} from 'glob'; import fs from 'graceful-fs'; import pLimit from 'p-limit'; +import pc from 'picocolors'; import stripJsonComments from 'strip-json-comments'; import {getPackagesWithTsConfig} from './buildUtils.mjs'; @@ -102,7 +102,7 @@ for (const {packageDir, pkg} of packagesWithTs) { if (hasJestTestUtils) { throw new Error( - chalk.red( + pc.red( `Package '${pkg.name}' declares '@jest/test-utils' as dependency, but it must be declared as dev dependency`, ), ); @@ -129,7 +129,7 @@ for (const {packageDir, pkg} of packagesWithTs) { if (hasJestTestUtils && testUtilsReferences.length === 0) { throw new Error( - chalk.red( + pc.red( `Package '${ pkg.name }' declares '@jest/test-utils' as dev dependency, but it is not referenced in:\n\n${tsConfigPaths.join( @@ -141,7 +141,7 @@ for (const {packageDir, pkg} of packagesWithTs) { if (!hasJestTestUtils && testUtilsReferences.length > 0) { throw new Error( - chalk.red( + pc.red( `Package '${ pkg.name }' does not declare '@jest/test-utils' as dev dependency, but it is referenced in:\n\n${testUtilsReferences.join( @@ -159,21 +159,21 @@ const args = [ ...process.argv.slice(2), ]; -console.log(chalk.inverse(' Building TypeScript definition files ')); +console.log(pc.inverse(' Building TypeScript definition files ')); try { await execa('yarn', args, {stdio: 'inherit'}); console.log( - chalk.inverse.green(' Successfully built TypeScript definition files '), + pc.inverse(pc.green(' Successfully built TypeScript definition files ')), ); } catch (error) { console.error( - chalk.inverse.red(' Unable to build TypeScript definition files '), + pc.inverse(pc.red(' Unable to build TypeScript definition files ')), ); throw error; } -console.log(chalk.inverse(' Validating TypeScript definition files ')); +console.log(pc.inverse(' Validating TypeScript definition files ')); // we want to limit the number of processes we spawn const cpus = Math.max( @@ -219,8 +219,8 @@ try { .filter(([, content]) => content.length > 0) .filter(hit => hit.length > 0) .map(([file, references]) => - chalk.red( - `${chalk.bold( + pc.red( + `${pc.bold( file, )} has the following non-node type references:\n\n${references}\n`, ), @@ -251,12 +251,12 @@ try { ); } catch (error) { console.error( - chalk.inverse.red(' Unable to validate TypeScript definition files '), + pc.inverse(pc.red(' Unable to validate TypeScript definition files ')), ); throw error; } console.log( - chalk.inverse.green(' Successfully validated TypeScript definition files '), + pc.inverse(pc.green(' Successfully validated TypeScript definition files ')), ); diff --git a/scripts/buildUtils.mjs b/scripts/buildUtils.mjs index a92a16df950b..6efa8c4f2c77 100644 --- a/scripts/buildUtils.mjs +++ b/scripts/buildUtils.mjs @@ -9,8 +9,8 @@ import {strict as assert} from 'assert'; import {createRequire} from 'module'; import * as path from 'path'; import {fileURLToPath} from 'url'; -import chalk from 'chalk'; import fs from 'graceful-fs'; +import pc from 'picocolors'; import {sync as readPkg} from 'read-pkg'; import webpack from 'webpack'; import nodeExternals from 'webpack-node-externals'; @@ -22,8 +22,8 @@ export const PACKAGES_DIR = path.resolve( ); const require = createRequire(import.meta.url); -export const OK = chalk.reset.inverse.bold.green(' DONE '); -export const ERROR = chalk.reset.inverse.bold.red(' BOOM '); +export const OK = pc.reset(pc.inverse(pc.bold(pc.green(' DONE ')))); +export const ERROR = pc.reset(pc.inverse(pc.bold(pc.red(' BOOM ')))); export const typeOnlyPackages = new Set([ 'babel-preset-jest', diff --git a/scripts/bundleTs.mjs b/scripts/bundleTs.mjs index f506d4a08507..0ca21c222bd0 100644 --- a/scripts/bundleTs.mjs +++ b/scripts/bundleTs.mjs @@ -13,10 +13,10 @@ import { Extractor, ExtractorConfig, } from '@microsoft/api-extractor'; -import chalk from 'chalk'; import {ESLint} from 'eslint'; import {glob} from 'glob'; import fs from 'graceful-fs'; +import pc from 'picocolors'; import pkgDir from 'pkg-dir'; import {rimraf} from 'rimraf'; import {copyrightSnippet, getPackagesWithTsConfig} from './buildUtils.mjs'; @@ -32,7 +32,7 @@ const packagesToBundle = getPackagesWithTsConfig().filter( p => !excludedPackages.has(p.pkg.name), ); -console.log(chalk.inverse(' Extracting TypeScript definition files ')); +console.log(pc.inverse(' Extracting TypeScript definition files ')); const sharedExtractorConfig = { $schema: @@ -118,7 +118,6 @@ let compilerState; await Promise.all( packagesToBundle.map(async ({packageDir, pkg}) => { const configFile = path.resolve(packageDir, 'api-extractor.json'); - await fs.promises.writeFile( configFile, JSON.stringify( @@ -151,7 +150,7 @@ await Promise.all( if (!extractorResult.succeeded || extractorResult.warningCount > 0) { console.error( - chalk.inverse.red(' Unable to extract TypeScript definition files '), + pc.inverse(pc.red(' Unable to extract TypeScript definition files ')), ); throw new Error( `API Extractor completed with ${extractorResult.errorCount} errors and ${extractorResult.warningCount} warnings`, @@ -232,5 +231,5 @@ await Promise.all( ); console.log( - chalk.inverse.green(' Successfully extracted TypeScript definition files '), + pc.inverse(pc.green(' Successfully extracted TypeScript definition files ')), ); diff --git a/scripts/lintTs.mjs b/scripts/lintTs.mjs index 01c4d353a74d..a51312d7dd74 100644 --- a/scripts/lintTs.mjs +++ b/scripts/lintTs.mjs @@ -10,9 +10,9 @@ import * as os from 'os'; import * as path from 'path'; import * as url from 'url'; -import chalk from 'chalk'; import {ESLint} from 'eslint'; import pLimit from 'p-limit'; +import pc from 'picocolors'; import {getPackagesWithTsConfig} from './buildUtils.mjs'; // we want to limit the number of processes we spawn @@ -184,7 +184,7 @@ try { ); } catch (error) { console.error( - chalk.inverse.red(' Unable to lint using TypeScript info files '), + pc.inverse(pc.red(' Unable to lint using TypeScript info files ')), ); throw error; @@ -198,12 +198,12 @@ if (allLintResults.length > 0) { console.error(resultText); console.error( - chalk.inverse.red(' Unable to lint using TypeScript info files '), + pc.inverse(pc.red(' Unable to lint using TypeScript info files ')), ); process.exitCode = 1; } else { console.log( - chalk.inverse.green(' Successfully linted using TypeScript info files '), + pc.inverse(pc.green(' Successfully linted using TypeScript info files ')), ); } diff --git a/scripts/verifyOldTs.mjs b/scripts/verifyOldTs.mjs index 574e9fef9c2a..6e0d7d866901 100644 --- a/scripts/verifyOldTs.mjs +++ b/scripts/verifyOldTs.mjs @@ -8,9 +8,9 @@ import {createRequire} from 'module'; import * as path from 'path'; import {fileURLToPath} from 'url'; -import chalk from 'chalk'; import execa from 'execa'; import fs from 'graceful-fs'; +import pc from 'picocolors'; import stripJsonComments from 'strip-json-comments'; /* eslint-disable import/order */ import tempy from 'tempy'; @@ -73,8 +73,8 @@ function smoketest() { execa.sync('yarn', ['tsc', '--project', '.'], {cwd, stdio: 'inherit'}); console.log( - chalk.inverse.green( - ` Successfully compiled Jest with TypeScript ${tsVersion} `, + pc.inverse( + pc.green(` Successfully compiled Jest with TypeScript ${tsVersion} `), ), ); } finally { @@ -82,6 +82,6 @@ function smoketest() { } } -console.log(chalk.inverse(` Running smoketest using TypeScript@${tsVersion} `)); +console.log(pc.inverse(` Running smoketest using TypeScript@${tsVersion} `)); smoketest(); -console.log(chalk.inverse.green(' Successfully ran smoketest ')); +console.log(pc.inverse(pc.green(' Successfully ran smoketest '))); diff --git a/scripts/verifyPnP.mjs b/scripts/verifyPnP.mjs index 31ace2088a11..647ef0312688 100644 --- a/scripts/verifyPnP.mjs +++ b/scripts/verifyPnP.mjs @@ -7,11 +7,11 @@ import * as path from 'path'; import {fileURLToPath} from 'url'; -import chalk from 'chalk'; import dedent from 'dedent'; import execa from 'execa'; import fs from 'graceful-fs'; import yaml from 'js-yaml'; +import pc from 'picocolors'; import tempy from 'tempy'; const rootDirectory = path.resolve( @@ -75,7 +75,7 @@ try { }); execa.sync('yarn', ['jest'], {cwd, stdio: 'inherit'}); - console.log(chalk.inverse.green(' Successfully ran Jest with PnP linker ')); + console.log(pc.inverse(pc.green(' Successfully ran Jest with PnP linker '))); } finally { fs.rmSync(cwd, {force: true, recursive: true}); } diff --git a/scripts/watch.mjs b/scripts/watch.mjs index 15900562c028..32506989495d 100644 --- a/scripts/watch.mjs +++ b/scripts/watch.mjs @@ -9,7 +9,7 @@ * Watch files for changes and rebuild (copy from 'src/' to `build/`) if changed */ -import chalk from 'chalk'; +import pc from 'picocolors'; import webpack from 'webpack'; import {createWebpackConfigs} from './buildUtils.mjs'; @@ -17,13 +17,13 @@ const compiler = webpack(createWebpackConfigs()); let hasBuilt = false; -console.log(chalk.inverse(' Bundling packages ')); +console.log(pc.inverse(' Bundling packages ')); compiler.watch({}, (error, stats) => { if (!hasBuilt) { hasBuilt = true; - console.log(chalk.red('->'), chalk.cyan('Watching for changes…')); + console.log(pc.red('->'), pc.cyan('Watching for changes…')); } if (error) { @@ -41,7 +41,7 @@ compiler.watch({}, (error, stats) => { console.warn('warning', warning.message); } } else { - console.log(chalk.red('->'), chalk.green('Rebuilt packages')); + console.log(pc.red('->'), pc.green('Rebuilt packages')); } } }); diff --git a/yarn.lock b/yarn.lock index 236b33c54c21..b3de945bcb96 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3582,9 +3582,9 @@ __metadata: "@jest/test-utils": "workspace:*" "@jest/types": "workspace:*" "@types/node": "*" - chalk: ^4.0.0 jest-message-util: "workspace:*" jest-util: "workspace:*" + picocolors: ^1.1.1 slash: ^3.0.0 languageName: unknown linkType: soft @@ -3605,7 +3605,6 @@ __metadata: "@types/micromatch": ^4.0.7 "@types/node": "*" ansi-escapes: ^4.2.1 - chalk: ^4.0.0 ci-info: ^4.0.0 exit-x: ^0.2.2 graceful-fs: ^4.2.9 @@ -3623,6 +3622,7 @@ __metadata: jest-validate: "workspace:*" jest-watcher: "workspace:*" micromatch: ^4.0.8 + picocolors: ^1.1.1 pretty-format: "workspace:*" slash: ^3.0.0 strip-ansi: ^6.0.0 @@ -3760,7 +3760,6 @@ __metadata: babel-jest: "workspace:*" babel-loader: ^9.0.0 camelcase: ^6.2.0 - chalk: ^4.0.0 dedent: ^1.0.0 eslint: ^8.8.0 eslint-config-prettier: ^10.0.0 @@ -3797,6 +3796,7 @@ __metadata: netlify-plugin-cache: ^1.0.3 node-notifier: ^10.0.0 p-limit: ^3.1.0 + picocolors: ^1.1.1 pkg-dir: ^5.0.0 prettier: ^3.0.3 promise: ^8.0.2 @@ -3846,7 +3846,6 @@ __metadata: "@types/istanbul-reports": ^3.0.0 "@types/node": "*" "@types/node-notifier": ^8.0.0 - chalk: ^4.0.0 collect-v8-coverage: ^1.0.0 exit-x: ^0.2.2 glob: ^10.3.10 @@ -3862,6 +3861,7 @@ __metadata: jest-worker: "workspace:*" mock-fs: ^5.1.2 node-notifier: ^10.0.0 + picocolors: ^1.1.1 slash: ^3.0.0 string-length: ^4.0.1 strip-ansi: ^6.0.0 @@ -3898,9 +3898,9 @@ __metadata: "@jest/types": "workspace:*" "@types/graceful-fs": ^4.1.3 "@types/natural-compare": ^1.4.0 - chalk: ^4.0.0 graceful-fs: ^4.2.9 natural-compare: ^1.4.0 + picocolors: ^1.1.1 languageName: unknown linkType: soft @@ -3994,7 +3994,6 @@ __metadata: "@types/micromatch": ^4.0.7 "@types/write-file-atomic": ^4.0.0 babel-plugin-istanbul: ^7.0.0 - chalk: ^4.0.0 convert-source-map: ^2.0.0 dedent: ^1.0.0 fast-json-stable-stringify: ^2.1.0 @@ -4003,6 +4002,7 @@ __metadata: jest-regex-util: "workspace:*" jest-util: "workspace:*" micromatch: ^4.0.8 + picocolors: ^1.1.1 pirates: ^4.0.4 slash: ^3.0.0 write-file-atomic: ^5.0.0 @@ -4046,7 +4046,7 @@ __metadata: "@types/istanbul-reports": ^3.0.0 "@types/node": "*" "@types/yargs": ^17.0.8 - chalk: ^4.0.0 + picocolors: ^1.1.1 languageName: unknown linkType: soft @@ -7384,8 +7384,8 @@ __metadata: "@types/graceful-fs": ^4.1.3 babel-plugin-istanbul: ^7.0.0 babel-preset-jest: "workspace:*" - chalk: ^4.0.0 graceful-fs: ^4.2.9 + picocolors: ^1.1.1 slash: ^3.0.0 peerDependencies: "@babel/core": ^7.11.0 @@ -8814,11 +8814,11 @@ __metadata: "@jest/types": "workspace:*" "@types/graceful-fs": ^4.1.3 "@types/prompts": ^2.0.1 - chalk: ^4.0.0 exit-x: ^0.2.2 graceful-fs: ^4.2.9 jest-config: "workspace:*" jest-util: "workspace:*" + picocolors: ^1.1.1 prompts: ^2.0.1 bin: create-jest: ./bin/create-jest.js @@ -10900,7 +10900,6 @@ __metadata: "@fast-check/jest": ^2.0.0 "@jest/expect-utils": "workspace:*" "@jest/test-utils": "workspace:*" - chalk: ^4.0.0 immutable: ^5.0.0 jest-get-type: "workspace:*" jest-matcher-utils: "workspace:*" @@ -13492,7 +13491,6 @@ __metadata: "@types/graceful-fs": ^4.1.3 "@types/node": "*" "@types/stack-utils": ^2.0.0 - chalk: ^4.0.0 co: ^4.6.0 dedent: ^1.0.0 execa: ^5.0.0 @@ -13505,6 +13503,7 @@ __metadata: jest-snapshot: "workspace:*" jest-util: "workspace:*" p-limit: ^3.1.0 + picocolors: ^1.1.1 pretty-format: "workspace:*" pure-rand: ^6.0.0 slash: ^3.0.0 @@ -13521,12 +13520,12 @@ __metadata: "@jest/test-result": "workspace:*" "@jest/types": "workspace:*" "@types/yargs": ^17.0.8 - chalk: ^4.0.0 exit-x: ^0.2.2 import-local: ^3.0.2 jest-config: "workspace:*" jest-util: "workspace:*" jest-validate: "workspace:*" + picocolors: ^1.1.1 yargs: ^17.3.1 peerDependencies: node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 @@ -13550,7 +13549,6 @@ __metadata: "@types/micromatch": ^4.0.7 "@types/parse-json": ^4.0.0 babel-jest: "workspace:*" - chalk: ^4.0.0 ci-info: ^4.0.0 deepmerge: ^4.2.2 esbuild: ^0.24.0 @@ -13568,6 +13566,7 @@ __metadata: jest-validate: "workspace:*" micromatch: ^4.0.8 parse-json: ^5.2.0 + picocolors: ^1.1.1 pretty-format: "workspace:*" semver: ^7.5.3 slash: ^3.0.0 @@ -13593,9 +13592,9 @@ __metadata: resolution: "jest-diff@workspace:packages/jest-diff" dependencies: "@jest/test-utils": "workspace:*" - chalk: ^4.0.0 diff-sequences: "workspace:*" jest-get-type: "workspace:*" + picocolors: ^1.1.1 pretty-format: "workspace:*" strip-ansi: ^6.0.0 languageName: unknown @@ -13615,9 +13614,9 @@ __metadata: resolution: "jest-each@workspace:packages/jest-each" dependencies: "@jest/types": "workspace:*" - chalk: ^4.0.0 jest-get-type: "workspace:*" jest-util: "workspace:*" + picocolors: ^1.1.1 pretty-format: "workspace:*" languageName: unknown linkType: soft @@ -13703,7 +13702,6 @@ __metadata: "@jest/types": "workspace:*" "@types/co": ^4.6.2 "@types/node": "*" - chalk: ^4.0.0 co: ^4.6.0 is-generator-fn: ^2.0.0 jest-each: "workspace:*" @@ -13713,6 +13711,7 @@ __metadata: jest-snapshot: "workspace:*" jest-util: "workspace:*" p-limit: ^3.1.0 + picocolors: ^1.1.1 pretty-format: "workspace:*" languageName: unknown linkType: soft @@ -13745,9 +13744,9 @@ __metadata: dependencies: "@jest/test-utils": "workspace:*" "@types/node": "*" - chalk: ^4.0.0 jest-diff: "workspace:*" jest-get-type: "workspace:*" + picocolors: ^1.1.1 pretty-format: "workspace:*" languageName: unknown linkType: soft @@ -13779,9 +13778,9 @@ __metadata: "@types/graceful-fs": ^4.1.3 "@types/micromatch": ^4.0.7 "@types/stack-utils": ^2.0.0 - chalk: ^4.0.0 graceful-fs: ^4.2.9 micromatch: ^4.0.8 + picocolors: ^1.1.1 pretty-format: "workspace:*" slash: ^3.0.0 stack-utils: ^2.0.3 @@ -13843,12 +13842,12 @@ __metadata: "@jest/transform": "workspace:*" "@jest/types": "workspace:*" "@types/yargs": ^17.0.8 - chalk: ^4.0.0 execa: ^5.0.0 jest-config: "workspace:*" jest-runtime: "workspace:*" jest-util: "workspace:*" jest-validate: "workspace:*" + picocolors: ^1.1.1 repl: ^0.1.3 yargs: ^17.3.1 bin: @@ -13878,12 +13877,12 @@ __metadata: "@types/graceful-fs": ^4.1.3 "@types/pnpapi": ^0.0.5 "@types/resolve": ^1.20.2 - chalk: ^4.0.0 graceful-fs: ^4.2.9 jest-haste-map: "workspace:*" jest-pnp-resolver: ^1.2.2 jest-util: "workspace:*" jest-validate: "workspace:*" + picocolors: ^1.1.1 resolve: ^1.20.0 resolve.exports: ^2.0.0 slash: ^3.0.0 @@ -13903,7 +13902,6 @@ __metadata: "@types/graceful-fs": ^4.1.3 "@types/node": "*" "@types/source-map-support": ^0.5.0 - chalk: ^4.0.0 emittery: ^0.13.1 graceful-fs: ^4.2.9 jest-docblock: "workspace:*" @@ -13918,6 +13916,7 @@ __metadata: jest-watcher: "workspace:*" jest-worker: "workspace:*" p-limit: ^3.1.0 + picocolors: ^1.1.1 source-map-support: 0.5.13 languageName: unknown linkType: soft @@ -13936,7 +13935,6 @@ __metadata: "@jest/types": "workspace:*" "@types/graceful-fs": ^4.1.3 "@types/node": "*" - chalk: ^4.0.0 cjs-module-lexer: ^1.0.0 collect-v8-coverage: ^1.0.0 glob: ^10.3.10 @@ -13949,6 +13947,7 @@ __metadata: jest-resolve: "workspace:*" jest-snapshot: "workspace:*" jest-util: "workspace:*" + picocolors: ^1.1.1 slash: ^3.0.0 strip-bom: ^4.0.0 languageName: unknown @@ -14048,9 +14047,9 @@ __metadata: "@types/graceful-fs": ^4.1.3 "@types/node": "*" "@types/picomatch": ^3.0.0 - chalk: ^4.0.0 ci-info: ^4.0.0 graceful-fs: ^4.2.9 + picocolors: ^1.1.1 picomatch: ^4.0.0 languageName: unknown linkType: soft @@ -14076,9 +14075,9 @@ __metadata: "@jest/types": "workspace:*" "@types/yargs": ^17.0.8 camelcase: ^6.2.0 - chalk: ^4.0.0 jest-get-type: "workspace:*" leven: ^3.1.0 + picocolors: ^1.1.1 pretty-format: "workspace:*" languageName: unknown linkType: soft @@ -14124,9 +14123,9 @@ __metadata: "@jest/types": "workspace:*" "@types/node": "*" ansi-escapes: ^4.2.1 - chalk: ^4.0.0 emittery: ^0.13.1 jest-util: "workspace:*" + picocolors: ^1.1.1 string-length: ^4.0.1 languageName: unknown linkType: soft