diff --git a/.npmignore b/.npmignore index 3c97ffe..3aee29f 100644 --- a/.npmignore +++ b/.npmignore @@ -9,6 +9,7 @@ yarn-error.log .vscode coverage lib/*.test.js +lib/test-utils.js yarn.lock craco-less-*.tgz .github/ diff --git a/README.md b/README.md index e8e383d..f569d0b 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ you should use the [`craco-antd`](https://github.com/DocSpring/craco-antd) plugi ## Installation -First, follow the [`craco` Installation Instructions](https://github.com/sharegate/craco/blob/master/packages/craco/README.md##installation) to install the `craco` package, create a `craco.config.js` file, and modify the scripts in your `package.json`. +First, follow the [`craco` Installation Instructions](https://github.com/gsoft-inc/craco/blob/master/packages/craco/README.md#installation) to install the `craco` package, create a `craco.config.js` file, and modify the scripts in your `package.json`. Then install `craco-less`: diff --git a/lib/craco-less.js b/lib/craco-less.js index 2089410..49af3e9 100644 --- a/lib/craco-less.js +++ b/lib/craco-less.js @@ -1,23 +1,21 @@ const path = require("path"); const { deepClone, styleRuleByName } = require("./utils"); +const { loaderByName, throwUnexpectedConfigError } = require("@craco/craco"); const lessRegex = /\.less$/; const lessModuleRegex = /\.module\.less$/; -const overrideWebpackConfig = ({ context, webpackConfig, pluginOptions }) => { - const { loaderByName, throwUnexpectedConfigError } = require("@craco/craco"); +const throwError = (message, githubIssueQuery) => + throwUnexpectedConfigError({ + packageName: "craco-less", + githubRepo: "DocSpring/craco-less", + message, + githubIssueQuery, + }); +const overrideWebpackConfig = ({ context, webpackConfig, pluginOptions }) => { // This is mocked in Windows tests const pathSep = module.exports.pathSep; - - const throwError = (message, githubIssueQuery) => - throwUnexpectedConfigError({ - packageName: "craco-less", - githubRepo: "DocSpring/craco-less", - message, - githubIssueQuery, - }); - pluginOptions = pluginOptions || {}; const createLessRule = ({ baseRule, overrideRule }) => { @@ -174,8 +172,44 @@ const overrideWebpackConfig = ({ context, webpackConfig, pluginOptions }) => { return webpackConfig; }; +const overrideJestConfig = ({ context, jestConfig }) => { + const moduleNameMapper = jestConfig.moduleNameMapper; + const cssModulesPattern = Object.keys(moduleNameMapper).find((p) => + p.match(/\\\.module\\\.\(.*?css.*?\)/) + ); + + if (!cssModulesPattern) { + throwError( + `Can't find CSS Modules pattern under moduleNameMapper in the ${context.env} jest config!`, + "jest+moduleNameMapper+css" + ); + } + + moduleNameMapper[cssModulesPattern.replace("css", "css|less")] = + moduleNameMapper[cssModulesPattern]; + delete moduleNameMapper[cssModulesPattern]; + + const transformIgnorePatterns = jestConfig.transformIgnorePatterns; + const cssModulesPatternIndex = transformIgnorePatterns.findIndex((p) => + p.match(/\\\.module\\\.\(.*?css.*?\)/) + ); + if (cssModulesPatternIndex === -1) { + throwError( + `Can't find CSS Modules pattern under transformIgnorePatterns in the ${context.env} jest config!`, + "jest+transformIgnorePatterns+css" + ); + } + + transformIgnorePatterns[cssModulesPatternIndex] = transformIgnorePatterns[ + cssModulesPatternIndex + ].replace("css", "css|less"); + + return jestConfig; +}; + // pathSep is mocked in Windows tests module.exports = { overrideWebpackConfig, + overrideJestConfig, pathSep: path.sep, }; diff --git a/lib/craco-less.test.test.js b/lib/craco-less.test.test.js new file mode 100644 index 0000000..d0c90a6 --- /dev/null +++ b/lib/craco-less.test.test.js @@ -0,0 +1,86 @@ +const { createJestConfig } = require("@craco/craco"); +const { processCracoConfig } = require("@craco/craco/lib/config"); +const { applyJestConfigPlugins } = require("@craco/craco/lib/features/plugins"); +const clone = require("clone"); +const CracoLessPlugin = require("./craco-less"); +const { getCracoContext } = require("./test-utils"); + +process.env.NODE_ENV = "test"; + +const baseCracoConfig = {}; +const cracoContext = getCracoContext(baseCracoConfig); +const originalJestConfig = createJestConfig(baseCracoConfig); + +const overrideJestConfig = (callerCracoConfig, jestConfig) => { + return applyJestConfigPlugins( + processCracoConfig({ + ...baseCracoConfig, + ...callerCracoConfig, + }), + jestConfig, + cracoContext + ); +}; + +let jestConfig; +beforeEach(() => { + // deep clone the object before each test. + jestConfig = clone(originalJestConfig); +}); + +test("the jest config is modified correctly", () => { + jestConfig = overrideJestConfig( + { + plugins: [{ plugin: CracoLessPlugin }], + }, + jestConfig + ); + + const moduleNameMapper = jestConfig.moduleNameMapper; + expect(moduleNameMapper["^.+\\.module\\.(css|sass|scss)$"]).toBeUndefined(); + expect(moduleNameMapper["^.+\\.module\\.(css|less|sass|scss)$"]).toEqual( + "identity-obj-proxy" + ); + + const transformIgnorePatterns = jestConfig.transformIgnorePatterns; + expect(transformIgnorePatterns[1]).toEqual( + "^.+\\.module\\.(css|less|sass|scss)$" + ); +}); + +test("throws an error when we can't find CSS Modules pattern under moduleNameMapper in the jest config", () => { + delete jestConfig.moduleNameMapper["^.+\\.module\\.(css|sass|scss)$"]; + + const runTest = () => { + overrideJestConfig( + { + plugins: [{ plugin: CracoLessPlugin }], + }, + jestConfig + ); + }; + + expect(runTest).toThrowError( + /^Can't find CSS Modules pattern under moduleNameMapper in the test jest config!/ + ); +}); + +test("throws an error when we can't find CSS Modules pattern under transformIgnorePatterns in the jest config", () => { + jestConfig.transformIgnorePatterns = + jestConfig.transformIgnorePatterns.filter( + (e) => e !== "^.+\\.module\\.(css|sass|scss)$" + ); + + const runTest = () => { + overrideJestConfig( + { + plugins: [{ plugin: CracoLessPlugin }], + }, + jestConfig + ); + }; + + expect(runTest).toThrowError( + /^Can't find CSS Modules pattern under transformIgnorePatterns in the test jest config!/ + ); +}); diff --git a/lib/test-utils.js b/lib/test-utils.js new file mode 100644 index 0000000..62acf86 --- /dev/null +++ b/lib/test-utils.js @@ -0,0 +1,13 @@ +const { processCracoConfig } = require("@craco/craco/lib/config"); +const { getCraPaths } = require("@craco/craco/lib/cra"); + +const getCracoContext = (callerCracoConfig, env = process.env.NODE_ENV) => { + const context = { env }; + const cracoConfig = processCracoConfig(callerCracoConfig, { env }); + context.paths = getCraPaths(cracoConfig); + return context; +}; + +module.exports = { + getCracoContext, +};