Add tests for generate_css_js_files script

No functional changes here - but we will be making changes in the future
to this script, so I think adding a few tests is a good idea.

The changes to the source code are purely to allow the relevant function
to be tested easily, and there are no actual output changes here.

Bug: 1399763
Change-Id: I7fec01f62ea2b034b175071aa1dd92a9d3df51b6
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/4092303
Commit-Queue: Alex Rudenko <alexrudenko@chromium.org>
Commit-Queue: Jack Franklin <jacktfranklin@chromium.org>
Auto-Submit: Jack Franklin <jacktfranklin@chromium.org>
Reviewed-by: Alex Rudenko <alexrudenko@chromium.org>
diff --git a/scripts/build/generate_css_js_files.js b/scripts/build/generate_css_js_files.js
index 52ccca3..f87f6d5 100644
--- a/scripts/build/generate_css_js_files.js
+++ b/scripts/build/generate_css_js_files.js
@@ -5,20 +5,14 @@
 const path = require('path');
 const CleanCSS = require('clean-css');
 const {writeIfChanged} = require('./ninja/write-if-changed.js');
-const [, , buildTimestamp, isDebugString, legacyString, targetName, srcDir, targetGenDir, files] = process.argv;
 
-const filenames = files.split(',');
-const configFiles = [];
 const cleanCSS = new CleanCSS();
-const isDebug = isDebugString === 'true';
-const isLegacy = legacyString === 'true';
 
-for (const fileName of filenames) {
-  let output = fs.readFileSync(path.join(srcDir, fileName), {encoding: 'utf8', flag: 'r'});
-  output = output.replace(/\`/g, '\\\'');
-  output = output.replace(/\\/g, '\\\\');
+function codeForFile({fileName, input, isDebug, isLegacy = false, buildTimestamp}) {
+  input = input.replace(/\`/g, '\\\'');
+  input = input.replace(/\\/g, '\\\\');
 
-  const stylesheetContents = isDebug ? output : cleanCSS.minify(output).styles;
+  const stylesheetContents = isDebug ? input : cleanCSS.minify(input).styles;
 
   let exportStatement;
   if (isLegacy) {
@@ -34,8 +28,6 @@
 export default styles;`;
   }
 
-  const generatedFileName = `${fileName}${isLegacy ? '.legacy' : ''}.js`;
-  const generatedFileLocation = path.join(targetGenDir, generatedFileName);
   const newContents = `// Copyright ${
       new Date(Number(buildTimestamp) * 1000).getUTCFullYear()} The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
@@ -44,13 +36,32 @@
 /* istanbul ignore file */
 ${exportStatement}
 `;
-
-  writeIfChanged(generatedFileLocation, newContents);
-
-  configFiles.push(`\"${generatedFileName}\"`);
+  return newContents;
 }
 
-writeIfChanged(path.join(targetGenDir, `${targetName}-tsconfig.json`), `{
+// Exported only so it can be unit tested.
+exports.codeForFile = codeForFile;
+
+function runMain() {
+  const [, , buildTimestamp, isDebugString, legacyString, targetName, srcDir, targetGenDir, files] = process.argv;
+
+  const filenames = files.split(',');
+  const configFiles = [];
+  const isDebug = isDebugString === 'true';
+  const isLegacy = legacyString === 'true';
+
+  for (const fileName of filenames) {
+    const contents = fs.readFileSync(path.join(srcDir, fileName), {encoding: 'utf8', flag: 'r'});
+    const newContents = codeForFile({fileName, isDebug, input: contents, isLegacy, buildTimestamp});
+    const generatedFileName = `${fileName}${isLegacy ? '.legacy' : ''}.js`;
+    const generatedFileLocation = path.join(targetGenDir, generatedFileName);
+
+    writeIfChanged(generatedFileLocation, newContents);
+
+    configFiles.push(`\"${generatedFileName}\"`);
+  }
+
+  writeIfChanged(path.join(targetGenDir, `${targetName}-tsconfig.json`), `{
     "compilerOptions": {
         "composite": true,
         "outDir": "."
@@ -60,3 +71,8 @@
     ]
 }
 `);
+}
+
+if (require.main === module) {
+  runMain();
+}
diff --git a/scripts/build/tests/generate_css_js_files_test.js b/scripts/build/tests/generate_css_js_files_test.js
new file mode 100644
index 0000000..c56fe92
--- /dev/null
+++ b/scripts/build/tests/generate_css_js_files_test.js
@@ -0,0 +1,53 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+const {assert} = require('chai');
+const {codeForFile} = require('../generate_css_js_files.js');
+
+describe('generating CSS JS files', () => {
+  it('minifies code when not in debug mode', () => {
+    const css = `div {
+      height: 20px;
+    }`;
+    const contents =
+        codeForFile({fileName: 'app.css', isDebug: false, input: css, isLegacy: false, buildTimestamp: Date.now()});
+    assert.isTrue(contents.includes('div{height:20px}'));
+  });
+
+  it('respects clean-css ignore comments', () => {
+    const css = `
+    /* clean-css ignore:start */
+    div {
+      height: 20px;
+    }
+    /* clean-css ignore:end */
+    otherDiv {
+      width: 20px;
+    }`;
+    const contents =
+        codeForFile({fileName: 'app.css', isDebug: false, input: css, isLegacy: false, buildTimestamp: Date.now()});
+    assert.isTrue(contents.includes(`div {
+      height: 20px;
+    }`));
+  });
+
+  it('does not strip container queries wrapped in clean-css ignore', () => {
+    const css = `
+    /* clean-css ignore:start */
+    @container (width<1024px) {
+      .test {
+        color: #fff;
+      }
+    }
+    /* clean-css ignore:end */
+    `;
+    const contents =
+        codeForFile({fileName: 'app.css', isDebug: false, input: css, isLegacy: false, buildTimestamp: Date.now()});
+    assert.isTrue(contents.includes(`@container (width<1024px) {
+      .test {
+        color: #fff;
+      }
+    }`));
+  });
+});