From f19b2760130b65d5e3aa02dbb556dd4a9dbd7eb3 Mon Sep 17 00:00:00 2001 From: Judah Meek Date: Thu, 29 Aug 2024 03:36:17 -0500 Subject: [PATCH] Add logic to sass rule conditional on sass-loader version (#508) * mock moduleExists now that we've mocked css-loader --- __mocks__/nonexistent/package.json | 4 ++++ __mocks__/sass-loader/package.json | 4 ++++ jest.config.js | 3 ++- package/rules/sass.js | 14 ++++++----- package/utils/helpers.js | 10 +++++++- test/package/development.test.js | 9 ++++++++ test/package/environments/base.test.js | 9 ++++++++ test/package/environments/development.test.js | 9 ++++++++ test/package/environments/production.test.js | 9 ++++++++ test/package/helpers.test.js | 11 +++++++++ test/package/index.test.js | 9 ++++++++ test/package/production.test.js | 9 ++++++++ test/package/rules/index.test.js | 9 ++++++++ test/package/rules/sass.test.js | 23 +++++++++++++++++++ test/package/rules/sass1.test.js | 23 +++++++++++++++++++ test/package/staging.test.js | 9 ++++++++ test/package/test.test.js | 9 ++++++++ test/resolver.js | 13 +++++++++++ 18 files changed, 178 insertions(+), 8 deletions(-) create mode 100644 __mocks__/nonexistent/package.json create mode 100644 __mocks__/sass-loader/package.json create mode 100644 test/package/helpers.test.js create mode 100644 test/package/rules/sass.test.js create mode 100644 test/package/rules/sass1.test.js create mode 100644 test/resolver.js diff --git a/__mocks__/nonexistent/package.json b/__mocks__/nonexistent/package.json new file mode 100644 index 00000000..0e303acd --- /dev/null +++ b/__mocks__/nonexistent/package.json @@ -0,0 +1,4 @@ +{ + "main": "./wat", + "version": "12.0.0" +} diff --git a/__mocks__/sass-loader/package.json b/__mocks__/sass-loader/package.json new file mode 100644 index 00000000..e926c306 --- /dev/null +++ b/__mocks__/sass-loader/package.json @@ -0,0 +1,4 @@ +{ + "main": "./lib/api.js", + "version": "16.56.81" +} diff --git a/jest.config.js b/jest.config.js index b2c9c58a..a777ee41 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,4 +1,5 @@ module.exports = { roots: ["/test"], - testPathIgnorePatterns: ["/__fixtures__/", "/__utils__/"] + testPathIgnorePatterns: ["/__fixtures__/", "/__utils__/"], + resolver: "/test/resolver" } diff --git a/package/rules/sass.js b/package/rules/sass.js index 4d71234a..a620d679 100644 --- a/package/rules/sass.js +++ b/package/rules/sass.js @@ -1,16 +1,18 @@ /* eslint global-require: 0 */ const getStyleRule = require("../utils/getStyleRule") -const { canProcess } = require("../utils/helpers") -const { additional_paths: includePaths } = require("../config") +const { canProcess, packageMajorVersion } = require("../utils/helpers") +const { additional_paths: extraPaths } = require("../config") -module.exports = canProcess("sass-loader", (resolvedPath) => - getStyleRule(/\.(scss|sass)(\.erb)?$/i, [ +module.exports = canProcess("sass-loader", (resolvedPath) => { + const optionKey = + packageMajorVersion("sass-loader") > 15 ? "loadPaths" : "includePaths" + return getStyleRule(/\.(scss|sass)(\.erb)?$/i, [ { loader: resolvedPath, options: { - sassOptions: { includePaths } + sassOptions: { [optionKey]: extraPaths } } } ]) -) +}) diff --git a/package/utils/helpers.js b/package/utils/helpers.js index d550eb3f..759178a9 100644 --- a/package/utils/helpers.js +++ b/package/utils/helpers.js @@ -41,10 +41,18 @@ const loaderMatches = (configLoader, loaderToCheck, fn) => { return fn() } +const packageMajorVersion = (packageName) => { + // eslint-disable-next-line import/no-dynamic-require + const packageJsonPath = require.resolve(`${packageName}/package.json`) + // eslint-disable-next-line import/no-dynamic-require, global-require + return require(packageJsonPath).version.match(/^\d+/)[0] +} + module.exports = { isBoolean, ensureTrailingSlash, canProcess, moduleExists, - loaderMatches + loaderMatches, + packageMajorVersion } diff --git a/test/package/development.test.js b/test/package/development.test.js index 9df9db75..c17909df 100644 --- a/test/package/development.test.js +++ b/test/package/development.test.js @@ -4,6 +4,15 @@ const { chdirTestApp, resetEnv } = require("../helpers") const rootPath = process.cwd() chdirTestApp() +jest.mock("../../package/utils/helpers", () => { + const original = jest.requireActual("../../package/utils/helpers") + const moduleExists = () => false + return { + ...original, + moduleExists + } +}) + describe("Development environment", () => { beforeEach(() => jest.resetModules() && resetEnv()) afterAll(() => process.chdir(rootPath)) diff --git a/test/package/environments/base.test.js b/test/package/environments/base.test.js index 585cf30c..2c9a6bb2 100644 --- a/test/package/environments/base.test.js +++ b/test/package/environments/base.test.js @@ -10,6 +10,15 @@ chdirTestApp() const baseConfig = require("../../../package/environments/base") const config = require("../../../package/config") +jest.mock("../../../package/utils/helpers", () => { + const original = jest.requireActual("../../../package/utils/helpers") + const moduleExists = () => false + return { + ...original, + moduleExists + } +}) + describe("Base config", () => { beforeEach(() => jest.resetModules() && resetEnv()) afterAll(() => process.chdir(rootPath)) diff --git a/test/package/environments/development.test.js b/test/package/environments/development.test.js index db1da737..7e29a8c9 100644 --- a/test/package/environments/development.test.js +++ b/test/package/environments/development.test.js @@ -3,6 +3,15 @@ const { chdirTestApp, resetEnv } = require("../../helpers") const rootPath = process.cwd() chdirTestApp() +jest.mock("../../../package/utils/helpers", () => { + const original = jest.requireActual("../../../package/utils/helpers") + const moduleExists = () => false + return { + ...original, + moduleExists + } +}) + describe("Development specific config", () => { beforeEach(() => { jest.resetModules() diff --git a/test/package/environments/production.test.js b/test/package/environments/production.test.js index dc1d8cfa..4cd4fb3b 100644 --- a/test/package/environments/production.test.js +++ b/test/package/environments/production.test.js @@ -3,6 +3,15 @@ const { chdirTestApp, resetEnv } = require("../../helpers") const rootPath = process.cwd() chdirTestApp() +jest.mock("../../../package/utils/helpers", () => { + const original = jest.requireActual("../../../package/utils/helpers") + const moduleExists = () => false + return { + ...original, + moduleExists + } +}) + describe("Production specific config", () => { beforeEach(() => { jest.resetModules() diff --git a/test/package/helpers.test.js b/test/package/helpers.test.js new file mode 100644 index 00000000..b25415f2 --- /dev/null +++ b/test/package/helpers.test.js @@ -0,0 +1,11 @@ +const { packageMajorVersion } = require("../../package/utils/helpers") + +describe("packageMajorVersion", () => { + test("should find that sass-loader is v16", () => { + expect(packageMajorVersion("sass-loader")).toBe("16") + }) + + test("should find that nonexistent is v12", () => { + expect(packageMajorVersion("nonexistent")).toBe("12") + }) +}) diff --git a/test/package/index.test.js b/test/package/index.test.js index b12efb4a..e13ec64b 100644 --- a/test/package/index.test.js +++ b/test/package/index.test.js @@ -1,5 +1,14 @@ const index = require("../../package/index") +jest.mock("../../package/utils/helpers", () => { + const original = jest.requireActual("../../package/utils/helpers") + const moduleExists = () => false + return { + ...original, + moduleExists + } +}) + describe("index", () => { test("exports webpack-merge v5 functions", () => { expect(index.merge).toBeInstanceOf(Function) diff --git a/test/package/production.test.js b/test/package/production.test.js index 0db1c753..73b1f11c 100644 --- a/test/package/production.test.js +++ b/test/package/production.test.js @@ -4,6 +4,15 @@ const { chdirTestApp } = require("../helpers") const rootPath = process.cwd() chdirTestApp() +jest.mock("../../package/utils/helpers", () => { + const original = jest.requireActual("../../package/utils/helpers") + const moduleExists = () => false + return { + ...original, + moduleExists + } +}) + describe("Production environment", () => { afterAll(() => process.chdir(rootPath)) diff --git a/test/package/rules/index.test.js b/test/package/rules/index.test.js index 32e62330..98feeca5 100644 --- a/test/package/rules/index.test.js +++ b/test/package/rules/index.test.js @@ -1,5 +1,14 @@ const rules = require("../../../package/rules/index") +jest.mock("../../../package/utils/helpers", () => { + const original = jest.requireActual("../../../package/utils/helpers") + const moduleExists = () => false + return { + ...original, + moduleExists + } +}) + describe("index", () => { test("rule tests are regexes", () => { rules.forEach((rule) => expect(rule.test instanceof RegExp).toBe(true)) diff --git a/test/package/rules/sass.test.js b/test/package/rules/sass.test.js new file mode 100644 index 00000000..85ef50a7 --- /dev/null +++ b/test/package/rules/sass.test.js @@ -0,0 +1,23 @@ +const sass = require("../../../package/rules/sass") + +jest.mock("../../../package/utils/helpers", () => { + const original = jest.requireActual("../../../package/utils/helpers") + const canProcess = (rule, fn) => { + return fn("This path was mocked") + } + const packageMajorVersion = () => "15" + return { + ...original, + canProcess, + packageMajorVersion + } +}) + +jest.mock("../../../package/utils/inliningCss", () => true) + +describe("sass rule", () => { + test("contains loadPaths as the sassOptions key if sass-loader is v15 or earlier", () => { + expect(typeof sass.use[3].options.sassOptions.includePaths).toBe("object") + expect(typeof sass.use[3].options.sassOptions.loadPaths).toBe("undefined") + }) +}) diff --git a/test/package/rules/sass1.test.js b/test/package/rules/sass1.test.js new file mode 100644 index 00000000..4de2546a --- /dev/null +++ b/test/package/rules/sass1.test.js @@ -0,0 +1,23 @@ +const sass = require("../../../package/rules/sass") + +jest.mock("../../../package/utils/helpers", () => { + const original = jest.requireActual("../../../package/utils/helpers") + const canProcess = (rule, fn) => { + return fn("This path was mocked") + } + return { + ...original, + canProcess + } +}) + +jest.mock("../../../package/utils/inliningCss", () => true) + +describe("sass rule", () => { + test("contains loadPaths as the sassOptions key if sass-loader is v15 or earlier", () => { + expect(typeof sass.use[3].options.sassOptions.includePaths).toBe( + "undefined" + ) + expect(typeof sass.use[3].options.sassOptions.loadPaths).toBe("object") + }) +}) diff --git a/test/package/staging.test.js b/test/package/staging.test.js index 55dd1936..f6adf496 100644 --- a/test/package/staging.test.js +++ b/test/package/staging.test.js @@ -4,6 +4,15 @@ const { chdirTestApp } = require("../helpers") const rootPath = process.cwd() chdirTestApp() +jest.mock("../../package/utils/helpers", () => { + const original = jest.requireActual("../../package/utils/helpers") + const moduleExists = () => false + return { + ...original, + moduleExists + } +}) + describe("Custom environment", () => { afterAll(() => process.chdir(rootPath)) diff --git a/test/package/test.test.js b/test/package/test.test.js index 2ddfe75d..53754826 100644 --- a/test/package/test.test.js +++ b/test/package/test.test.js @@ -4,6 +4,15 @@ const { chdirTestApp } = require("../helpers") const rootPath = process.cwd() chdirTestApp() +jest.mock("../../package/utils/helpers", () => { + const original = jest.requireActual("../../package/utils/helpers") + const moduleExists = () => false + return { + ...original, + moduleExists + } +}) + describe("Test environment", () => { afterAll(() => process.chdir(rootPath)) diff --git a/test/resolver.js b/test/resolver.js new file mode 100644 index 00000000..c0d50017 --- /dev/null +++ b/test/resolver.js @@ -0,0 +1,13 @@ +const mapping = { + "css-loader": "this path was mocked", + "sass-loader/package.json": "../../__mocks__/sass-loader/package.json", + "nonexistent/package.json": "../../__mocks__/nonexistent/package.json" +} + +function resolver(module, options) { + // If the path corresponds to a key in the mapping object, returns the fakely resolved path + // otherwise it calls the Jest's default resolver + return mapping[module] || options.defaultResolver(module, options) +} + +module.exports = resolver