diff --git a/packages/cli/__tests__/compile-stylex-folder-test.js b/packages/cli/__tests__/compile-stylex-folder-test.js index aee94059..5a3325dd 100644 --- a/packages/cli/__tests__/compile-stylex-folder-test.js +++ b/packages/cli/__tests__/compile-stylex-folder-test.js @@ -15,7 +15,7 @@ import { compileDirectory } from '../src/transform'; import * as cacheModule from '../src/cache'; import { getDefaultCachePath } from '../src/cache'; -import fs from 'fs'; +const fs = require('fs').promises; import { isDir, getRelativePath } from '../src/files'; import * as path from 'path'; @@ -23,37 +23,57 @@ const cp = require('child_process'); process.chdir('__tests__/__mocks__'); -function clearTestDir(config: CliConfig) { +async function clearTestDir(config: CliConfig) { for (const output of config.output) { - fs.rmSync(output, { recursive: true, force: true }); + await fs.rm(output, { recursive: true, force: true }); } } -function runCli(args: string, config: CliConfig, onClose: () => void) { +function runCli( + args: string, + config: CliConfig, + onClose: () => void | Promise, +) { const cmd = 'node ' + path.resolve('../../lib/index.js ') + args; console.log(cmd); const script = cp.exec(cmd); script.addListener('error', (err) => { - clearTestDir(config); - throw err; + clearTestDir(config) + .then(() => { + throw err; + }) + .catch((clearErr) => { + throw new Error(`Failed to clear test directory: ${clearErr.message}`); + }); }); script.stderr.on('data', (data) => { process.kill(script.pid); - clearTestDir(config); - throw new Error('failed to start StyleX CLI', data); + clearTestDir(config) + .then(() => { + throw new Error('Failed to start StyleX CLI', data); + }) + .catch((clearErr) => { + throw new Error(`Failed to clear test directory: ${clearErr.message}`); + }); + }); + script.addListener('close', () => { + Promise.resolve(onClose()) + .then(() => {}) + .catch((err) => { + throw new Error(`Error in onClose callback: ${err.message}`); + }); }); - script.addListener('close', onClose); } const snapshot = './snapshot'; const cachePath = getDefaultCachePath(); describe('compiling __mocks__/source to __mocks__/src correctly such that it matches __mocks__/snapshot', () => { - afterAll(() => { - fs.rmSync(config.output, { recursive: true, force: true }); - fs.rmSync(cachePath, { recursive: true, force: true }); + afterAll(async () => { + await fs.rm(config.output, { recursive: true, force: true }); + await fs.rm(cachePath, { recursive: true, force: true }); }); - // need to resolve to absolute paths because the compileDirectory function is expecting them. + const config: TransformConfig = { input: path.resolve('./source'), output: path.resolve('./src'), @@ -70,24 +90,31 @@ describe('compiling __mocks__/source to __mocks__/src correctly such that it mat }, }; - afterAll(() => fs.rmSync(config.output, { recursive: true, force: true })); + afterAll(async () => { + await fs.rm(config.output, { recursive: true, force: true }); + }); - test(config.input, () => { - expect(isDir(config.input)).toBe(true); + test(config.input, async () => { + expect(await isDir(config.input)).toBe(true); }); test(config.output, async () => { - fs.mkdirSync(config.output, { recursive: true }); - expect(isDir(config.output)).toBe(true); + await fs.mkdir(config.output, { recursive: true }); + expect(await isDir(config.output)).toBe(true); await compileDirectory(config); - const outputDir = fs.readdirSync(config.output, { recursive: true }); + const outputDir = await fs.readdir(config.output); for (const file of outputDir) { const outputPath = path.join(config.output, file); const snapshotPath = path.join(snapshot, file); - expect(fs.existsSync(snapshotPath)).toBe(true); + expect( + await fs + .access(snapshotPath) + .then(() => true) + .catch(() => false), + ).toBe(true); if (path.extname(outputPath) === '.js') { - const outputContent = fs.readFileSync(outputPath).toString(); - const snapshotContent = fs.readFileSync(snapshotPath).toString(); + const outputContent = await fs.readFile(outputPath, 'utf-8'); + const snapshotContent = await fs.readFile(snapshotPath, 'utf-8'); expect(outputContent).toEqual(snapshotContent); } } @@ -103,23 +130,29 @@ describe('cli works with -i and -o args', () => { watch: false, babelPresets: [], }; - afterAll(() => clearTestDir(config)); + afterAll(async () => await clearTestDir(config)); + test('script start', (done) => { - const onClose = () => { + const onClose = async () => { for (const dir of config.output) { - const outputDir = fs.readdirSync(dir, { recursive: true }); + const outputDir = await fs.readdir(dir); for (const file of outputDir) { const snapshotDir = path.resolve(path.join(snapshot, file)); - expect(fs.existsSync(snapshotDir)).toBe(true); + expect( + await fs + .access(snapshotDir) + .then(() => true) + .catch(() => false), + ).toBe(true); const outputPath = path.join(dir, file); if (path.extname(outputPath) === '.js') { - const outputContent = fs.readFileSync(outputPath).toString(); - const snapshotContent = fs.readFileSync(snapshotDir).toString(); + const outputContent = await fs.readFile(outputPath, 'utf-8'); + const snapshotContent = await fs.readFile(snapshotDir, 'utf-8'); expect(outputContent).toEqual(snapshotContent); } } } - clearTestDir(config); + await clearTestDir(config); done(); }; @@ -132,16 +165,22 @@ describe('cli works with -i and -o args', () => { input: [path.resolve(config.input[0])], output: [path.resolve(config.output[0])], }; - const onClose = () => { - expect(fs.existsSync(config.output[0])).toBe(true); + const onClose = async () => { + expect( + await fs + .access(config.output[0]) + .then(() => true) + .catch(() => false), + ).toBe(true); done(); }; - clearTestDir(absConfig); - runCli( - `-i ${absConfig.input[0]} -o ${absConfig.output[0]}`, - absConfig, - onClose, - ); + clearTestDir(absConfig).then(() => { + runCli( + `-i ${absConfig.input[0]} -o ${absConfig.output[0]}`, + absConfig, + onClose, + ); + }); }, 10000); }); @@ -154,15 +193,16 @@ describe('cli works with multiple inputs and outputs', () => { watch: false, babelPresets: [], }; - afterAll(() => clearTestDir(config)); + afterAll(async () => await clearTestDir(config)); + test('script compiles multiple directories', (done) => { - const onClose = () => { + const onClose = async () => { let isSecondOutput = false; for (const dir of config.output) { if (dir.endsWith('src2')) { isSecondOutput = true; } - const outputDir = fs.readdirSync(dir, { recursive: true }); + const outputDir = await fs.readdir(dir); for (const file of outputDir) { if (isSecondOutput) { expect(file).not.toContain(config.styleXBundleName); @@ -170,15 +210,20 @@ describe('cli works with multiple inputs and outputs', () => { const outputPath = path.join(dir, file); const snapshotDir = isSecondOutput ? snapshot + '2' : snapshot; const snapshotPath = path.join(snapshotDir, file); - expect(fs.existsSync(snapshotPath)).toBe(true); + expect( + await fs + .access(snapshotPath) + .then(() => true) + .catch(() => false), + ).toBe(true); if (path.extname(outputPath) === '.js') { - const outputContent = fs.readFileSync(outputPath).toString(); - const snapshotContent = fs.readFileSync(snapshotPath).toString(); + const outputContent = await fs.readFile(outputPath, 'utf-8'); + const snapshotContent = await fs.readFile(snapshotPath, 'utf-8'); expect(outputContent).toEqual(snapshotContent); } } } - clearTestDir(config); + await clearTestDir(config); done(); }; const input = config.input.join(' '); @@ -194,7 +239,7 @@ describe('individual testing of util functions', () => { output: './src', cssBundleName: 'stylex_bundle.css', }; - test('file to relative css path', () => { + test('file to relative css path', async () => { const mockFileName = './src/pages/home/page.js'; const relativePath = getRelativePath( mockFileName, @@ -221,7 +266,6 @@ describe('cache mechanism works as expected', () => { copiedNodeModules: false, }, }; - beforeEach(() => { writeSpy = jest.spyOn(cacheModule, 'writeCache'); }); @@ -230,25 +274,27 @@ describe('cache mechanism works as expected', () => { writeSpy.mockRestore(); }); - afterAll(() => { - fs.rmSync(config.output, { recursive: true, force: true }); - fs.rmSync(cachePath, { recursive: true, force: true }); + afterAll(async () => { + await fs.rm(config.output, { recursive: true, force: true }); + await fs.rm(cachePath, { recursive: true, force: true }); }); test('first compilation populates the cache', async () => { - fs.mkdirSync(config.output, { recursive: true }); - fs.mkdirSync(cachePath, { recursive: true }); + await fs.mkdir(config.output, { recursive: true }); + await fs.mkdir(cachePath, { recursive: true }); writeSpy = jest.spyOn(cacheModule, 'writeCache'); await compileDirectory(config); expect(writeSpy).toHaveBeenCalledTimes(3); - const cacheFiles = fs.readdirSync(cachePath); + const cacheFiles = await fs.readdir(cachePath); expect(cacheFiles.length).toEqual(3); for (const cacheFile of cacheFiles) { const cacheFilePath = path.join(cachePath, cacheFile); - const cacheContent = JSON.parse(fs.readFileSync(cacheFilePath, 'utf-8')); + const cacheContent = JSON.parse( + await fs.readFile(cacheFilePath, 'utf-8'), + ); expect(cacheContent).toHaveProperty('inputHash'); expect(cacheContent).toHaveProperty('outputHash'); expect(cacheContent).toHaveProperty('collectedCSS'); @@ -267,18 +313,21 @@ describe('cache mechanism works as expected', () => { const mockFilePath = path.join(config.input, 'index.js'); const mockFileOutputPath = path.join(config.output, 'index.js'); const newContent = 'console.log("Updated content");'; - const originalContent = fs.readFileSync(mockFilePath, 'utf-8'); - const originalOutputContent = fs.readFileSync(mockFileOutputPath, 'utf-8'); + const originalContent = await fs.readFile(mockFilePath, 'utf-8'); + const originalOutputContent = await fs.readFile( + mockFileOutputPath, + 'utf-8', + ); - fs.appendFileSync(mockFilePath, newContent, 'utf-8'); + await fs.appendFile(mockFilePath, newContent, 'utf-8'); await compileDirectory(config); // Ensure index.js is rewritten due to cache invalidation expect(writeSpy).toHaveBeenCalledTimes(1); - fs.writeFileSync(mockFilePath, originalContent, 'utf-8'); - fs.writeFileSync(mockFileOutputPath, originalOutputContent, 'utf-8'); + await fs.writeFile(mockFilePath, originalContent, 'utf-8'); + await fs.writeFile(mockFileOutputPath, originalOutputContent, 'utf-8'); writeSpy.mockRestore(); }); @@ -304,16 +353,26 @@ describe('CLI works with a custom cache path', () => { }; config.cachePath = customCachePath; - beforeEach(() => { - if (fs.existsSync(customCachePath)) { - fs.rmSync(customCachePath, { recursive: true, force: true }); + beforeEach(async () => { + if ( + await fs + .access(customCachePath) + .then(() => true) + .catch(() => false) + ) { + await fs.rm(customCachePath, { recursive: true, force: true }); } }); - afterAll(() => { - fs.rmSync(config.output, { recursive: true, force: true }); - if (fs.existsSync(customCachePath)) { - fs.rmSync(customCachePath, { recursive: true, force: true }); + afterAll(async () => { + await fs.rm(config.output, { recursive: true, force: true }); + if ( + await fs + .access(customCachePath) + .then(() => true) + .catch(() => false) + ) { + await fs.rm(customCachePath, { recursive: true, force: true }); } }); @@ -327,14 +386,24 @@ describe('CLI works with a custom cache path', () => { path.relative(config.input, customFilePath) + '.json', ); - expect(fs.existsSync(customCachePath)).toBe(true); - expect(fs.existsSync(cacheFilePath)).toBe(true); - - const cacheData = JSON.parse(fs.readFileSync(cacheFilePath, 'utf-8')); + expect( + await fs + .access(customCachePath) + .then(() => true) + .catch(() => false), + ).toBe(true); + expect( + await fs + .access(cacheFilePath) + .then(() => true) + .catch(() => false), + ).toBe(true); + + const cacheData = JSON.parse(await fs.readFile(cacheFilePath, 'utf-8')); expect(cacheData).toHaveProperty('inputHash'); expect(cacheData).toHaveProperty('outputHash'); expect(cacheData).toHaveProperty('collectedCSS'); - fs.rmSync(cacheFilePath, { recursive: true, force: true }); + await fs.rm(cacheFilePath, { recursive: true, force: true }); }); });