From 0d9b5b422a9e18cc6391fa119abe41b7d384c154 Mon Sep 17 00:00:00 2001
From: Nickolas Oliver <Nickolas.Oliver@aexp.com>
Date: Mon, 12 Jun 2023 10:21:48 -0700
Subject: [PATCH] fix(one-app-dev-bundler): avoid default export of sass
 accidentally removed in 1.63.0 through 1.63.3, will be removed in 2.x
 https://github.com/sass/dart-sass/issues/2008

---
 .../esbuild/plugins/styles-loader.spec.js     | 35 ++++++++++++-------
 .../esbuild/plugins/styles-loader.js          |  4 +--
 2 files changed, 24 insertions(+), 15 deletions(-)

diff --git a/packages/one-app-dev-bundler/__tests__/esbuild/plugins/styles-loader.spec.js b/packages/one-app-dev-bundler/__tests__/esbuild/plugins/styles-loader.spec.js
index 3b90bb41..1c893611 100644
--- a/packages/one-app-dev-bundler/__tests__/esbuild/plugins/styles-loader.spec.js
+++ b/packages/one-app-dev-bundler/__tests__/esbuild/plugins/styles-loader.spec.js
@@ -15,7 +15,7 @@
  */
 
 import glob from 'glob-all';
-import sass from 'sass';
+import { compile as sassCompile } from 'sass';
 import stylesLoader from '../../../esbuild/plugins/styles-loader';
 import { runSetupAndGetLifeHooks, runOnLoadHook } from './__plugin-testing-utils__';
 import {
@@ -29,7 +29,16 @@ jest.mock('glob-all');
 
 jest.mock('cssnano');
 
-jest.spyOn(sass, 'compile');
+// sass has different loaders for CJS and ESM, the latter does not have a "default" export
+// making `import sass from 'sass';` throw an error
+// Jest is still working on ESM mocking https://jestjs.io/docs/ecmascript-modules#module-mocking-in-esm
+// so there is a divergance from this test setup and sass versions: update this setup once the jest
+// API is stable
+jest.mock('sass', () => {
+  const sass = jest.requireActual('sass');
+  jest.spyOn(sass, 'compile');
+  return sass;
+});
 
 const mockNodeEnv = (env) => {
   let oldEnv;
@@ -93,8 +102,8 @@ describe('Esbuild plugin stylesLoader', () => {
             { mockFileName, mockFileContent }
           );
 
-          expect(sass.compile).toHaveBeenCalledTimes(1);
-          expect(sass.compile).toHaveBeenCalledWith(`mock/path/to/file/${mockFileName}`, { loadPaths: ['./node_modules'] });
+          expect(sassCompile).toHaveBeenCalledTimes(1);
+          expect(sassCompile).toHaveBeenCalledWith(`mock/path/to/file/${mockFileName}`, { loadPaths: ['./node_modules'] });
 
           expect(loader).toEqual('js');
           expect(contents).toMatchInlineSnapshot(`
@@ -140,7 +149,7 @@ body > p {
             { mockFileName, mockFileContent }
           );
 
-          expect(sass.compile).toHaveBeenCalledTimes(0);
+          expect(sassCompile).toHaveBeenCalledTimes(0);
           expect(loader).toEqual('js');
           expect(contents).toMatchInlineSnapshot(`
 "const digest = '83279c4025e8b1107c3f376acaaac5656a3b68d0066ab70f2ceeb3c065a5751f';
@@ -186,8 +195,8 @@ body > p {
           { mockFileName, mockFileContent }
         );
 
-        expect(sass.compile).toHaveBeenCalledTimes(1);
-        expect(sass.compile).toHaveBeenCalledWith(`mock/path/to/file/${mockFileName}`, { loadPaths: ['./node_modules'] });
+        expect(sassCompile).toHaveBeenCalledTimes(1);
+        expect(sassCompile).toHaveBeenCalledWith(`mock/path/to/file/${mockFileName}`, { loadPaths: ['./node_modules'] });
 
         expect(loader).toEqual('js');
         expect(contents).toMatchInlineSnapshot(`
@@ -227,7 +236,7 @@ body > p {
           { mockFileName, mockFileContent }
         );
 
-        expect(sass.compile).toHaveBeenCalledTimes(0);
+        expect(sassCompile).toHaveBeenCalledTimes(0);
         expect(loader).toEqual('js');
         expect(contents).toMatchInlineSnapshot(`
 "const digest = '83279c4025e8b1107c3f376acaaac5656a3b68d0066ab70f2ceeb3c065a5751f';
@@ -294,7 +303,7 @@ export { css, digest };"
           additionalMockedFiles
         );
 
-        expect(sass.compile).toHaveBeenCalledTimes(0);
+        expect(sassCompile).toHaveBeenCalledTimes(0);
         expect(loader).toEqual('js');
         expect(contents).toMatchInlineSnapshot(`
 "const digest = '786f696ae19422021e0f17df7c6dd6eb43f92c9c101f7d0649b341165dda1b31';
@@ -366,7 +375,7 @@ export { css, digest };"
           additionalMockedFiles
         );
 
-        expect(sass.compile).toHaveBeenCalledTimes(0);
+        expect(sassCompile).toHaveBeenCalledTimes(0);
         expect(loader).toEqual('js');
         expect(contents).toMatchInlineSnapshot(`
 "const digest = '786f696ae19422021e0f17df7c6dd6eb43f92c9c101f7d0649b341165dda1b31';
@@ -418,8 +427,8 @@ export { css, digest };"
           { mockFileName, mockFileContent }
         );
 
-        expect(sass.compile).toHaveBeenCalledTimes(1);
-        expect(sass.compile).toHaveBeenCalledWith(`mock/path/to/file/${mockFileName}`, { loadPaths: ['./node_modules'] });
+        expect(sassCompile).toHaveBeenCalledTimes(1);
+        expect(sassCompile).toHaveBeenCalledWith(`mock/path/to/file/${mockFileName}`, { loadPaths: ['./node_modules'] });
 
         expect(loader).toEqual('js');
         expect(contents).toMatchInlineSnapshot(`
@@ -469,7 +478,7 @@ body > p {
           { mockFileName, mockFileContent }
         );
 
-        expect(sass.compile).toHaveBeenCalledTimes(0);
+        expect(sassCompile).toHaveBeenCalledTimes(0);
         expect(loader).toEqual('js');
         expect(contents).toMatchInlineSnapshot(`
 "const digest = '83279c4025e8b1107c3f376acaaac5656a3b68d0066ab70f2ceeb3c065a5751f';
diff --git a/packages/one-app-dev-bundler/esbuild/plugins/styles-loader.js b/packages/one-app-dev-bundler/esbuild/plugins/styles-loader.js
index 8941072f..c04d5f8b 100644
--- a/packages/one-app-dev-bundler/esbuild/plugins/styles-loader.js
+++ b/packages/one-app-dev-bundler/esbuild/plugins/styles-loader.js
@@ -14,7 +14,7 @@
  * permissions and limitations under the License.
  */
 
-import sass from 'sass';
+import { compile as sassCompile } from 'sass';
 import postcss from 'postcss';
 import cssModules from 'postcss-modules';
 import crypto from 'crypto';
@@ -40,7 +40,7 @@ const stylesLoader = (cssModulesOptions = {}, { bundleType } = {}) => ({
       // Compile scss to css
       let cssContent;
       if (args.path.endsWith('scss')) {
-        cssContent = sass.compile(args.path, { loadPaths: ['./node_modules'] }).css.toString();
+        cssContent = sassCompile(args.path, { loadPaths: ['./node_modules'] }).css.toString();
       } else {
         cssContent = await fs.promises.readFile(args.path, 'utf8');
       }