From 81aad430fb797779981dffa2ed4f9656f16d75e5 Mon Sep 17 00:00:00 2001 From: Gilad Shoham Date: Tue, 16 Jul 2024 18:02:29 +0300 Subject: [PATCH] upgrade(jest) - upgrade jest to v29, replace jest aspect with jest tester component, deprecate jest aspect (#9015) --- .../config/jest.config.js | 17 +++++ .../config/tsconfig.json | 12 +++ .../custom-jest-resolve-env.aspect.ts | 5 -- .../custom-jest-resolve-env.bit-env.ts | 57 ++++++++++++++ .../custom-jest-resolve-env.main.runtime.ts | 40 ---------- .../custom-jest-resolve-env/index.ts | 7 +- .../jest/jest.config.js | 10 --- .../typescript/tsconfig.json | 18 ----- .../webpack/webpack-transformers.ts | 45 ----------- .../config/jest.config.js | 16 ++++ .../config/tsconfig.json | 12 +++ .../invalid-jest-config-env/index.ts | 4 + .../invalid-jest-config.bit-env.ts | 55 ++++++++++++++ .../config/jest.config.js | 17 +++++ .../config/tsconfig.json | 12 +++ .../multi-jest-testers-env/index.ts | 7 +- .../jest/jest.config.js | 10 --- .../multi-jest-tester-env.bit-env.ts | 74 +++++++++++++++++++ .../multi-jest-testers-env.aspect.ts | 5 -- .../multi-jest-testers-env.main.runtime.ts | 50 ------------- e2e/harmony/jest.e2e.ts | 37 +++++----- e2e/harmony/multiple-testers.e2e.ts | 15 +++- e2e/harmony/tag-harmony.e2e.ts | 6 +- scopes/defender/jest/jest.main.runtime.ts | 7 ++ .../multi-tester/multi-tester.main.runtime.ts | 15 +++- .../cli-reference/cli-reference.docs.mdx | 1 - scopes/harmony/node/node.env.ts | 2 +- scopes/harmony/worker/harmony-worker.ts | 4 +- scopes/react/react/jest/jest.base.config.js | 31 -------- scopes/react/react/jest/jest.cjs.config.js | 20 +++-- scopes/react/react/jest/jest.config.js | 7 -- scopes/react/react/jest/jest.esm.config.js | 19 +++-- scopes/react/react/jest/setupTests.js | 7 -- .../transformers/base-transformer-plugins.js | 13 ---- .../transformers/base-transformer-presets.js | 11 --- .../transformers/base-transformer-process.js | 20 ----- .../jest/transformers/cjs-transformer.js | 25 ------- .../react/jest/transformers/css-transform.js | 12 --- .../jest/transformers/esm-transformer.js | 27 ------- .../react/jest/transformers/file-transform.js | 38 ---------- scopes/react/react/react.env.ts | 54 +++++++++++--- scopes/react/react/react.main.runtime.ts | 18 +++-- workspace.jsonc | 21 +++--- 43 files changed, 428 insertions(+), 455 deletions(-) create mode 100644 e2e/fixtures/extensions/custom-jest-resolve-env/config/jest.config.js create mode 100644 e2e/fixtures/extensions/custom-jest-resolve-env/config/tsconfig.json delete mode 100644 e2e/fixtures/extensions/custom-jest-resolve-env/custom-jest-resolve-env.aspect.ts create mode 100644 e2e/fixtures/extensions/custom-jest-resolve-env/custom-jest-resolve-env.bit-env.ts delete mode 100644 e2e/fixtures/extensions/custom-jest-resolve-env/custom-jest-resolve-env.main.runtime.ts delete mode 100644 e2e/fixtures/extensions/custom-jest-resolve-env/jest/jest.config.js delete mode 100644 e2e/fixtures/extensions/custom-jest-resolve-env/typescript/tsconfig.json delete mode 100644 e2e/fixtures/extensions/custom-jest-resolve-env/webpack/webpack-transformers.ts create mode 100644 e2e/fixtures/extensions/invalid-jest-config-env/config/jest.config.js create mode 100644 e2e/fixtures/extensions/invalid-jest-config-env/config/tsconfig.json create mode 100644 e2e/fixtures/extensions/invalid-jest-config-env/index.ts create mode 100644 e2e/fixtures/extensions/invalid-jest-config-env/invalid-jest-config.bit-env.ts create mode 100644 e2e/fixtures/extensions/multi-jest-testers-env/config/jest.config.js create mode 100644 e2e/fixtures/extensions/multi-jest-testers-env/config/tsconfig.json delete mode 100644 e2e/fixtures/extensions/multi-jest-testers-env/jest/jest.config.js create mode 100644 e2e/fixtures/extensions/multi-jest-testers-env/multi-jest-tester-env.bit-env.ts delete mode 100644 e2e/fixtures/extensions/multi-jest-testers-env/multi-jest-testers-env.aspect.ts delete mode 100644 e2e/fixtures/extensions/multi-jest-testers-env/multi-jest-testers-env.main.runtime.ts delete mode 100644 scopes/react/react/jest/jest.base.config.js delete mode 100644 scopes/react/react/jest/jest.config.js delete mode 100644 scopes/react/react/jest/setupTests.js delete mode 100644 scopes/react/react/jest/transformers/base-transformer-plugins.js delete mode 100644 scopes/react/react/jest/transformers/base-transformer-presets.js delete mode 100644 scopes/react/react/jest/transformers/base-transformer-process.js delete mode 100644 scopes/react/react/jest/transformers/cjs-transformer.js delete mode 100644 scopes/react/react/jest/transformers/css-transform.js delete mode 100644 scopes/react/react/jest/transformers/esm-transformer.js delete mode 100644 scopes/react/react/jest/transformers/file-transform.js diff --git a/e2e/fixtures/extensions/custom-jest-resolve-env/config/jest.config.js b/e2e/fixtures/extensions/custom-jest-resolve-env/config/jest.config.js new file mode 100644 index 000000000000..e1d0565f1c45 --- /dev/null +++ b/e2e/fixtures/extensions/custom-jest-resolve-env/config/jest.config.js @@ -0,0 +1,17 @@ +// Override the Jest config to ignore transpiling from specific folders +// See the base Jest config: https://bit.cloud/teambit/react/react/~code/jest/jest.config.js + +const { jestConfig } = require('@teambit/react.react-env'); +// const { esmConfig } = require('@teambit/react.jest.react-jest'); +// uncomment the line below and install the package if you want to use this function +// const { +// generateNodeModulesPattern, +// } = require('@teambit/dependencies.modules.packages-excluder'); +// const packagesToExclude = ['@my-org', 'my-package-name']; +module.exports = { + ...jestConfig, + // transformIgnorePatterns: [ + // '^.+\.module\.(css|sass|scss)$', + // generateNodeModulesPattern({ packages: packagesToExclude }), + // ], +}; diff --git a/e2e/fixtures/extensions/custom-jest-resolve-env/config/tsconfig.json b/e2e/fixtures/extensions/custom-jest-resolve-env/config/tsconfig.json new file mode 100644 index 000000000000..94befdf2c7c7 --- /dev/null +++ b/e2e/fixtures/extensions/custom-jest-resolve-env/config/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "@teambit/react.react-env/config/tsconfig.json", + "exclude": [ + "artifacts", + "public", + "dist", + "node_modules", + "package.json", + "**/*.cjs" + ], + "include": ["**/*", "**/*.json"] +} diff --git a/e2e/fixtures/extensions/custom-jest-resolve-env/custom-jest-resolve-env.aspect.ts b/e2e/fixtures/extensions/custom-jest-resolve-env/custom-jest-resolve-env.aspect.ts deleted file mode 100644 index 126b1b5a3fe9..000000000000 --- a/e2e/fixtures/extensions/custom-jest-resolve-env/custom-jest-resolve-env.aspect.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Aspect } from '@teambit/harmony'; - -export const CustomJestResolveEnv = Aspect.create({ - id: 'my-scope/custom-jest-resolve-env', -}); diff --git a/e2e/fixtures/extensions/custom-jest-resolve-env/custom-jest-resolve-env.bit-env.ts b/e2e/fixtures/extensions/custom-jest-resolve-env/custom-jest-resolve-env.bit-env.ts new file mode 100644 index 000000000000..1373db93648e --- /dev/null +++ b/e2e/fixtures/extensions/custom-jest-resolve-env/custom-jest-resolve-env.bit-env.ts @@ -0,0 +1,57 @@ +import { + TypescriptTask, +} from '@teambit/typescript.typescript-compiler'; +import { resolve } from 'path'; +import { Pipeline } from "@teambit/builder"; +import { Tester, TesterContext } from '@teambit/tester'; +import { EnvHandler } from '@teambit/envs'; +import { Component } from '@teambit/component'; +import { ReactEnv } from '@teambit/react.react-env'; +import type { ReactEnvInterface } from '@teambit/react.react-env'; +import { JestTask, JestTester } from '@teambit/defender.jest-tester'; + +function generateResolveSpecPathsFunc(pattern: string) { + return (component: Component, context: TesterContext) => { + const componentPatternValue = context.patterns.get(component); + if (!componentPatternValue) return [] as string[]; + const [, patternEntry] = componentPatternValue; + return [resolve(patternEntry.componentDir, pattern)] + } +} + +export class CustomJestResolveTesterEnv extends ReactEnv implements ReactEnvInterface { + /** + * name of the environment. used for friendly mentions across bit. + */ + name = 'custom-jest-resolve-tester'; + + /** + * icon for the env. use this to build a more friendly env. + * uses react by default. + */ + icon = 'https://static.bit.dev/extensions-icons/react.svg'; + + protected jestConfigPath = require.resolve('./config/jest.config'); + protected tsconfigPath = require.resolve('./config/tsconfig.json'); + + tester(): EnvHandler { + return JestTester.from({ + config: this.jestConfigPath, + resolveSpecPaths: generateResolveSpecPathsFunc('**/*.custom-pattern.spec.+(js|ts|jsx|tsx)') + }); + } + + build() { + return Pipeline.from([ + TypescriptTask.from({ + tsconfig: this.tsconfigPath, + }), + JestTask.from({ + config: this.jestConfigPath, + resolveSpecPaths: generateResolveSpecPathsFunc('**/*.custom-pattern.spec.+(js|ts|jsx|tsx)') + }) + ]); + } +} + +export default new CustomJestResolveTesterEnv(); diff --git a/e2e/fixtures/extensions/custom-jest-resolve-env/custom-jest-resolve-env.main.runtime.ts b/e2e/fixtures/extensions/custom-jest-resolve-env/custom-jest-resolve-env.main.runtime.ts deleted file mode 100644 index cdb6becf5ece..000000000000 --- a/e2e/fixtures/extensions/custom-jest-resolve-env/custom-jest-resolve-env.main.runtime.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { MainRuntime } from '@teambit/cli'; -import { ReactAspect, ReactMain } from '@teambit/react'; -import { JestAspect, JestMain } from '@teambit/jest'; -import { EnvsAspect, EnvsMain } from '@teambit/envs'; -import { CustomJestResolveEnv } from './custom-jest-resolve-env.aspect'; -import { join, resolve } from 'path'; -import { Component } from '@teambit/component'; -import { TesterContext } from '@teambit/tester'; - -export class CustomJestResolveEnvMain { - static slots = []; - - static dependencies = [ReactAspect, EnvsAspect, JestAspect]; - - static runtime = MainRuntime; - - static async provider([react, envs, jestAspect]: [ReactMain, EnvsMain, JestMain]) { - const templatesReactEnv = envs.compose(react.reactEnv, [ - envs.override({ - getTester: () => { - const pathToSource = __dirname.replace('/dist', ''); - const configPath = join(pathToSource, './jest/jest.config.js'); - const opts = { - resolveSpecPaths: (component: Component, context: TesterContext) => { - const componentPatternValue = context.patterns.get(component); - if (!componentPatternValue) return [] as string[]; - const [, patternEntry] = componentPatternValue; - return [resolve(patternEntry.componentDir, '**/*.custom-pattern.spec.+(js|ts|jsx|tsx)')] - } - } - return jestAspect.createTester(configPath, undefined, opts); - } - }), - ]); - envs.registerEnv(templatesReactEnv); - return new CustomJestResolveEnvMain(); - } -} - -CustomJestResolveEnv.addRuntime(CustomJestResolveEnvMain); diff --git a/e2e/fixtures/extensions/custom-jest-resolve-env/index.ts b/e2e/fixtures/extensions/custom-jest-resolve-env/index.ts index fc258217a7f2..c367851bed2e 100644 --- a/e2e/fixtures/extensions/custom-jest-resolve-env/index.ts +++ b/e2e/fixtures/extensions/custom-jest-resolve-env/index.ts @@ -1,5 +1,4 @@ -import { CustomJestResolveEnv } from './custom-jest-resolve-env.aspect'; +import { CustomJestResolveTesterEnv } from './custom-jest-resolve-env.bit-env'; -export type { CustomJestResolveEnvMain } from './custom-jest-resolve-env.main.runtime'; -export default CustomJestResolveEnv; -export { CustomJestResolveEnv }; +export default CustomJestResolveTesterEnv; +export { CustomJestResolveTesterEnv }; diff --git a/e2e/fixtures/extensions/custom-jest-resolve-env/jest/jest.config.js b/e2e/fixtures/extensions/custom-jest-resolve-env/jest/jest.config.js deleted file mode 100644 index 983775c26171..000000000000 --- a/e2e/fixtures/extensions/custom-jest-resolve-env/jest/jest.config.js +++ /dev/null @@ -1,10 +0,0 @@ -const reactJestConfig = require('@teambit/react/jest/jest.cjs.config'); -// uncomment the line below and install the package if you want to use this function -// const { -// generateNodeModulesPattern, -// } = require('@teambit/dependencies.modules.packages-excluder'); -// const packagesToExclude = ['@my-org', 'my-package-name']; - -module.exports = { - ...reactJestConfig -}; diff --git a/e2e/fixtures/extensions/custom-jest-resolve-env/typescript/tsconfig.json b/e2e/fixtures/extensions/custom-jest-resolve-env/typescript/tsconfig.json deleted file mode 100644 index fd9427ddf3ab..000000000000 --- a/e2e/fixtures/extensions/custom-jest-resolve-env/typescript/tsconfig.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - // add your compiler options here - - "compilerOptions": { - // "target": "es2017", - // "module": "es2015", - // "moduleResolution": "node", - // "lib": ["es2017", "dom"], - // "experimentalDecorators": true, - // "esModuleInterop": true, - // "outDir": "dist", - // "sourceMap": true, - // "emitDecoratorMetadata": true, - // "allowJs": true, - // "baseUrl": ".", - // "jsx": "react" - } -} diff --git a/e2e/fixtures/extensions/custom-jest-resolve-env/webpack/webpack-transformers.ts b/e2e/fixtures/extensions/custom-jest-resolve-env/webpack/webpack-transformers.ts deleted file mode 100644 index a812f9631e65..000000000000 --- a/e2e/fixtures/extensions/custom-jest-resolve-env/webpack/webpack-transformers.ts +++ /dev/null @@ -1,45 +0,0 @@ - - import { WebpackConfigTransformer, WebpackConfigMutator, WebpackConfigTransformContext } from '@teambit/webpack'; - - /** - * Transformation to apply for both preview and dev server - * @param config - * @param _context - */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - function commonTransformation(config: WebpackConfigMutator, _context: WebpackConfigTransformContext) { - // Merge config with the webpack.config.js file if you choose to import a module export format config. - // config.merge([webpackConfig]); - // config.addAliases({}); - // config.addModuleRule(youRuleHere); - return config; - } - - /** - * Transformation for the preview only - * @param config - * @param context - * @returns - */ - export const previewConfigTransformer: WebpackConfigTransformer = ( - config: WebpackConfigMutator, - context: WebpackConfigTransformContext - ) => { - const newConfig = commonTransformation(config, context); - return newConfig; - }; - - /** - * Transformation for the dev server only - * @param config - * @param context - * @returns - */ - export const devServerConfigTransformer: WebpackConfigTransformer = ( - config: WebpackConfigMutator, - context: WebpackConfigTransformContext - ) => { - const newConfig = commonTransformation(config, context); - return newConfig; - }; - diff --git a/e2e/fixtures/extensions/invalid-jest-config-env/config/jest.config.js b/e2e/fixtures/extensions/invalid-jest-config-env/config/jest.config.js new file mode 100644 index 000000000000..5124004d40db --- /dev/null +++ b/e2e/fixtures/extensions/invalid-jest-config-env/config/jest.config.js @@ -0,0 +1,16 @@ +// Override the Jest config to ignore transpiling from specific folders +// See the base Jest config: https://bit.cloud/teambit/react/react/~code/jest/jest.config.js + +const { jestConfig } = require('@teambit/react.react-env'); +// const { esmConfig } = require('@teambit/react.jest.react-jest'); +// uncomment the line below and install the package if you want to use this function +// const { +// generateNodeModulesPattern, +// } = require('@teambit/dependencies.modules.packages-excluder'); +// const packagesToExclude = ['@my-org', 'my-package-name']; +module.exports = { + ...jestConfig, + transformIgnorePatterns: [ + someUndefinedFunc(), + ], +}; diff --git a/e2e/fixtures/extensions/invalid-jest-config-env/config/tsconfig.json b/e2e/fixtures/extensions/invalid-jest-config-env/config/tsconfig.json new file mode 100644 index 000000000000..94befdf2c7c7 --- /dev/null +++ b/e2e/fixtures/extensions/invalid-jest-config-env/config/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "@teambit/react.react-env/config/tsconfig.json", + "exclude": [ + "artifacts", + "public", + "dist", + "node_modules", + "package.json", + "**/*.cjs" + ], + "include": ["**/*", "**/*.json"] +} diff --git a/e2e/fixtures/extensions/invalid-jest-config-env/index.ts b/e2e/fixtures/extensions/invalid-jest-config-env/index.ts new file mode 100644 index 000000000000..5d71071b42b4 --- /dev/null +++ b/e2e/fixtures/extensions/invalid-jest-config-env/index.ts @@ -0,0 +1,4 @@ +import { InvalidJestConfigTesterEnv } from './invalid-jest-config.bit-env'; + +export default InvalidJestConfigTesterEnv; +export { InvalidJestConfigTesterEnv }; diff --git a/e2e/fixtures/extensions/invalid-jest-config-env/invalid-jest-config.bit-env.ts b/e2e/fixtures/extensions/invalid-jest-config-env/invalid-jest-config.bit-env.ts new file mode 100644 index 000000000000..2321411bbf67 --- /dev/null +++ b/e2e/fixtures/extensions/invalid-jest-config-env/invalid-jest-config.bit-env.ts @@ -0,0 +1,55 @@ +import { + TypescriptTask, +} from '@teambit/typescript.typescript-compiler'; +import { resolve } from 'path'; +import { Pipeline } from "@teambit/builder"; +import { Tester, TesterContext } from '@teambit/tester'; +import { EnvHandler } from '@teambit/envs'; +import { Component } from '@teambit/component'; +import { ReactEnv } from '@teambit/react.react-env'; +import type { ReactEnvInterface } from '@teambit/react.react-env'; +import { JestTask, JestTester } from '@teambit/defender.jest-tester'; + +function generateResolveSpecPathsFunc(pattern: string) { + return (component: Component, context: TesterContext) => { + const componentPatternValue = context.patterns.get(component); + if (!componentPatternValue) return [] as string[]; + const [, patternEntry] = componentPatternValue; + return [resolve(patternEntry.componentDir, pattern)] + } +} + +export class InvalidJestConfigTesterEnv extends ReactEnv implements ReactEnvInterface { + /** + * name of the environment. used for friendly mentions across bit. + */ + name = 'invalid-jest-config-tester'; + + /** + * icon for the env. use this to build a more friendly env. + * uses react by default. + */ + icon = 'https://static.bit.dev/extensions-icons/react.svg'; + + protected jestConfigPath = require.resolve('./config/jest.config'); + protected tsconfigPath = require.resolve('./config/tsconfig.json'); + + tester(): EnvHandler { + return JestTester.from({ + config: this.jestConfigPath, + }); + } + + build() { + return Pipeline.from([ + TypescriptTask.from({ + tsconfig: this.tsconfigPath, + }), + JestTask.from({ + config: this.jestConfigPath, + }) + ]); + } +} + +export default new InvalidJestConfigTesterEnv(); diff --git a/e2e/fixtures/extensions/multi-jest-testers-env/config/jest.config.js b/e2e/fixtures/extensions/multi-jest-testers-env/config/jest.config.js new file mode 100644 index 000000000000..e1d0565f1c45 --- /dev/null +++ b/e2e/fixtures/extensions/multi-jest-testers-env/config/jest.config.js @@ -0,0 +1,17 @@ +// Override the Jest config to ignore transpiling from specific folders +// See the base Jest config: https://bit.cloud/teambit/react/react/~code/jest/jest.config.js + +const { jestConfig } = require('@teambit/react.react-env'); +// const { esmConfig } = require('@teambit/react.jest.react-jest'); +// uncomment the line below and install the package if you want to use this function +// const { +// generateNodeModulesPattern, +// } = require('@teambit/dependencies.modules.packages-excluder'); +// const packagesToExclude = ['@my-org', 'my-package-name']; +module.exports = { + ...jestConfig, + // transformIgnorePatterns: [ + // '^.+\.module\.(css|sass|scss)$', + // generateNodeModulesPattern({ packages: packagesToExclude }), + // ], +}; diff --git a/e2e/fixtures/extensions/multi-jest-testers-env/config/tsconfig.json b/e2e/fixtures/extensions/multi-jest-testers-env/config/tsconfig.json new file mode 100644 index 000000000000..94befdf2c7c7 --- /dev/null +++ b/e2e/fixtures/extensions/multi-jest-testers-env/config/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "@teambit/react.react-env/config/tsconfig.json", + "exclude": [ + "artifacts", + "public", + "dist", + "node_modules", + "package.json", + "**/*.cjs" + ], + "include": ["**/*", "**/*.json"] +} diff --git a/e2e/fixtures/extensions/multi-jest-testers-env/index.ts b/e2e/fixtures/extensions/multi-jest-testers-env/index.ts index 4f35c5303829..d5bef23e10d8 100644 --- a/e2e/fixtures/extensions/multi-jest-testers-env/index.ts +++ b/e2e/fixtures/extensions/multi-jest-testers-env/index.ts @@ -1,5 +1,4 @@ -import { MultiJestTestersEnv } from './multi-jest-testers-env.aspect'; +import { MultiJestTesterEnv } from './multi-jest-tester-env.bit-env'; -export type { MultiJestTestersEnvMain } from './multi-jest-testers-env.main.runtime'; -export default MultiJestTestersEnv; -export { MultiJestTestersEnv }; +export default MultiJestTesterEnv; +export { MultiJestTesterEnv }; diff --git a/e2e/fixtures/extensions/multi-jest-testers-env/jest/jest.config.js b/e2e/fixtures/extensions/multi-jest-testers-env/jest/jest.config.js deleted file mode 100644 index 983775c26171..000000000000 --- a/e2e/fixtures/extensions/multi-jest-testers-env/jest/jest.config.js +++ /dev/null @@ -1,10 +0,0 @@ -const reactJestConfig = require('@teambit/react/jest/jest.cjs.config'); -// uncomment the line below and install the package if you want to use this function -// const { -// generateNodeModulesPattern, -// } = require('@teambit/dependencies.modules.packages-excluder'); -// const packagesToExclude = ['@my-org', 'my-package-name']; - -module.exports = { - ...reactJestConfig -}; diff --git a/e2e/fixtures/extensions/multi-jest-testers-env/multi-jest-tester-env.bit-env.ts b/e2e/fixtures/extensions/multi-jest-testers-env/multi-jest-tester-env.bit-env.ts new file mode 100644 index 000000000000..075d3631314c --- /dev/null +++ b/e2e/fixtures/extensions/multi-jest-testers-env/multi-jest-tester-env.bit-env.ts @@ -0,0 +1,74 @@ +import { + TypescriptTask, +} from '@teambit/typescript.typescript-compiler'; +import { resolve } from 'path'; +import { Pipeline } from "@teambit/builder"; +import { Tester, TesterContext } from '@teambit/tester'; +import { EnvHandler } from '@teambit/envs'; +import { Component } from '@teambit/component'; +import { ReactEnv } from '@teambit/react.react-env'; +import type { ReactEnvInterface } from '@teambit/react.react-env'; +import { JestTester } from '@teambit/defender.jest-tester'; +import {MultiTester, MultiTesterTask} from '@teambit/defender.testers.multi-tester'; + +function generateResolveSpecPathsFunc(pattern: string) { + return (component: Component, context: TesterContext) => { + const componentPatternValue = context.patterns.get(component); + if (!componentPatternValue) return [] as string[]; + const [, patternEntry] = componentPatternValue; + return [resolve(patternEntry.componentDir, pattern)] + } +} + +export class MultiJestTesterEnv extends ReactEnv implements ReactEnvInterface { + /** + * name of the environment. used for friendly mentions across bit. + */ + name = 'multi-jest-tester'; + + /** + * icon for the env. use this to build a more friendly env. + * uses react by default. + */ + icon = 'https://static.bit.dev/extensions-icons/react.svg'; + + protected jestConfigPath = require.resolve('./config/jest.config'); + protected tsconfigPath = require.resolve('./config/tsconfig.json'); + + tester(): EnvHandler { + return MultiTester.fromTesterHandlers({ + testers: [ + JestTester.from({ + config: this.jestConfigPath, + resolveSpecPaths: generateResolveSpecPathsFunc('**/*.custom-pattern-1.spec.+(js|ts|jsx|tsx)') + }), + JestTester.from({ + config: this.jestConfigPath, + resolveSpecPaths: generateResolveSpecPathsFunc('**/*.custom-pattern-2.spec.+(js|ts|jsx|tsx)') + }) + ] + }); + } + + build() { + return Pipeline.from([ + TypescriptTask.from({ + tsconfig: this.tsconfigPath, + }), + MultiTesterTask.fromTesterHandlers({ + testers: [ + JestTester.from({ + config: this.jestConfigPath, + resolveSpecPaths: generateResolveSpecPathsFunc('**/*.custom-pattern-1.spec.+(js|ts|jsx|tsx)') + }), + JestTester.from({ + config: this.jestConfigPath, + resolveSpecPaths: generateResolveSpecPathsFunc('**/*.custom-pattern-2.spec.+(js|ts|jsx|tsx)') + }) + ] + }) + ]); + } +} + +export default new MultiJestTesterEnv(); diff --git a/e2e/fixtures/extensions/multi-jest-testers-env/multi-jest-testers-env.aspect.ts b/e2e/fixtures/extensions/multi-jest-testers-env/multi-jest-testers-env.aspect.ts deleted file mode 100644 index a4d1ea9eb554..000000000000 --- a/e2e/fixtures/extensions/multi-jest-testers-env/multi-jest-testers-env.aspect.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Aspect } from '@teambit/harmony'; - -export const MultiJestTestersEnv = Aspect.create({ - id: 'my-scope/multi-jest-testers-env', -}); diff --git a/e2e/fixtures/extensions/multi-jest-testers-env/multi-jest-testers-env.main.runtime.ts b/e2e/fixtures/extensions/multi-jest-testers-env/multi-jest-testers-env.main.runtime.ts deleted file mode 100644 index 375de276d756..000000000000 --- a/e2e/fixtures/extensions/multi-jest-testers-env/multi-jest-testers-env.main.runtime.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { MainRuntime } from '@teambit/cli'; -import { ReactAspect, ReactMain } from '@teambit/react'; -import { JestAspect, JestMain } from '@teambit/jest'; -import { EnvsAspect, EnvsMain } from '@teambit/envs'; -import { MultiJestTestersEnv } from './multi-jest-testers-env.aspect'; -import { join, resolve } from 'path'; -import { Component } from '@teambit/component'; -import { TesterContext } from '@teambit/tester'; -import { MultiTesterAspect, MultiTesterMain } from '@teambit/multi-tester'; - - -export class MultiJestTestersEnvMain { - static slots = []; - - static dependencies = [ReactAspect, EnvsAspect, JestAspect, MultiTesterAspect]; - - static runtime = MainRuntime; - - static async provider([react, envs, jestAspect, multiTester]: [ReactMain, EnvsMain, JestMain, MultiTesterMain]) { - function getJestTester(jestConfigName: string, pattern: string) { - const pathToSource = __dirname.replace('/dist', ''); - const configPath = join(pathToSource, `./jest/${jestConfigName}`); - const opts = { - resolveSpecPaths: (component: Component, context: TesterContext) => { - const componentPatternValue = context.patterns.get(component); - if (!componentPatternValue) return [] as string[]; - const [, patternEntry] = componentPatternValue; - return [resolve(patternEntry.componentDir, pattern)] - } - } - const jestTester = jestAspect.createTester(configPath, undefined, opts); - return jestTester; - } - - const templatesReactEnv = envs.compose(react.reactEnv, [ - envs.override({ - getTester: () => { - const custom1JestTester = getJestTester('jest.config.js', '**/*.custom-pattern-1.spec.+(js|ts|jsx|tsx)') - const custom2JestTester = getJestTester('jest.config.js', '**/*.custom-pattern-2.spec.+(js|ts|jsx|tsx)') - const combinedTester = multiTester.createTester([custom1JestTester, custom2JestTester]); - return combinedTester; - } - }), - ]); - envs.registerEnv(templatesReactEnv); - return new MultiJestTestersEnvMain(); - } -} - -MultiJestTestersEnv.addRuntime(MultiJestTestersEnvMain); diff --git a/e2e/harmony/jest.e2e.ts b/e2e/harmony/jest.e2e.ts index 8ef572ff4431..a967d2860e6b 100644 --- a/e2e/harmony/jest.e2e.ts +++ b/e2e/harmony/jest.e2e.ts @@ -92,15 +92,20 @@ describe('Jest Tester', function () { }); }); describe('env with an incorrect Jest config', () => { + let envName; + let envId; before(() => { helper.scopeHelper.reInitLocalScope(); helper.fixtures.populateComponents(1); helper.fs.outputFile('comp1/comp1.spec.ts', specFilePassingFixture()); - helper.env.setCustomEnv('custom-react-env'); - helper.fs.outputFile('custom-react-env/jest/jest.config.js', invalidJestConfigFixture()); - helper.command.compile(); - helper.command.install(); - helper.command.setEnv('comp1', 'custom-react-env'); + envName = helper.env.setCustomNewEnv('invalid-jest-config-env', [ + '@teambit/react.react-env', + '@teambit/typescript.typescript-compiler', + '@teambit/defender.jest-tester', + '@teambit/defender.testers.multi-tester', + ]); + envId = `${helper.scopes.remote}/${envName}`; + helper.command.setEnv('comp1', envId); }); it('bit test should exit with non-zero code', () => { expect(() => helper.command.test()).to.throw(); @@ -117,6 +122,8 @@ describe('Jest Tester', function () { describe('env with custom spec resolver', () => { let compName; + let envName; + let envId; before(() => { helper.scopeHelper.reInitLocalScope(); compName = helper.fixtures.populateComponents(1); @@ -125,10 +132,13 @@ describe('Jest Tester', function () { 'comp1/comp1.custom-pattern.spec.ts', specFilePassingFixture('custom pattern describe text', 'custom pattern it text') ); - helper.env.setCustomEnv('custom-jest-resolve-env'); - helper.command.compile(); - helper.command.install(); - helper.command.setEnv('comp1', 'custom-jest-resolve-env'); + envName = helper.env.setCustomNewEnv('custom-jest-resolve-env', [ + '@teambit/react.react-env', + '@teambit/typescript.typescript-compiler', + '@teambit/defender.jest-tester', + ]); + envId = `${helper.scopes.remote}/${envName}`; + helper.command.setEnv('comp1', envId); }); describe('bit test command', () => { let output; @@ -202,12 +212,3 @@ function specFileErroringFixture() { }); `; } - -function invalidJestConfigFixture() { - return `module.exports = { - transformIgnorePatterns: [ - someUndefinedFunc(), - ], - }; - `; -} diff --git a/e2e/harmony/multiple-testers.e2e.ts b/e2e/harmony/multiple-testers.e2e.ts index 7fe060e61d0f..588a5607c9a2 100644 --- a/e2e/harmony/multiple-testers.e2e.ts +++ b/e2e/harmony/multiple-testers.e2e.ts @@ -16,6 +16,8 @@ describe('multi testers', function () { (IS_WINDOWS ? describe.skip : describe)('2 jest testers with different resolve pattern', function () { let compName; + let envId; + let envName; before(() => { helper.scopeHelper.reInitLocalScope(); compName = helper.fixtures.populateComponents(1); @@ -28,10 +30,15 @@ describe('multi testers', function () { 'comp1/comp1.custom-pattern-2.spec.ts', specFilePassingFixture('custom-pattern-2 describe text', 'custom-pattern-2 it text') ); - helper.env.setCustomEnv('multi-jest-testers-env'); - helper.command.compile(); + envName = helper.env.setCustomNewEnv('multi-jest-testers-env', [ + '@teambit/react.react-env', + '@teambit/typescript.typescript-compiler', + '@teambit/defender.jest-tester', + '@teambit/defender.testers.multi-tester', + ]); + envId = `${helper.scopes.remote}/${envName}`; + helper.command.setEnv('comp1', envId); helper.command.install(); - helper.command.setEnv('comp1', 'multi-jest-testers-env'); }); describe('bit test command', () => { let output; @@ -61,7 +68,7 @@ describe('multi testers', function () { before(() => { output = helper.command.build(compName, undefined, true); }); - it('bit test should run spec files in separate runs', () => { + it('test task should run spec files in separate runs', () => { const matches = Array.from(output.matchAll(/Test Suites: 1 passed/g)); const numOfTestSuites = matches.length; expect(numOfTestSuites).to.equal(2); diff --git a/e2e/harmony/tag-harmony.e2e.ts b/e2e/harmony/tag-harmony.e2e.ts index 972323485d90..18657f1b7a7e 100644 --- a/e2e/harmony/tag-harmony.e2e.ts +++ b/e2e/harmony/tag-harmony.e2e.ts @@ -232,9 +232,9 @@ describe('tag components on Harmony', function () { beforeTagScope = helper.scopeHelper.cloneLocalScope(); }); it('should fail without --skip-tests', () => { - expect(() => helper.command.tagAllComponents()).to.throw( - 'Failed task 1: "teambit.defender/tester:TestComponents" of env "teambit.harmony/node"' - ); + const cmd = () => helper.command.tagAllComponents(); + const error = new Error('Failed task 1: "teambit.defender/tester:JestTest" of env "teambit.harmony/node"'); + helper.general.expectToThrow(cmd, error); const stagedConfigPath = helper.general.getStagedConfigPath(); expect(stagedConfigPath).to.not.be.a.path(); }); diff --git a/scopes/defender/jest/jest.main.runtime.ts b/scopes/defender/jest/jest.main.runtime.ts index d91aaff5e109..70754db7abdb 100644 --- a/scopes/defender/jest/jest.main.runtime.ts +++ b/scopes/defender/jest/jest.main.runtime.ts @@ -1,6 +1,7 @@ import { MainRuntime } from '@teambit/cli'; import { LoggerAspect, LoggerMain, Logger } from '@teambit/logger'; import { WorkerAspect, WorkerMain, HarmonyWorker } from '@teambit/worker'; +import { getCloudDomain } from '@teambit/legacy/dist/constants'; import { JestAspect } from './jest.aspect'; import { JestTester, JestTesterOptions } from './jest.tester'; import type { JestWorker } from './jest.worker'; @@ -10,7 +11,13 @@ export const WORKER_NAME = 'jest'; export class JestMain { constructor(private jestWorker: HarmonyWorker, private logger: Logger) {} + /** + * @deprecated use jest tester from https://bit.cloud/teambit/defender/jest-tester + */ createTester(jestConfig: any, jestModulePath = require.resolve('jest'), opts?: JestTesterOptions) { + this.logger.consoleWarning( + `The 'Jest' aspect is deprecated. Please use the 'jest tester' component instead. For more details, visit: https://${getCloudDomain()}/teambit/defender/jest-tester` + ); return new JestTester(JestAspect.id, jestConfig, jestModulePath, this.jestWorker, this.logger, opts); } diff --git a/scopes/defender/multi-tester/multi-tester.main.runtime.ts b/scopes/defender/multi-tester/multi-tester.main.runtime.ts index 1cbac6243c88..0357d017b752 100644 --- a/scopes/defender/multi-tester/multi-tester.main.runtime.ts +++ b/scopes/defender/multi-tester/multi-tester.main.runtime.ts @@ -1,21 +1,32 @@ +import { getCloudDomain } from '@teambit/legacy/dist/constants'; import { MainRuntime } from '@teambit/cli'; import { Tester } from '@teambit/tester'; +import { LoggerAspect, LoggerMain, Logger } from '@teambit/logger'; import { MultiTesterAspect } from './multi-tester.aspect'; import { MultiTester } from './multi-tester.tester'; export class MultiTesterMain { + constructor(private logger: Logger) {} + /** + * + * @deprecated use jest tester from https://bit.cloud/teambit/defender/testers/multi-tester * create a multi-tester `Tester` instance. * @param testers list of testers to include. */ createTester(testers: Tester[]) { + this.logger.consoleWarning( + `The 'MultiTester' aspect is deprecated. Please use the 'multi tester' component instead. For more details, visit: https://${getCloudDomain()}/teambit/defender/testers/multi-tester` + ); return new MultiTester(MultiTesterAspect.id, testers); } static runtime = MainRuntime; + static dependencies = [LoggerAspect]; - static async provider() { - return new MultiTesterMain(); + static async provider([loggerAspect]: [LoggerMain]) { + const logger = loggerAspect.createLogger(MultiTesterAspect.id); + return new MultiTesterMain(logger); } } diff --git a/scopes/harmony/cli-reference/cli-reference.docs.mdx b/scopes/harmony/cli-reference/cli-reference.docs.mdx index 912fefae8464..75899b9568ea 100644 --- a/scopes/harmony/cli-reference/cli-reference.docs.mdx +++ b/scopes/harmony/cli-reference/cli-reference.docs.mdx @@ -2,4 +2,3 @@ description: 'Bit command synopses. Bit version: 1.7.47' labels: ['cli', 'mdx', 'docs'] --- - diff --git a/scopes/harmony/node/node.env.ts b/scopes/harmony/node/node.env.ts index 083f2faa9398..9d297333c135 100644 --- a/scopes/harmony/node/node.env.ts +++ b/scopes/harmony/node/node.env.ts @@ -50,7 +50,7 @@ export class NodeEnv implements DependenciesEnv, PackageEnv { */ getTester(jestConfigPath: string, jestModulePath?: string): Tester { const config = jestConfigPath || require.resolve('./jest/jest.config'); - return this.reactAspect.reactEnv.getCjsJestTester(config, jestModulePath); + return this.reactAspect.reactEnv.createCjsJestTester(config, jestModulePath); } getPreviewConfig() { diff --git a/scopes/harmony/worker/harmony-worker.ts b/scopes/harmony/worker/harmony-worker.ts index 76f358bb78e3..e6aa33258554 100644 --- a/scopes/harmony/worker/harmony-worker.ts +++ b/scopes/harmony/worker/harmony-worker.ts @@ -27,9 +27,9 @@ export type InitOptions = { export class HarmonyWorker { constructor(readonly name: string, readonly workerPath: string) {} - private remoteWorker: undefined | Remote; + protected remoteWorker: undefined | Remote; - private worker: Worker | undefined; + protected worker: Worker | undefined; get stdout() { return this.worker?.stdout; diff --git a/scopes/react/react/jest/jest.base.config.js b/scopes/react/react/jest/jest.base.config.js deleted file mode 100644 index ba3b578f82e9..000000000000 --- a/scopes/react/react/jest/jest.base.config.js +++ /dev/null @@ -1,31 +0,0 @@ -module.exports = { - // "roots": [ - // "/src" - // ], - // "collectCoverageFrom": [ - // "src/**/*.{js,jsx,ts,tsx}", - // "!src/**/*.d.ts" - // ], - setupFiles: [require.resolve('react-app-polyfill/jsdom')], - setupFilesAfterEnv: [require.resolve('./setupTests.js')], - // "testMatch": [ - // "/src/**/__tests__/**/*.{js,jsx,ts,tsx}", - // "/src/**/*.{spec,test}.{js,jsx,ts,tsx}" - // ], - testEnvironment: require.resolve('jest-environment-jsdom'), - transform: { - '^.+\\.css$': require.resolve('./transformers/css-transform.js'), - '^(?!.*\\.(js|jsx|ts|tsx|css|json)$)': require.resolve('./transformers/file-transform.js'), - // '^(?!.*\\.(svg|png|jpg|jpeg|gif|webp|woff|ttf|woff2)$)': require.resolve('./file-transform.js'), - }, - transformIgnorePatterns: ['[/\\\\]node_modules[/\\\\].+\\.(js|jsx|ts|tsx|cjs)$', '^.+\\.module\\.(css|sass|scss)$'], - modulePaths: [], - moduleNameMapper: { - '\\.(css|less|scss|sass)$': require.resolve('identity-obj-proxy'), - '^react-native$': require.resolve('react-native-web'), - '^.+\\.module\\.(css|sass|scss)$': require.resolve('identity-obj-proxy'), - }, - moduleFileExtensions: ['web.js', 'js', 'web.ts', 'ts', 'web.tsx', 'tsx', 'json', 'web.jsx', 'jsx', 'node'], - testTimeout: 30000, // @todo remove this once mocha-tester is ready and aspect-api testing are using it. - // watchPlugins: [require.resolve('jest-watch-typeahead/filename'), require.resolve('jest-watch-typeahead/testname')], -}; diff --git a/scopes/react/react/jest/jest.cjs.config.js b/scopes/react/react/jest/jest.cjs.config.js index 77efed1c3ad4..e74eee06720c 100644 --- a/scopes/react/react/jest/jest.cjs.config.js +++ b/scopes/react/react/jest/jest.cjs.config.js @@ -1,8 +1,14 @@ -const baseConfig = require('./jest.base.config'); +const { cjsConfig } = require('@teambit/react.jest.react-jest'); +const { generateNodeModulesPattern } = require('@teambit/dependencies.modules.packages-excluder'); +const packagesToExclude = ['@teambit']; -const cjsTransformer = require.resolve('./transformers/cjs-transformer.js'); - -const cjsTransform = { ...baseConfig.transform, '^.+\\.(js|jsx|ts|tsx|cjs)$': cjsTransformer }; -const cjsConfig = { ...baseConfig, transform: cjsTransform }; - -module.exports = cjsConfig; +module.exports = { + ...cjsConfig, + transformIgnorePatterns: [ + '^.+.module.(css|sass|scss)$', + generateNodeModulesPattern({ + packages: packagesToExclude, + excludeComponents: true, + }), + ], +}; diff --git a/scopes/react/react/jest/jest.config.js b/scopes/react/react/jest/jest.config.js deleted file mode 100644 index 37b822d1c4a2..000000000000 --- a/scopes/react/react/jest/jest.config.js +++ /dev/null @@ -1,7 +0,0 @@ -// DEPRECATED -// This file is here for backward compatibility. not breaking users who used to import this file directly. -// Please use the specific config file (jest.cjs.config / jest.esm.config) instead - -const cjsConfig = require('./jest.cjs.config'); - -module.exports = cjsConfig; diff --git a/scopes/react/react/jest/jest.esm.config.js b/scopes/react/react/jest/jest.esm.config.js index 4d7851073c3c..a694200808b4 100644 --- a/scopes/react/react/jest/jest.esm.config.js +++ b/scopes/react/react/jest/jest.esm.config.js @@ -1,7 +1,14 @@ -const baseConfig = require('./jest.base.config'); +const { esmConfig } = require('@teambit/react.jest.react-jest'); +const { generateNodeModulesPattern } = require('@teambit/dependencies.modules.packages-excluder'); +const packagesToExclude = ['@teambit']; -const esmTransformer = require.resolve('./transformers/esm-transformer.js'); -const esmTransform = { ...baseConfig.transform, '^.+\\.(js|jsx|ts|tsx)$': esmTransformer }; -const esmConfig = { ...baseConfig, extensionsToTreatAsEsm: ['.ts', '.tsx', '.jsx'], transform: esmTransform }; - -module.exports = esmConfig; +module.exports = { + ...esmConfig, + transformIgnorePatterns: [ + '^.+.module.(css|sass|scss)$', + generateNodeModulesPattern({ + packages: packagesToExclude, + excludeComponents: true, + }), + ], +}; diff --git a/scopes/react/react/jest/setupTests.js b/scopes/react/react/jest/setupTests.js deleted file mode 100644 index 4954beadc45a..000000000000 --- a/scopes/react/react/jest/setupTests.js +++ /dev/null @@ -1,7 +0,0 @@ -// add babel-polyfill. -// require('babel-polyfill'); -// jest-dom adds custom jest matchers for asserting on DOM nodes. -// allows you to do things like: -// expect(element).toHaveTextContent(/react/i) -// learn more: https://github.com/testing-library/jest-dom -require('@testing-library/jest-dom/extend-expect'); diff --git a/scopes/react/react/jest/transformers/base-transformer-plugins.js b/scopes/react/react/jest/transformers/base-transformer-plugins.js deleted file mode 100644 index 76e5c85c0121..000000000000 --- a/scopes/react/react/jest/transformers/base-transformer-plugins.js +++ /dev/null @@ -1,13 +0,0 @@ -/* eslint-disable global-require */ - -const basePlugins = [ - [require('babel-plugin-transform-typescript-metadata')], - [require('@babel/plugin-proposal-decorators'), { legacy: true }], - // [require('@babel/plugin-transform-runtime')], - [require('@babel/plugin-transform-object-rest-spread')], - [require('@babel/plugin-transform-class-properties')], -]; - -module.exports = { - basePlugins, -}; diff --git a/scopes/react/react/jest/transformers/base-transformer-presets.js b/scopes/react/react/jest/transformers/base-transformer-presets.js deleted file mode 100644 index 3099df035a12..000000000000 --- a/scopes/react/react/jest/transformers/base-transformer-presets.js +++ /dev/null @@ -1,11 +0,0 @@ -/* eslint-disable global-require */ - -const basePresets = [ - [require('@babel/preset-react'), { runtime: 'automatic' }], - require('@babel/preset-typescript'), - require('babel-preset-jest'), -]; - -module.exports = { - basePresets, -}; diff --git a/scopes/react/react/jest/transformers/base-transformer-process.js b/scopes/react/react/jest/transformers/base-transformer-process.js deleted file mode 100644 index 09675ee3e924..000000000000 --- a/scopes/react/react/jest/transformers/base-transformer-process.js +++ /dev/null @@ -1,20 +0,0 @@ -const { transform } = require('@babel/core'); - -const generateProcessFunc = (presets, plugins) => { - return (src, filename) => { - const result = transform(src, { - sourceMap: 'inline', - filename, - presets, - plugins, - babelrc: false, - configFile: false, - }); - - return result ? result.code : src; - }; -}; - -module.exports = { - generateProcessFunc, -}; diff --git a/scopes/react/react/jest/transformers/cjs-transformer.js b/scopes/react/react/jest/transformers/cjs-transformer.js deleted file mode 100644 index 7a6bf5525ab8..000000000000 --- a/scopes/react/react/jest/transformers/cjs-transformer.js +++ /dev/null @@ -1,25 +0,0 @@ -/* eslint-disable import/order */ -/* eslint-disable global-require */ -const { generateProcessFunc } = require('./base-transformer-process'); -const { basePlugins } = require('./base-transformer-plugins'); -const { basePresets } = require('./base-transformer-presets'); - -const presets = [ - ...basePresets, - [ - require('@babel/preset-env'), - { - targets: { - node: 16, - }, - // useBuiltIns: 'usage', - // corejs: 3, - }, - ], -]; - -const plugins = [[require('@babel/plugin-transform-modules-commonjs')], ...basePlugins]; - -module.exports = { - process: generateProcessFunc(presets, plugins), -}; diff --git a/scopes/react/react/jest/transformers/css-transform.js b/scopes/react/react/jest/transformers/css-transform.js deleted file mode 100644 index d3612352dd60..000000000000 --- a/scopes/react/react/jest/transformers/css-transform.js +++ /dev/null @@ -1,12 +0,0 @@ -// This is a custom Jest transformer turning style imports into empty objects. -// http://facebook.github.io/jest/docs/en/webpack.html - -module.exports = { - process() { - return 'module.exports = {};'; - }, - getCacheKey() { - // The output is always the same. - return 'cssTransform'; - }, -}; diff --git a/scopes/react/react/jest/transformers/esm-transformer.js b/scopes/react/react/jest/transformers/esm-transformer.js deleted file mode 100644 index fd99a1129cbb..000000000000 --- a/scopes/react/react/jest/transformers/esm-transformer.js +++ /dev/null @@ -1,27 +0,0 @@ -/* eslint-disable global-require */ -/* eslint-disable import/order */ - -const { basePlugins } = require('./base-transformer-plugins'); -const { basePresets } = require('./base-transformer-presets'); -const { generateProcessFunc } = require('./base-transformer-process'); - -const presets = [ - ...basePresets, - [ - require('@babel/preset-env'), - { - modules: false, - targets: { - node: 16, - }, - // useBuiltIns: 'usage', - // corejs: 3, - }, - ], -]; - -const plugins = basePlugins; - -module.exports = { - process: generateProcessFunc(presets, plugins), -}; diff --git a/scopes/react/react/jest/transformers/file-transform.js b/scopes/react/react/jest/transformers/file-transform.js deleted file mode 100644 index b301c88ffd1c..000000000000 --- a/scopes/react/react/jest/transformers/file-transform.js +++ /dev/null @@ -1,38 +0,0 @@ -const path = require('path'); -const camelcase = require('camelcase'); - -// This is a custom Jest transformer turning file imports into filenames. -// http://facebook.github.io/jest/docs/en/webpack.html - -module.exports = { - process(src, filename) { - const assetFilename = JSON.stringify(path.basename(filename)); - - if (filename.match(/\.svg$/)) { - // Based on how SVGR generates a component name: - // https://github.com/smooth-code/svgr/blob/01b194cf967347d43d4cbe6b434404731b87cf27/packages/core/src/state.js#L6 - const pascalCaseFilename = camelcase(path.parse(filename).name, { - pascalCase: true, - }); - const componentName = `Svg${pascalCaseFilename}`; - return `const React = require('react'); - module.exports = { - __esModule: true, - default: ${assetFilename}, - ReactComponent: React.forwardRef(function ${componentName}(props, ref) { - return { - $$typeof: Symbol.for('react.element'), - type: 'svg', - ref: ref, - key: null, - props: Object.assign({}, props, { - children: ${assetFilename} - }) - }; - }), - };`; - } - - return `module.exports = ${assetFilename};`; - }, -}; diff --git a/scopes/react/react/react.env.ts b/scopes/react/react/react.env.ts index ec251a6493f8..07006adf935b 100644 --- a/scopes/react/react/react.env.ts +++ b/scopes/react/react/react.env.ts @@ -29,7 +29,8 @@ import { PipeServiceModifier, PipeServiceModifiersMap, } from '@teambit/envs'; -import { JestMain } from '@teambit/jest'; +import { JestTask, JestTester, jestWorkerPath } from '@teambit/defender.jest-tester'; +import type { JestWorker } from '@teambit/defender.jest-tester'; import { PackageJsonProps, PkgMain } from '@teambit/pkg'; import { Tester, TesterMain } from '@teambit/tester'; import { TsConfigTransformer, TypescriptMain } from '@teambit/typescript'; @@ -72,6 +73,8 @@ import { templateWebpackConfigFactory } from './webpack/webpack.config.env.templ // webpack configs for components only import componentPreviewProdConfigFactory from './webpack/webpack.config.component.prod'; import componentPreviewDevConfigFactory from './webpack/webpack.config.component.dev'; +import type { WorkerMain } from '@teambit/worker'; +import type { DevFilesMain } from '@teambit/dev-files'; export const ReactEnvType = 'react'; const defaultTsConfig = require('./typescript/tsconfig.json'); @@ -84,6 +87,7 @@ type CompilerMode = 'build' | 'dev'; type GetBuildPipeModifiers = PipeServiceModifiersMap & { tsModifier?: PipeServiceModifier; + jestModifier?: PipeServiceModifier; }; /** @@ -93,11 +97,6 @@ export class ReactEnv implements TesterEnv, CompilerEnv, LinterEnv, DevEnv, BuilderEnv, DependenciesEnv, PackageEnv, FormatterEnv { constructor( - /** - * jest extension - */ - private jestAspect: JestMain, - /** * typescript extension. */ @@ -118,6 +117,11 @@ export class ReactEnv */ private workspace: Workspace, + /** + * worker extension. + */ + private worker: WorkerMain, + /** * pkg extension. */ @@ -132,6 +136,8 @@ export class ReactEnv private dependencyResolver: DependencyResolverMain, + private devFiles: DevFilesMain, + private logger: Logger, private compilerAspectId: string @@ -162,7 +168,20 @@ export class ReactEnv const pathToSource = pathNormalizeToLinux(__dirname).replace('/dist', ''); const defaultConfig = join(pathToSource, './jest/jest.cjs.config.js'); const config = jestConfigPath || defaultConfig; - return this.jestAspect.createTester(config, jestModulePath || require.resolve('jest')); + const worker = this.getJestWorker(); + const tester = JestTester.create( + { + jest: jestModulePath || require.resolve('jest'), + config, + }, + { logger: this.logger, worker } + ); + + return tester; + } + + private getJestWorker() { + return this.worker.declareWorker('jest', jestWorkerPath); } /** @@ -182,14 +201,20 @@ export class ReactEnv const pathToSource = pathNormalizeToLinux(__dirname).replace('/dist', ''); const defaultConfig = join(pathToSource, './jest/jest.esm.config.js'); const config = jestConfigPath || defaultConfig; - return this.jestAspect.createTester(config, jestModulePath || require.resolve('jest')); + const worker = this.getJestWorker(); + return JestTester.create( + { + jest: jestModulePath || require.resolve('jest'), + config, + }, + { logger: this.logger, worker } + ); } /** * returns a component tester. */ getTester(jestConfigPath: string, jestModulePath?: string): Tester { - // return this.createEsmJestTester(jestConfigPath, jestModulePath); return this.createCjsJestTester(jestConfigPath, jestModulePath); } @@ -509,7 +534,16 @@ export class ReactEnv */ getBuildPipe(modifiers: GetBuildPipeModifiers = {}): BuildTask[] { const transformers: Function[] = modifiers?.tsModifier?.transformers || []; - return [this.createCjsCompilerTask(transformers, modifiers?.tsModifier?.module || ts), this.tester.task]; + const pathToSource = pathNormalizeToLinux(__dirname).replace('/dist', ''); + const jestConfigPath = + modifiers?.jestModifier?.transformers?.[0]() || join(pathToSource, './jest/jest.cjs.config.js'); + const jestPath = modifiers?.jestModifier?.module || require.resolve('jest'); + const worker = this.getJestWorker(); + const testerTask = JestTask.create( + { config: jestConfigPath, jest: jestPath }, + { logger: this.logger, worker, devFiles: this.devFiles } + ); + return [this.createCjsCompilerTask(transformers, modifiers?.tsModifier?.module || ts), testerTask]; } /** diff --git a/scopes/react/react/react.main.runtime.ts b/scopes/react/react/react.main.runtime.ts index 99c492a6f659..60585d531e41 100644 --- a/scopes/react/react/react.main.runtime.ts +++ b/scopes/react/react/react.main.runtime.ts @@ -1,3 +1,5 @@ +import type { DevFilesMain } from '@teambit/dev-files'; +import { DevFilesAspect } from '@teambit/dev-files'; import { Harmony } from '@teambit/harmony'; import { merge, omit } from 'lodash'; import { MainRuntime } from '@teambit/cli'; @@ -8,8 +10,6 @@ import { Component, ComponentID } from '@teambit/component'; import { EnvsAspect, EnvsMain, EnvTransformer, Environment, EnvContext } from '@teambit/envs'; import type { GraphqlMain } from '@teambit/graphql'; import { GraphqlAspect } from '@teambit/graphql'; -import type { JestMain } from '@teambit/jest'; -import { JestAspect } from '@teambit/jest'; import type { PkgMain, PackageJsonProps } from '@teambit/pkg'; import { SchemaMain, SchemaAspect } from '@teambit/schema'; import { PkgAspect } from '@teambit/pkg'; @@ -43,7 +43,6 @@ import { PrettierConfigTransformer } from '@teambit/defender.prettier.config-mut type ReactDeps = [ EnvsMain, - JestMain, TypescriptMain, CompilerMain, WebpackMain, @@ -56,7 +55,8 @@ type ReactDeps = [ DependencyResolverMain, LoggerMain, SchemaMain, - WorkerMain + WorkerMain, + DevFilesMain ]; export type ReactMainConfig = { @@ -312,8 +312,11 @@ export class ReactMain { * @param jestModulePath absolute path to jest */ overrideJestConfig(jestConfigPath: string, jestModulePath?: string) { + const buildTransformers = [() => jestConfigPath]; return this.envs.override({ getTester: () => this.reactEnv.getTester(jestConfigPath, jestModulePath), + getBuildPipe: () => + this.reactEnv.getBuildPipe({ jestModifier: { transformers: buildTransformers, module: jestModulePath } }), }); } @@ -400,7 +403,6 @@ export class ReactMain { static runtime = MainRuntime; static dependencies = [ EnvsAspect, - JestAspect, TypescriptAspect, CompilerAspect, WebpackAspect, @@ -414,12 +416,12 @@ export class ReactMain { LoggerAspect, SchemaAspect, WorkerAspect, + DevFilesAspect, ]; static async provider( [ envs, - jestAspect, tsAspect, compiler, webpack, @@ -433,6 +435,7 @@ export class ReactMain { loggerMain, schemaMain, workerMain, + devFilesMain, ]: ReactDeps, config: ReactMainConfig, slots, @@ -440,15 +443,16 @@ export class ReactMain { ) { const logger = loggerMain.createLogger(ReactAspect.id); const reactEnv = new ReactEnv( - jestAspect, tsAspect, compiler, webpack, workspace, + workerMain, pkg, tester, config, dependencyResolver, + devFilesMain, logger, CompilerAspect.id ); diff --git a/workspace.jsonc b/workspace.jsonc index dbe9670277ab..613824ec2e1f 100644 --- a/workspace.jsonc +++ b/workspace.jsonc @@ -23,7 +23,7 @@ "@dagrejs/dagre": "^1.1.2", "@graphql-modules/core": "0.7.17", "@graphql-tools/schema": "^10.0.0", - "@jest/test-result": "26.6.2", + "@jest/test-result": "29.3.1", "@mdx-js/mdx": "1.6.21", "@mdx-js/react": "1.6.22", "@monaco-editor/react": "4.4.6", @@ -149,6 +149,7 @@ "@teambit/defender.content.linter-overview": "1.95.0", "@teambit/defender.content.tester-overview": "1.95.0", "@teambit/defender.eslint-linter": "^1.0.35", + "@teambit/defender.jest-tester": "^2.0.4", "@teambit/defender.prettier-formatter": "1.0.12", "@teambit/defender.ui.test-compare-section": "^0.0.100", "@teambit/defender.ui.test-loader": "^0.0.504", @@ -261,6 +262,7 @@ "@teambit/react.instructions.react-native.adding-tests": "0.0.1", "@teambit/react.instructions.react.adding-compositions": "0.0.6", "@teambit/react.instructions.react.adding-tests": "0.0.6", + "@teambit/react.jest.react-jest": "^1.0.22", "@teambit/react.rendering.ssr": "0.0.3", "@teambit/react.ui.component-highlighter": "0.2.2", "@teambit/react.webpack.react-webpack": "^1.0.25", @@ -274,7 +276,7 @@ "@teambit/scopes.scope-descriptor": "^0.0.24", "@teambit/scopes.scope-id": "^0.0.7", "@teambit/semantics.entities.semantic-schema": "^0.0.65", - "@teambit/tests-results": "^1.0.4", + "@teambit/tests-results": "^1.0.5", "@teambit/typescript.typescript-compiler": "^2.0.42", "@teambit/ui-foundation.ui.constants.z-indexes": "^0.0.504", "@teambit/ui-foundation.ui.corner": "^0.0.520", @@ -319,8 +321,8 @@ "@teambit/workspace.ui.empty-workspace": "^0.0.508", "@teambit/workspace.ui.load-preview": "^0.0.504", "@teambit/workspace.ui.status": "^0.0.504", - "@testing-library/jest-dom": "5.16.2", - "@testing-library/jest-native": "4.0.4", + "@testing-library/jest-dom": "5.16.5", + "@testing-library/jest-native": "5.4.3", "@testing-library/react": "12.1.5", "@tippyjs/react": "4.2.0", "@types/archiver": "5.3.1", @@ -369,8 +371,6 @@ "archy": "1.0.0", "assert": "^2.1.0", "aws-sdk": "2.756.0", - "babel-jest": "27.5.1", - "babel-preset-jest": "27.5.1", "body-parser": "1.19.0", "buffer": "6.0.3", "camelcase": "6.2.0", @@ -419,12 +419,9 @@ "is-binary-path": "2.1.0", "is-builtin-module": "3.1.0", "is-primitive": "3.0.1", - "jest": { - "version": "27.5.1", - "preserve": true - }, - "jest-message-util": "27.5.1", - "jest-watcher": "27.5.1", + "jest": "29.3.1", + "jest-message-util": "29.3.1", + "jest-watcher": "29.7.0", "json-formatter-js": "2.3.4", "junit-report-builder": "3.0.1", "less": "^4.1.1",