From 0cc025c4c7ef0ac31a7540501fda536aee87ea81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Colladon?= Date: Wed, 3 Jan 2024 09:38:55 +0100 Subject: [PATCH] fix: circular dependency issues --- .../flowTranslationProcessor.test.ts | 9 +- __tests__/unit/lib/utils/cliHelper.test.ts | 9 +- __tests__/unit/lib/utils/fsHelper.test.ts | 174 +--------------- __tests__/unit/lib/utils/fsUtils.test.ts | 189 ++++++++++++++++++ __tests__/unit/lib/utils/ignoreHelper.test.ts | 4 +- .../flowTranslationProcessor.ts | 3 +- src/utils/cliHelper.ts | 3 +- src/utils/fsHelper.ts | 35 +--- src/utils/fsUtils.ts | 35 ++++ src/utils/ignoreHelper.ts | 2 +- 10 files changed, 241 insertions(+), 222 deletions(-) create mode 100644 __tests__/unit/lib/utils/fsUtils.test.ts create mode 100644 src/utils/fsUtils.ts diff --git a/__tests__/unit/lib/post-processor/flowTranslationProcessor.test.ts b/__tests__/unit/lib/post-processor/flowTranslationProcessor.test.ts index 3372cf71..f3d51e06 100644 --- a/__tests__/unit/lib/post-processor/flowTranslationProcessor.test.ts +++ b/__tests__/unit/lib/post-processor/flowTranslationProcessor.test.ts @@ -10,17 +10,14 @@ import { TRANSLATION_EXTENSION, TRANSLATION_TYPE, } from '../../../../src/utils/metadataConstants' -import { - writeFile, - scanExtension, - isSubDir, - readFile, -} from '../../../../src/utils/fsHelper' +import { writeFile, scanExtension } from '../../../../src/utils/fsHelper' +import { isSubDir, readFile } from '../../../../src/utils/fsUtils' import { MetadataRepository } from '../../../../src/types/metadata' import { Work } from '../../../../src/types/work' jest.mock('fs-extra') jest.mock('../../../../src/utils/fsHelper') +jest.mock('../../../../src/utils/fsUtils') const mockedScanExtension = jest.mocked(scanExtension) const mockedParseXmlFileToJson = jest.mocked(parseXmlFileToJson) diff --git a/__tests__/unit/lib/utils/cliHelper.test.ts b/__tests__/unit/lib/utils/cliHelper.test.ts index 44b49ccc..0b80dc5e 100644 --- a/__tests__/unit/lib/utils/cliHelper.test.ts +++ b/__tests__/unit/lib/utils/cliHelper.test.ts @@ -9,12 +9,8 @@ import CLIHelper from '../../../../src/utils/cliHelper' import { getLatestSupportedVersion } from '../../../../src/metadata/metadataManager' import messages from '../../../../src/locales/en' import { Work } from '../../../../src/types/work' -import { - readFile, - dirExists, - fileExists, - isGit, -} from '../../../../src/utils/fsHelper' +import { isGit } from '../../../../src/utils/fsHelper' +import { readFile, dirExists, fileExists } from '../../../../src/utils/fsUtils' import { format } from 'util' jest.mock('../../../../src/utils/childProcessUtils', () => { @@ -39,6 +35,7 @@ jest.mock('../../../../src/utils/repoSetup', () => { }) jest.mock('../../../../src/utils/fsHelper') +jest.mock('../../../../src/utils/fsUtils') const mockedReadFile = jest.mocked(readFile) const mockedDirExists = jest.mocked(dirExists) diff --git a/__tests__/unit/lib/utils/fsHelper.test.ts b/__tests__/unit/lib/utils/fsHelper.test.ts index cecdf307..caa5df63 100644 --- a/__tests__/unit/lib/utils/fsHelper.test.ts +++ b/__tests__/unit/lib/utils/fsHelper.test.ts @@ -3,14 +3,10 @@ import { expect, jest, describe, it } from '@jest/globals' import { getWork } from '../../../__utils__/globalTestHelper' import { copyFiles, - dirExists, - fileExists, gitPathSeparatorNormalizer, isGit, - isSubDir, pathExists, readDir, - readFile, readPathFromGit, scan, scanExtension, @@ -309,7 +305,7 @@ describe('readDir', () => { it('should throw', async () => { // Act try { - await readFile('path') + await readDir('path', work.config) } catch (err) { // Assert expect(err).toBeTruthy() @@ -318,41 +314,7 @@ describe('readDir', () => { }) }) }) -/* -describe('readFile', () => { - describe('when readfile succeed', () => { - beforeEach(() => { - // Arrange - fs.promises.readFile.mockImplementationOnce(() => Promise.resolve({})) - }) - it('should return the file', async () => { - // Act - const file = await readFile('path') - // Assert - expect(file).toBeTruthy() - expect(fs.promises.readFile).toHaveBeenCalled() - }) - }) - - describe('when readfile throw', () => { - beforeEach(() => { - // Arrange - fs.promises.readFile.mockImplementationOnce(() => Promise.reject('Error')) - }) - it('should throw', async () => { - // Act - try { - await readFile('path') - } catch (err) { - // Assert - expect(err).toBeTruthy() - expect(fs.promises.readFile).toHaveBeenCalled() - } - }) - }) -}) -*/ describe('scan', () => { describe('when getSpawnContent throw', () => { beforeEach(() => { @@ -485,56 +447,6 @@ describe('scanExtension', () => { }) }) -describe('isSubDir', () => { - describe('when parent contains dir', () => { - it('returns true', async () => { - // Arrange - - // Act - const result = isSubDir('parent', 'parent/dir') - - // Assert - expect(result).toBe(true) - }) - }) - - describe('when parent does not contains dir', () => { - it('returns false', async () => { - // Arrange - - // Act - const result = isSubDir('parent', 'dir/child') - - // Assert - expect(result).toBe(false) - }) - }) - it.each([ - ['/foo', '/foo', false], - ['/foo', '/bar', false], - ['/foo', '/foobar', false], - ['/foo', '/foo/bar', true], - ['/foo', '/foo/../bar', false], - ['/foo', '/foo/./bar', true], - ['/bar/../foo', '/foo/bar', true], - ['/foo', './bar', false], - ['C:\\Foo', 'C:\\Foo\\Bar', false], - ['C:\\Foo', 'C:\\Bar', false], - ['C:\\Foo', 'D:\\Foo\\Bar', false], - ])( - `should verify %s expect %s to be a subDir: %s`, - (parent, child, expected) => { - // Arrange - - // Act - const actual = isSubDir(parent, child) - - // Assert - expect(actual).toBe(expected) - } - ) -}) - describe('pathExists', () => { it('returns true when path is folder', async () => { // Arrange @@ -638,90 +550,6 @@ describe('writeFile', () => { }) }) -describe('dirExists', () => { - it('returns true when dir exist', async () => { - // Arrange - mockedStat.mockImplementation((() => - Promise.resolve({ - isDirectory: () => true, - } as unknown as Stats)) as unknown as typeof stat) - - // Act - const exist = await dirExists('test') - - // Assert - expect(exist).toBe(true) - }) - - it('returns false when dir does not exist', async () => { - // Arrange - mockedStat.mockImplementation((() => - Promise.resolve({ - isDirectory: () => false, - } as unknown as Stats)) as unknown as typeof stat) - - // Act - const exist = await dirExists('test') - - // Assert - expect(exist).toBe(false) - }) - - it('returns false when an exception occurs', async () => { - // Arrange - mockedStat.mockImplementation((() => - Promise.reject(new Error('test'))) as unknown as typeof stat) - - // Act - const exist = await dirExists('test') - - // Assert - expect(exist).toBe(false) - }) -}) - -describe('fileExists', () => { - it('returns true when file exist', async () => { - // Arrange - mockedStat.mockImplementation((() => - Promise.resolve({ - isFile: () => true, - } as unknown as Stats)) as unknown as typeof stat) - - // Act - const exist = await fileExists('test') - - // Assert - expect(exist).toBe(true) - }) - - it('returns false when file does not exist', async () => { - // Arrange - mockedStat.mockImplementation((() => - Promise.resolve({ - isFile: () => false, - } as unknown as Stats)) as unknown as typeof stat) - - // Act - const exist = await fileExists('test') - - // Assert - expect(exist).toBe(false) - }) - - it('returns false when an exception occurs', async () => { - // Arrange - mockedStat.mockImplementation((() => - Promise.reject(new Error('test'))) as unknown as typeof stat) - - // Act - const exist = await fileExists('test') - - // Assert - expect(exist).toBe(false) - }) -}) - describe('isGit', () => { it('returns true when it is a git file', async () => { // Arrange diff --git a/__tests__/unit/lib/utils/fsUtils.test.ts b/__tests__/unit/lib/utils/fsUtils.test.ts new file mode 100644 index 00000000..08bd23cf --- /dev/null +++ b/__tests__/unit/lib/utils/fsUtils.test.ts @@ -0,0 +1,189 @@ +'use strict' +import { expect, jest, describe, it } from '@jest/globals' +import { + dirExists, + fileExists, + isSubDir, + readFile, +} from '../../../../src/utils/fsUtils' + +import { Stats, stat, readFile as fsReadFile } from 'fs-extra' + +jest.mock('fs-extra') + +const mockedStat = jest.mocked(stat) +const mockedReadFile = jest.mocked(fsReadFile) + +beforeEach(() => { + jest.resetAllMocks() +}) + +describe('isSubDir', () => { + describe('when parent contains dir', () => { + it('returns true', async () => { + // Arrange + + // Act + const result = isSubDir('parent', 'parent/dir') + + // Assert + expect(result).toBe(true) + }) + }) + + describe('when parent does not contains dir', () => { + it('returns false', async () => { + // Arrange + + // Act + const result = isSubDir('parent', 'dir/child') + + // Assert + expect(result).toBe(false) + }) + }) + it.each([ + ['/foo', '/foo', false], + ['/foo', '/bar', false], + ['/foo', '/foobar', false], + ['/foo', '/foo/bar', true], + ['/foo', '/foo/../bar', false], + ['/foo', '/foo/./bar', true], + ['/bar/../foo', '/foo/bar', true], + ['/foo', './bar', false], + ['C:\\Foo', 'C:\\Foo\\Bar', false], + ['C:\\Foo', 'C:\\Bar', false], + ['C:\\Foo', 'D:\\Foo\\Bar', false], + ])( + `should verify %s expect %s to be a subDir: %s`, + (parent, child, expected) => { + // Arrange + + // Act + const actual = isSubDir(parent, child) + + // Assert + expect(actual).toBe(expected) + } + ) +}) + +describe('dirExists', () => { + it('returns true when dir exist', async () => { + // Arrange + mockedStat.mockImplementation((() => + Promise.resolve({ + isDirectory: () => true, + } as unknown as Stats)) as unknown as typeof stat) + + // Act + const exist = await dirExists('test') + + // Assert + expect(exist).toBe(true) + }) + + it('returns false when dir does not exist', async () => { + // Arrange + mockedStat.mockImplementation((() => + Promise.resolve({ + isDirectory: () => false, + } as unknown as Stats)) as unknown as typeof stat) + + // Act + const exist = await dirExists('test') + + // Assert + expect(exist).toBe(false) + }) + + it('returns false when an exception occurs', async () => { + // Arrange + mockedStat.mockImplementation((() => + Promise.reject(new Error('test'))) as unknown as typeof stat) + + // Act + const exist = await dirExists('test') + + // Assert + expect(exist).toBe(false) + }) +}) + +describe('fileExists', () => { + it('returns true when file exist', async () => { + // Arrange + mockedStat.mockImplementation((() => + Promise.resolve({ + isFile: () => true, + } as unknown as Stats)) as unknown as typeof stat) + + // Act + const exist = await fileExists('test') + + // Assert + expect(exist).toBe(true) + }) + + it('returns false when file does not exist', async () => { + // Arrange + mockedStat.mockImplementation((() => + Promise.resolve({ + isFile: () => false, + } as unknown as Stats)) as unknown as typeof stat) + + // Act + const exist = await fileExists('test') + + // Assert + expect(exist).toBe(false) + }) + + it('returns false when an exception occurs', async () => { + // Arrange + mockedStat.mockImplementation((() => + Promise.reject(new Error('test'))) as unknown as typeof stat) + + // Act + const exist = await fileExists('test') + + // Assert + expect(exist).toBe(false) + }) +}) + +describe('readFile', () => { + describe('when readfile succeed', () => { + beforeEach(() => { + // Arrange + mockedReadFile.mockImplementationOnce((() => + Promise.resolve('content')) as unknown as typeof mockedReadFile) + }) + it('should return the file', async () => { + // Act + const file = await readFile('path') + + // Assert + expect(file).toBeTruthy() + expect(mockedReadFile).toHaveBeenCalled() + }) + }) + + describe('when readfile throw', () => { + beforeEach(() => { + // Arrange + mockedReadFile.mockImplementationOnce((() => + Promise.reject('Error')) as unknown as typeof mockedReadFile) + }) + it('should throw', async () => { + // Act + try { + await readFile('path') + } catch (err) { + // Assert + expect(err).toBeTruthy() + expect(mockedReadFile).toHaveBeenCalled() + } + }) + }) +}) diff --git a/__tests__/unit/lib/utils/ignoreHelper.test.ts b/__tests__/unit/lib/utils/ignoreHelper.test.ts index d938b344..1dc9b2d8 100644 --- a/__tests__/unit/lib/utils/ignoreHelper.test.ts +++ b/__tests__/unit/lib/utils/ignoreHelper.test.ts @@ -7,14 +7,14 @@ import { resetIncludeInstance, resetIgnoreInstance, } from '../../../../src/utils/ignoreHelper' -import { readFile } from '../../../../src/utils/fsHelper' +import { readFile } from '../../../../src/utils/fsUtils' import { ADDITION, MODIFICATION, DELETION, } from '../../../../src/utils/gitConstants' import { Config } from '../../../../src/types/config' -jest.mock('../../../../src/utils/fsHelper') +jest.mock('../../../../src/utils/fsUtils') const mockedReadFile = jest.mocked(readFile) describe('ignoreHelper', () => { diff --git a/src/post-processor/flowTranslationProcessor.ts b/src/post-processor/flowTranslationProcessor.ts index 8e14dd25..4bef3780 100644 --- a/src/post-processor/flowTranslationProcessor.ts +++ b/src/post-processor/flowTranslationProcessor.ts @@ -8,7 +8,8 @@ import { TRANSLATION_EXTENSION, TRANSLATION_TYPE, } from '../utils/metadataConstants' -import { writeFile, scanExtension, isSubDir, readFile } from '../utils/fsHelper' +import { writeFile, scanExtension } from '../utils/fsHelper' +import { isSubDir, readFile } from '../utils/fsUtils' import { pathExists } from 'fs-extra' import { parse, join } from 'path' import { buildIgnoreHelper } from '../utils/ignoreHelper' diff --git a/src/utils/cliHelper.ts b/src/utils/cliHelper.ts index a2473a05..d2f20797 100644 --- a/src/utils/cliHelper.ts +++ b/src/utils/cliHelper.ts @@ -9,7 +9,8 @@ import { isVersionSupported, } from '../metadata/metadataManager' import { format } from 'util' -import { readFile, dirExists, fileExists, isGit } from './fsHelper' +import { isGit } from './fsHelper' +import { readFile, dirExists, fileExists } from './fsUtils' import { join } from 'path' import { Work } from '../types/work' import { Config } from '../types/config' diff --git a/src/utils/fsHelper.ts b/src/utils/fsHelper.ts index 42808d94..a582fb20 100644 --- a/src/utils/fsHelper.ts +++ b/src/utils/fsHelper.ts @@ -1,6 +1,6 @@ 'use strict' -import { isAbsolute, join, relative } from 'path' -import { readFile as fsReadFile, outputFile, stat } from 'fs-extra' +import { join } from 'path' +import { readFile as fsReadFile, outputFile } from 'fs-extra' import { GIT_COMMAND, GIT_FOLDER, @@ -10,6 +10,7 @@ import { import { EOLRegex, getSpawnContent, treatPathSep } from './childProcessUtils' import { isLFS, getLFSObjectContentPath } from './gitLfsHelper' import { buildIgnoreHelper } from './ignoreHelper' +import { dirExists, fileExists } from './fsUtils' import { Config } from '../types/config' const FOLDER = 'tree' @@ -99,13 +100,6 @@ export const readDir = async (dir: string, config: Config) => { return dirContent } -export const readFile = async (path: string) => { - const file = await fsReadFile(path, { - encoding: UTF8_ENCODING, - }) - return file -} - export async function* scan( dir: string, config: Config @@ -139,11 +133,6 @@ export const writeFile = async ( await outputFile(join(config.output, treatPathSep(path)), content) } -export const isSubDir = (parent: string, dir: string) => { - const rel = relative(parent, dir) - return !!rel && !rel.startsWith('..') && !isAbsolute(rel) -} - export const scanExtension = async ( dir: string, ext: string, @@ -158,24 +147,6 @@ export const scanExtension = async ( return result } -export const dirExists = async (dir: string) => { - try { - const st = await stat(dir) - return st.isDirectory() - } catch { - return false - } -} - -export const fileExists = async (file: string) => { - try { - const st = await stat(file) - return st.isFile() - } catch { - return false - } -} - export const isGit = async (dir: string) => { const isGitDir = await dirExists(join(dir, GIT_FOLDER)) const isGitFile = await fileExists(join(dir, GIT_FOLDER)) diff --git a/src/utils/fsUtils.ts b/src/utils/fsUtils.ts new file mode 100644 index 00000000..1c419589 --- /dev/null +++ b/src/utils/fsUtils.ts @@ -0,0 +1,35 @@ +import { stat, readFile as fsReadFile } from 'fs-extra' +import { isAbsolute, relative } from 'path' +import { UTF8_ENCODING } from './gitConstants' + +export const isSubDir = (parent: string, dir: string) => { + const rel = relative(parent, dir) + return !!rel && !rel.startsWith('..') && !isAbsolute(rel) +} + +export const dirExists = async (dir: string) => { + try { + const st = await stat(dir) + return st.isDirectory() + } catch { + return false + } +} + +export const fileExists = async (file: string) => { + try { + const st = await stat(file) + return st.isFile() + } catch { + return false + } +} + +export const readFile = async (path: string) => { + const file = await fsReadFile(path, { + encoding: UTF8_ENCODING, + }) + return file +} + +export const DOT = '.' diff --git a/src/utils/ignoreHelper.ts b/src/utils/ignoreHelper.ts index 129def92..7e982e54 100644 --- a/src/utils/ignoreHelper.ts +++ b/src/utils/ignoreHelper.ts @@ -1,5 +1,5 @@ import ignore, { Ignore } from 'ignore' -import { readFile } from './fsHelper' +import { readFile } from './fsUtils' import { ADDITION, DELETION,