@apistudio/apim-cli
Version:
CLI for API Management Products
395 lines (324 loc) • 13.1 kB
text/typescript
/**
* Copyright Super iPaaS Integration LLC, an IBM Company 2024
*/
import fs, {existsSync, statSync, readFileSync, accessSync} from 'fs-extra';
import path, {join} from 'path';
import crypto from 'crypto';
import {hasReadAccess,
isDirectory,
isDirOrFileExists,
isFile,
isSubDirectoryExists,
readFile,
readFileAsBuffer,
isYamlFile,
isJsonFile,
isOtherFile,
getRandomFileName,
getSubDirectory,
writeJsonToFile,
readJsonFromFile,
checkFileExists,
ensureDirectoryExists,
readFileAsString,
readDirectoryContents,
getFileNameFromPath,
createBuildZip,
normalizePath,
getParentDir
} from './fs-helper';
jest.mock('fs');
jest.mock('fs-extra');
jest.mock('path');
jest.mock('crypto', () => ({
randomUUID: jest.fn(),
}));
jest.mock('./message-helper', () => ({
__esModule: true,
showError: jest.fn()
}));
describe('FS Helper test suite', () => {
afterEach(() => {
jest.clearAllMocks();
});
it('should return true if file exists', () => {
(existsSync as jest.Mock).mockReturnValue(true);
expect(isDirOrFileExists('sample path')).toBe(true);
});
it('should return false if file does not exists', () => {
(existsSync as jest.Mock).mockReturnValue(false);
expect(isDirOrFileExists('sample path')).toBe(false);
});
it('should return false if the given path is not directory', () => {
(existsSync as jest.Mock).mockReturnValue(true);
(statSync as jest.Mock).mockReturnValue({
isDirectory: () => false
});
expect(isDirectory('sample path')).toBe(false);
});
it('should return true if the given path is directory', () => {
(existsSync as jest.Mock).mockReturnValue(true);
(statSync as jest.Mock).mockReturnValue({
isDirectory: () => true
});
expect(isDirectory('sample path')).toBe(true);
});
it('should return false if the given path does not exists', () => {
(existsSync as jest.Mock).mockReturnValue(false);
(statSync as jest.Mock).mockReturnValue({
isDirectory: () => true
});
expect(isDirectory('sample path')).toBe(false);
});
it('should return false if sub-directory does not exists', () => {
(existsSync as jest.Mock).mockReturnValue(true);
(statSync as jest.Mock).mockReturnValue({
isDirectory: () => false
});
(join as jest.Mock).mockReturnValue('');
expect(isSubDirectoryExists('sample path', 'test')).toBe(false);
});
it('should return true if sub-directory does exists', () => {
(existsSync as jest.Mock).mockReturnValue(true);
(statSync as jest.Mock).mockReturnValue({
isDirectory: () => true
});
(join as jest.Mock).mockReturnValue('');
expect(isSubDirectoryExists('sample path', 'test')).toBe(true);
});
it('should return true if the given path is a file', () => {
(existsSync as jest.Mock).mockReturnValue(true);
(statSync as jest.Mock).mockReturnValue({
isDirectory: () => false,
isFile: () => true
});
expect(isFile('sample path')).toBe(true);
});
it('should return false if the given path is not a file', () => {
(existsSync as jest.Mock).mockReturnValue(true);
(statSync as jest.Mock).mockReturnValue({
isDirectory: () => false,
isFile: () => false
});
expect(isFile('sample path')).toBe(false);
});
it('should return false if the given path does not exists', () => {
(existsSync as jest.Mock).mockReturnValue(false);
(statSync as jest.Mock).mockReturnValue({
isDirectory: () => false,
isFile: () => true
});
expect(isFile('sample path')).toBe(false);
});
it('should return content of the file', () => {
const fileContent = 'File content';
(existsSync as jest.Mock).mockReturnValue(true);
(statSync as jest.Mock).mockReturnValue({
isDirectory: () => false,
isFile: () => true
});
(join as jest.Mock).mockReturnValue('');
(readFileSync as jest.Mock).mockReturnValue(Buffer.alloc(fileContent.length, fileContent));
expect(readFile('dir path', 'filename')).toBe(fileContent);
});
it('should return true if access permission is available', () => {
(accessSync as jest.Mock).mockReturnValue(true);
expect(hasReadAccess('sample path')).toBe(true);
});
it('should return false if access permission is not available', () => {
jest.spyOn(fs, 'accessSync').mockImplementation(() => {
throw new Error('test');
});
expect(hasReadAccess('sample path')).toBe(false);
});
it('should return file content as buffer', () => {
expect(readFileAsBuffer('sample path')).toBeInstanceOf(Buffer);
});
it('should generate a random file name with default extension', () => {
(crypto.randomUUID as jest.Mock).mockReturnValue('random-uuid');
const fileName = getRandomFileName();
expect(fileName).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.yml$/i);
});
it('should return a random file name with provided extension', () => {
(crypto.randomUUID as jest.Mock).mockReturnValue('random-uuid');
const fileName = getRandomFileName('.txt');
expect(fileName).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.txt$/i);
});
it('should add a dot to the extension if not provided', () => {
(crypto.randomUUID as jest.Mock).mockReturnValue('random-uuid');
const fileName = getRandomFileName('txt');
expect(fileName).toMatch(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\.txt$/i);
});
it('should return true for .yml files', () => {
expect(isYamlFile('file.yml')).toBe(true);
});
it('should return true for .yaml files', () => {
expect(isYamlFile('file.yaml')).toBe(true);
});
it('should return false for non-yaml files', () => {
expect(isYamlFile('file.txt')).toBe(false);
});
it('should return yaml file as false for null', () => {
expect(isYamlFile(null as unknown as string)).toBe(false);
});
it('should return yaml file as false for undefined', () => {
expect(isYamlFile(undefined as unknown as string)).toBe(false);
});
it('should return true for .json files', () => {
expect(isJsonFile('file.json')).toBe(true);
});
it('should return false for non-json files', () => {
expect(isJsonFile('file.txt')).toBe(false);
});
it('should return json file as false for null', () => {
expect(isJsonFile(null as unknown as string)).toBe(false);
});
it('should return json file as false for undefined', () => {
expect(isJsonFile(undefined as unknown as string)).toBe(false);
});
it('should return true for .txt files', () => {
expect(isOtherFile('file.txt')).toBe(true);
});
it('should return other file as false for json files', () => {
expect(isOtherFile('file.json')).toBe(false);
});
it('should return other file as false for null', () => {
expect(isOtherFile(null as unknown as string)).toBe(false);
});
it('should return other file as false for undefined', () => {
expect(isOtherFile(undefined as unknown as string)).toBe(false);
});
it('should throw an error if the subdirectory does not exist', () => {
jest.spyOn({ isSubDirectoryExists }, 'isSubDirectoryExists').mockReturnValue(false);
const parentDirPath = '/parent/dir';
const folderName = 'subfolder';
const errorMessage = `The folder '${folderName}' is invalid or does not exist inside parent directory '${parentDirPath}'`;
expect(() => getSubDirectory(parentDirPath, folderName)).toThrowError(errorMessage);
});
it('should return the file name from the given path', () => {
const filePath = 'path/to/file.txt';
const expectedFileName = 'file.txt';
(path.basename as jest.Mock).mockReturnValue(expectedFileName);
const result = getFileNameFromPath(filePath);
expect(result).toBe(expectedFileName);
});
it('should create build zip and return true', async () => {
const fileContent = 'File content';
const buffer = Buffer.alloc(fileContent.length, fileContent);
const folderPath = 'path/to/directory/build.zip';
const result = await createBuildZip(buffer, folderPath);
expect(result).toBe(true);
});
it('should return false if the file path do not .zip', async () => {
const fileContent = 'File content';
const buffer = Buffer.alloc(fileContent.length, fileContent);
const folderPath = 'path/to/directory/build';
const result = await createBuildZip(buffer, folderPath);
expect(result).toBe(false);
});
describe('writeJsonToFile', () => {
it('should write JSON to file with the correct options', async () => {
const filePath = 'path/to/file.json';
const data = { key: 'value' };
const options = { spaces: 2 };
await writeJsonToFile(filePath, data, options);
expect(fs.writeJson).toHaveBeenCalledWith(filePath, data, options);
});
it('should throw an error if writing fails', async () => {
const filePath = 'path/to/file.json';
const data = { key: 'value' };
(fs.writeJson as jest.Mock).mockRejectedValue(new Error('Write failed'));
await expect(writeJsonToFile(filePath, data)).rejects.toThrow('Failed to write JSON to file: Write failed');
});
});
describe('readJsonFromFile', () => {
const mockFilePath = 'mock/file/path.json';
const mockJsonData = { key: 'value' };
it('should read JSON data from a file successfully', async () => {
(fs.readJson as jest.Mock).mockResolvedValue(mockJsonData);
const result = await readJsonFromFile(mockFilePath);
expect(fs.readJson).toHaveBeenCalledWith(mockFilePath);
expect(result).toEqual(mockJsonData);
});
it('should throw an error if reading JSON from the file fails', async () => {
const errorMessage = 'mock error message';
(fs.readJson as jest.Mock).mockRejectedValue(new Error(errorMessage));
await expect(readJsonFromFile(mockFilePath)).rejects.toThrow(`${errorMessage}`);
});
});
describe('checkFileExists', () => {
it('should return true if the file exists', async () => {
const filePath = 'path/to/file.json';
(fs.pathExists as jest.Mock).mockResolvedValue(true);
const result = await checkFileExists(filePath);
expect(result).toBe(true);
expect(fs.pathExists).toHaveBeenCalledWith(filePath);
});
it('should return false if the file does not exist', async () => {
const filePath = 'path/to/file.json';
(fs.pathExists as jest.Mock).mockResolvedValue(false);
const result = await checkFileExists(filePath);
expect(result).toBe(false);
});
it('should throw an error if checking fails', async () => {
const filePath = 'path/to/file.json';
(fs.pathExists as jest.Mock).mockRejectedValue(new Error('Check failed'));
await expect(checkFileExists(filePath)).rejects.toThrow('Failed to check if file exists: Check failed');
});
});
describe('ensureDirectoryExists', () => {
it('should ensure the directory exists', async () => {
const dirPath = 'path/to/dir';
await ensureDirectoryExists(dirPath);
expect(fs.ensureDir).toHaveBeenCalledWith(dirPath);
});
it('should throw an error if directory creation fails', async () => {
const dirPath = 'path/to/dir';
(fs.ensureDir as jest.Mock).mockRejectedValue(new Error('Ensure dir failed'));
await expect(ensureDirectoryExists(dirPath)).rejects.toThrow('Failed to ensure directory exists: Ensure dir failed');
});
});
describe('readFileAsString', () => {
it('should return the file content as a string', () => {
const filePath = 'path/to/file.txt';
const fileContent = 'File content here';
(fs.existsSync as jest.Mock).mockReturnValue(true);
(fs.readFileSync as jest.Mock).mockReturnValue(fileContent);
const result = readFileAsString(filePath);
expect(result).toBe(fileContent);
expect(fs.existsSync).toHaveBeenCalledWith(filePath);
expect(fs.readFileSync).toHaveBeenCalledWith(filePath, 'utf8');
});
it('should throw an error if the file does not exist', () => {
const filePath = 'path/to/nonexistent-file.txt';
(fs.existsSync as jest.Mock).mockReturnValue(false);
expect(() => readFileAsString(filePath)).toThrow(`The file '${filePath}' does not exist`);
expect(fs.existsSync).toHaveBeenCalledWith(filePath);
});
it('should throw an error if reading file fails', () => {
const filePath = 'path/to/file.txt';
(fs.existsSync as jest.Mock).mockReturnValue(true);
(fs.readFileSync as jest.Mock).mockImplementation(() => {
throw new Error('Failed to read file');
});
expect(() => readFileAsString(filePath)).toThrow('Failed to read file');
});
});
describe('readDirectoryContents', () => {
it('should return the list of files in the directory', () => {
const folderPath = 'path/to/directory';
const directoryContents = ['file1.txt', 'file2.txt'];
(fs.readdirSync as jest.Mock).mockReturnValue(directoryContents);
const result = readDirectoryContents(folderPath);
expect(result).toEqual(directoryContents);
expect(fs.readdirSync).toHaveBeenCalledWith(folderPath);
});
it('should throw an error if directory reading fails', () => {
const folderPath = 'path/to/directory';
(fs.readdirSync as jest.Mock).mockImplementation(() => {
throw new Error('Failed to read directory');
});
expect(() => readDirectoryContents(folderPath)).toThrow('Failed to read directory');
});
});
});