diff --git a/packages/infrastructure/jest/README.md b/packages/infrastructure/jest/README.md new file mode 100644 index 0000000000..6e31d44255 --- /dev/null +++ b/packages/infrastructure/jest/README.md @@ -0,0 +1,55 @@ +# @k8slens/jest + +This package contains jest configurations and scripts for Lens packages. + +## Install + +``` +$ npm install @k8slens/jest +``` + +## Features + +### Package configurations +Shared configurations for minimal duplication. + +#### Node + +**./packages//jest.config.js** +```javascript +module.exports = require("@k8slens/jest").monorepoPackageConfig(__dirname).configForNode; +``` + +#### React + +**./packages//jest.config.js** +```javascript +module.exports = require("@k8slens/jest").monorepoPackageConfig(__dirname).configForReact; +``` + +### Root configuration +You may want to enable testing of packages using single command from root level. This allows you to utilize `jest --watch` between all packages. + + +**./jest.config.js** +```javascript +module.exports = require("@k8slens/jest").monorepoRootConfig(__dirname); +``` + +### Scripts + +#### lens-test +Test package with coverage enforcement. Automatically opens coverage report in case of failure. + +**./packages//package.json** +```json +{ + "scripts": { + "test": "lens-test" + } +} +``` + + + + diff --git a/packages/infrastructure/jest/bin/test.sh b/packages/infrastructure/jest/bin/test.sh new file mode 100755 index 0000000000..2dd03f459a --- /dev/null +++ b/packages/infrastructure/jest/bin/test.sh @@ -0,0 +1,6 @@ +jest --coverage --runInBand +result=$? + +[ $result != 0 ] && [ -v $CI ] && open ./coverage/lcov-report/index.html + +exit $result diff --git a/packages/infrastructure/jest/index.js b/packages/infrastructure/jest/index.js new file mode 100644 index 0000000000..c985d69a0e --- /dev/null +++ b/packages/infrastructure/jest/index.js @@ -0,0 +1,4 @@ +module.exports = { + monorepoRootConfig: require("./monorepo-root-config"), + monorepoPackageConfig: require("./monorepo-package-config"), +}; diff --git a/packages/infrastructure/jest/monorepo-package-config.js b/packages/infrastructure/jest/monorepo-package-config.js new file mode 100644 index 0000000000..ed00bc2355 --- /dev/null +++ b/packages/infrastructure/jest/monorepo-package-config.js @@ -0,0 +1,56 @@ +module.exports = (rootDir) => { + const shared = { + transform: { + "^.+\\.(t|j)sx?$": ["@swc/jest", { cwd: rootDir }], + }, + + clearMocks: true, + coverageDirectory: "coverage", + coverageProvider: "v8", + coverageReporters: ["lcov"], + collectCoverage: true, + testMatch: ["**/?(*.)+(test).{js,ts,tsx}"], + watchPathIgnorePatterns: ["/node_modules/", "/coverage/", "/build/"], + + collectCoverageFrom: [ + "/src/**/*.{ts,tsx}", + "!/src/**/*.no-coverage.ts", + ], + + moduleNameMapper: { + "^electron$": "identity-obj-proxy", + }, + + // Todo: restore threshold after initial hurry. + // coverageThreshold: { + // global: { + // branches: 100, + // functions: 100, + // lines: 100, + // statements: 100, + // }, + // }, + }; + + const configForNode = { + ...shared, + testEnvironment: "node", + }; + + const configForReact = { + ...shared, + + moduleNameMapper: { + "\\.(css|scss)$": "identity-obj-proxy", + ...shared.moduleNameMapper, + }, + + testEnvironment: "jsdom", + setupFilesAfterEnv: [`${__dirname}/setup-react-tests.ts`], + }; + + return { + configForReact, + configForNode, + }; +}; diff --git a/packages/infrastructure/jest/monorepo-root-config.js b/packages/infrastructure/jest/monorepo-root-config.js new file mode 100644 index 0000000000..12b4973928 --- /dev/null +++ b/packages/infrastructure/jest/monorepo-root-config.js @@ -0,0 +1,73 @@ +const path = require("path"); +const glob = require("glob"); +const { omit } = require("lodash/fp"); + +const getProjectColor = (projectNumber) => { + const colors = [ + "red", + "green", + "yellow", + "magenta", + "cyan", + "white", + "redBright", + "greenBright", + "yellowBright", + "blueBright", + "magentaBright", + "cyanBright", + "whiteBright", + ]; + + return colors[projectNumber % colors.length]; +}; + +const nonMultiProjectConfigs = [ + "coverageDirectory", + "coverageProvider", + "coverageReporters", + "collectCoverage", + "collectCoverageFrom", + "coveragePathIgnorePatterns", + "coverageThreshold", +]; + +const toJestMultiProjectConfig = ( + { packageJson, jestConfig, packagePath }, + projectNumber +) => ({ + rootDir: packagePath, + + displayName: { + name: packageJson.name, + color: getProjectColor(projectNumber), + }, + + ...omit(nonMultiProjectConfigs, jestConfig), +}); + +const getJestConfigsAndPackageJsons = (rootDir) => { + const packageJsonPaths = glob + .sync(`${rootDir}/packages/**/jest.config.js`, { + ignore: "./**/node_modules/**/*", + }) + .map((filePath) => path.dirname(filePath)); + + return packageJsonPaths.map((packagePath) => ({ + packagePath, + packageJson: require(`${packagePath}/package.json`), + jestConfig: require(`${packagePath}/jest.config.js`), + })); +}; + +module.exports = (rootDir) => ({ + projects: getJestConfigsAndPackageJsons(rootDir).map( + toJestMultiProjectConfig + ), + + watchPlugins: [ + "jest-watch-typeahead/filename", + "jest-watch-typeahead/testname", + "jest-watch-select-projects", + ], +}); diff --git a/packages/infrastructure/jest/package.json b/packages/infrastructure/jest/package.json new file mode 100644 index 0000000000..cd28e28a57 --- /dev/null +++ b/packages/infrastructure/jest/package.json @@ -0,0 +1,35 @@ +{ + "name": "@k8slens/jest", + "private": false, + "version": "0.0.1", + "description": "Jest configuration and scripts for Lens packages.", + "type": "commonjs", + "repository": { + "type": "git", + "url": "git+https://github.com/lensapp/monorepo.git" + }, + "main": "index.js", + "author": { + "name": "OpenLens Authors", + "email": "info@k8slens.dev" + }, + "license": "MIT", + "homepage": "https://github.com/lensapp/lens", + "bin": { + "lens-test": "bin/test.sh" + }, + "dependencies": { + "@swc/core": "^1.3.20", + "@swc/jest": "^0.2.23", + "@testing-library/jest-dom": "^5.16.5", + "@testing-library/react": "^13.4.0", + "@types/jest": "^29.2.2", + "identity-obj-proxy": "^3.0.0", + "jest": "^29.3.1", + "jest-environment-jsdom": "^29.3.1", + "jest-watch-select-projects": "^2.0.0", + "jest-watch-typeahead": "^2.2.1", + "lodash": "^4.17.21", + "ts-jest": "^29.0.3" + } +} diff --git a/packages/infrastructure/jest/setup-react-tests.ts b/packages/infrastructure/jest/setup-react-tests.ts new file mode 100644 index 0000000000..d0de870dc5 --- /dev/null +++ b/packages/infrastructure/jest/setup-react-tests.ts @@ -0,0 +1 @@ +import "@testing-library/jest-dom";