diff --git a/test/utils/file-system.test.ts b/test/utils/file-system.test.ts index bea37fa..86d5801 100644 --- a/test/utils/file-system.test.ts +++ b/test/utils/file-system.test.ts @@ -1,38 +1,54 @@ -import { afterEach, beforeEach, describe, expect, jest, mock, test, spyOn } from 'bun:test'; +import { + afterEach, + beforeEach, + describe, + expect, + jest, + mock, + spyOn, + test, +} from 'bun:test'; import fs from 'node:fs'; +import { confirm } from '@inquirer/prompts'; import { copyFile, createFile, createPath, + deletePath, isDirectory, isFile, } from '../../src/utils/file-system'; -import log from '../../src/utils/log'; mock.module('node:fs', () => ({ default: { + copyFileSync: mock(), existsSync: mock(), lstatSync: mock(), - writeFileSync: mock(), - copyFileSync: mock(), mkdirSync: mock(), + rmdirSync: mock(), + rmSync: mock(), + writeFileSync: mock(), }, })); +mock.module('@inquirer/prompts', () => ({ + confirm: mock(), +})); + beforeEach(() => { - jest.clearAllMocks(); spyOn(console, 'log').mockImplementation(() => {}); -}) +}); afterEach(() => { + jest.clearAllMocks(); jest.restoreAllMocks(); }); describe('Utils: file-system', () => { describe('isFile', () => { test('returns true if file exists', () => { - (fs.existsSync as jest.Mock).mockReturnValue(true); - (fs.lstatSync as jest.Mock).mockReturnValue({ isFile: () => true }); + (fs.existsSync as jest.Mock).mockReturnValueOnce(true); + (fs.lstatSync as jest.Mock).mockReturnValueOnce({ isFile: () => true }); expect(isFile('./cli.ts')).toBeTrue(); expect(fs.existsSync).toHaveBeenCalledWith('./cli.ts'); @@ -40,7 +56,7 @@ describe('Utils: file-system', () => { }); test('returns false if file does not exist', () => { - (fs.existsSync as jest.Mock).mockReturnValue(false); + (fs.existsSync as jest.Mock).mockReturnValueOnce(false); expect(isFile('./cli.not.exists.ts')).toBeFalse(); expect(fs.existsSync).toHaveBeenCalledWith('./cli.not.exists.ts'); @@ -48,8 +64,8 @@ describe('Utils: file-system', () => { }); test('returns false if path exists but is not a file', () => { - (fs.existsSync as jest.Mock).mockReturnValue(true); - (fs.lstatSync as jest.Mock).mockReturnValue({ isFile: () => false }); + (fs.existsSync as jest.Mock).mockReturnValueOnce(true); + (fs.lstatSync as jest.Mock).mockReturnValueOnce({ isFile: () => false }); expect(isFile('test-path')).toBeFalse(); expect(fs.existsSync).toHaveBeenCalledWith('test-path'); @@ -180,4 +196,72 @@ describe('Utils: file-system', () => { expect(fs.mkdirSync).not.toHaveBeenCalled(); }); }); + + describe('deletePath', () => { + test('deletes a directory if it exists and force is true', async () => { + (confirm as jest.Mock).mockResolvedValue(true); + (fs.existsSync as jest.Mock).mockReturnValue(true); + (fs.lstatSync as jest.Mock).mockReturnValue({ + isFile: () => false, + isDirectory: () => true, + }); + + await deletePath({ path: 'test-dir', force: true }); + + expect(fs.existsSync).toHaveBeenCalledWith('test-dir'); + expect(confirm).not.toHaveBeenCalled(); + expect(fs.rmdirSync).toHaveBeenCalledWith('test-dir', { + recursive: true, + }); + expect(fs.rmSync).not.toHaveBeenCalled(); + }); + + test('deletes a file if it exists and force is true', async () => { + (confirm as jest.Mock).mockResolvedValue(true); + (fs.existsSync as jest.Mock).mockReturnValue(true); + (fs.lstatSync as jest.Mock).mockReturnValue({ + isFile: () => true, + isDirectory: () => false, + }); + + await deletePath({ path: 'test-file.txt', force: true }); + + expect(fs.existsSync).toHaveBeenCalledWith('test-file.txt'); + expect(confirm).not.toHaveBeenCalled(); + expect(fs.rmdirSync).not.toHaveBeenCalled(); + expect(fs.rmSync).toHaveBeenCalledWith('test-file.txt'); + }); + + test('does not delete a directory if force is false and confirmation is not given', async () => { + (confirm as jest.Mock).mockResolvedValue(false); + (fs.existsSync as jest.Mock).mockReturnValue(true); + (fs.lstatSync as jest.Mock).mockReturnValue({ + isFile: () => false, + isDirectory: () => true, + }); + + await deletePath({ path: 'test-dir' }); + + expect(fs.existsSync).toHaveBeenCalledWith('test-dir'); + expect(confirm).toHaveBeenCalledWith({ message: 'Delete directory test-dir recursively?' }); + expect(fs.rmdirSync).not.toHaveBeenCalled(); + expect(fs.rmSync).not.toHaveBeenCalled(); + }); + + test('should not delete a file if force is false and confirmation is not given', async () => { + (confirm as jest.Mock).mockResolvedValue(false); + (fs.existsSync as jest.Mock).mockReturnValue(true); + (fs.lstatSync as jest.Mock).mockReturnValue({ + isFile: () => true, + isDirectory: () => false, + }); + + await deletePath({ path: 'test-file.txt' }); + + expect(fs.existsSync).toHaveBeenCalledWith('test-file.txt'); + expect(confirm).toHaveBeenCalledWith({ message: 'Delete file test-file.txt?' }); + expect(fs.rmdirSync).not.toHaveBeenCalled(); + expect(fs.rmSync).not.toHaveBeenCalled(); + }); + }); }); diff --git a/test/utils/log.test.ts b/test/utils/log.test.ts index e70cbd8..d92409d 100644 --- a/test/utils/log.test.ts +++ b/test/utils/log.test.ts @@ -1,6 +1,14 @@ -import { beforeEach, afterEach, describe, expect, test, jest, spyOn } from 'bun:test'; -import log from '../../src/utils/log'; +import { + afterEach, + beforeEach, + describe, + expect, + jest, + spyOn, + test, +} from 'bun:test'; import chalk from 'chalk'; +import log from '../../src/utils/log'; describe('log', () => { beforeEach(() => { @@ -28,7 +36,9 @@ describe('log', () => { test('should log dimmed warning message in dim yellow color', () => { log.dimmedWarning('dimmed warning message'); - expect(console.log).toHaveBeenCalledWith(chalk.dim.yellow('dimmed warning message')); + expect(console.log).toHaveBeenCalledWith( + chalk.dim.yellow('dimmed warning message'), + ); }); test('should log error message in red color', () => { diff --git a/test/utils/object.test.ts b/test/utils/object.test.ts index fa6f59a..ee34753 100644 --- a/test/utils/object.test.ts +++ b/test/utils/object.test.ts @@ -127,7 +127,9 @@ describe('Utils: object', () => { replaceKeysInFile(filePath, replaceMap); - expect(log.error).toHaveBeenCalledWith('File test-file-path is not a valid file.'); + expect(log.error).toHaveBeenCalledWith( + 'File test-file-path is not a valid file.', + ); expect(log.success).not.toHaveBeenCalled(); expect(fs.writeFileSync).not.toHaveBeenCalled(); }); @@ -142,7 +144,9 @@ describe('Utils: object', () => { }); expect(() => replaceKeysInFile(filePath, replaceMap)).toThrow(Error); - expect(log.error).toHaveBeenCalledWith('Error updating file test-file-path. See below for more info:'); + expect(log.error).toHaveBeenCalledWith( + 'Error updating file test-file-path. See below for more info:', + ); expect(log.success).not.toHaveBeenCalled(); expect(fs.writeFileSync).not.toHaveBeenCalled(); });