UNPKG

@apistudio/apim-cli

Version:

CLI for API Management Products

294 lines (245 loc) 11.3 kB
/** * Copyright Super iPaaS Integration LLC, an IBM Company 2024 */ /* eslint-disable @typescript-eslint/no-var-requires */ import AdmZip from 'adm-zip'; import path from 'path'; import { addValidAssetsToZip, checkAndAddValidYamlFile, checkAndAddValidJsonFile, checkAndAddOtherFile } from './zip-helper'; import { isDirOrFileExists, readDirectoryContents, isDirectory, isYamlFile, isJsonFile, readFile, getFileNameFromPath, isOtherFile } from '../../helpers/common/fs-helper'; import { DIRECTORY_DOESNT_EXIST, ASSERT_ADDED } from '../../constants/message-constants.js'; import { showInfo, showWarning } from './message-helper'; import { readMultiYaml, convertToYAMLString } from '../../helpers/common/yaml-helper.js'; import { readJson } from '../../helpers/common/json-helper.js'; import { DebugManager } from "../../debug/debug-manager.js"; import { isValidRestAPI } from './rest-api-validation-helper.js'; import { isValidAsset } from '../apim/asset-helper.js'; jest.mock('../../helpers/common/fs-helper', () => ({ isDirOrFileExists: jest.fn(), readDirectoryContents: jest.fn(), isDirectory: jest.fn(), isYamlFile: jest.fn(), isJsonFile: jest.fn(), isOtherFile: jest.fn(), readFile: jest.fn(), getFileNameFromPath: jest.fn() })); jest.mock('../../helpers/common/message-helper', () => ({ showWarning: jest.fn(), showError: jest.fn(), showInfo: jest.fn() })); jest.mock('../../debug/debug-manager.js', () => ({ DebugManager: { getInstance: () => ({ isDebugEnabled: jest.fn().mockReturnValue(true), setDebugEnabled: jest.fn(), }) } })); jest.mock('../../helpers/apim/asset-helper.js', () => ({ isValidAsset: jest.fn(), })); jest.mock('../../helpers/common/rest-api-validation-helper.js', () => ({ isValidRestAPI: jest.fn(), })); jest.mock('../../helpers/common/yaml-helper.js', () => ({ readMultiYaml: jest.fn(), convertToYAMLString: jest.fn() })); jest.mock('../../helpers/common/json-helper.js', () => ({ readJson: jest.fn() })); describe('Zip Helper Recursive and File Skipping Tests', () => { let mockZipFile: jest.Mocked<AdmZip>; beforeEach(() => { jest.clearAllMocks(); mockZipFile = new AdmZip() as jest.Mocked<AdmZip>; mockZipFile.addLocalFile = jest.fn(); mockZipFile.addFile = jest.fn(); }); afterEach(() => { jest.clearAllMocks(); }); it('should add valid assets recursively and handle directory structure', () => { const mockFolderPath = 'folder'; const mockZipFolderPath = 'zip/folder'; const mockExcludeKinds: string[] = ['kindToExclude']; const mockItems = ['file.yaml', 'subfolder']; (readMultiYaml as jest.Mock).mockReturnValue([{ kind: 'api' }, { kind: 'transport' }]); (isDirOrFileExists as jest.Mock).mockReturnValue(true); (readDirectoryContents as jest.Mock).mockReturnValue(mockItems); (isDirectory as jest.Mock).mockImplementation((itemPath) => itemPath === path.join(mockFolderPath, 'subfolder')); (isYamlFile as jest.Mock).mockReturnValue(true); (isJsonFile as jest.Mock).mockReturnValue(false); addValidAssetsToZip(mockFolderPath, mockZipFolderPath, mockZipFile, mockExcludeKinds); expect(mockZipFile.addFile).toHaveBeenCalledWith( `${mockZipFolderPath}/`, Buffer.from("") ); // Check if the YAML file is added expect(mockZipFile.addFile).toHaveBeenCalledWith( `${mockZipFolderPath}/`, expect.any(Buffer) ); }); it('should skip non-supported files', () => { const mockFolderPath = 'folder'; const mockZipFolderPath = 'zip/folder'; const mockExcludeKinds: string[] = []; const mockItems = ['file.txt']; (isDirOrFileExists as jest.Mock).mockReturnValue(true); (readDirectoryContents as jest.Mock).mockReturnValue(mockItems); (isDirectory as jest.Mock).mockReturnValue(false); (isYamlFile as jest.Mock).mockReturnValue(false); (isJsonFile as jest.Mock).mockReturnValue(false); addValidAssetsToZip(mockFolderPath, mockZipFolderPath, mockZipFile, mockExcludeKinds); expect(mockZipFile.addFile).not.toHaveBeenCalledWith( `${mockZipFolderPath}/file.txt`, expect.any(Buffer) ); }); }); describe('Zip Helper Test Suite', () => { let mockZipFile: jest.Mocked<AdmZip>; beforeEach(() => { jest.clearAllMocks(); mockZipFile = new AdmZip() as jest.Mocked<AdmZip>; mockZipFile.addLocalFile = jest.fn(); }); afterEach(() => { jest.clearAllMocks(); }); it('should not add files if directory has no files, but should add the empty directory', () => { const mockFolderPath = 'folder'; const mockZipFolderPath = 'zip/folder'; const mockExcludeKinds: string[] = ['kindToExclude']; (isDirOrFileExists as jest.Mock).mockReturnValue(true); (readDirectoryContents as jest.Mock).mockReturnValue([]); addValidAssetsToZip(mockFolderPath, mockZipFolderPath, mockZipFile, mockExcludeKinds); const expectedPath = path.join(mockZipFolderPath, '/'); expect(mockZipFile.getEntries().length).toBe(1); expect(mockZipFile.getEntries()[0].entryName).toBe(expectedPath); }); it('should not add files if directory does not exist', () => { const mockFolderPath = 'folder'; const mockZipFolderPath = 'zip/folder'; const mockExcludeKinds: string[] = ['kindToExclude']; (isDirOrFileExists as jest.Mock).mockReturnValue(false); (showWarning as jest.Mock).mockImplementation((message) => { expect(message).toBe(`${DIRECTORY_DOESNT_EXIST} ${mockFolderPath}`); }); addValidAssetsToZip(mockFolderPath, mockZipFolderPath, mockZipFile, mockExcludeKinds); expect(showWarning).toHaveBeenCalledWith(`${DIRECTORY_DOESNT_EXIST} ${mockFolderPath}`); expect(mockZipFile.getEntries().length).toBe(0); }); it('should add yaml files to the zip', () => { const mockFolderPath = 'folder'; const mockZipFolderPath = 'zip/folder'; const mockExcludeKinds: string[] = ['kindToExclude']; const mockYamlContent = 'yaml content'; const mockCombinedYaml = 'combined yaml content'; (isDirOrFileExists as jest.Mock).mockReturnValue(true); (readDirectoryContents as jest.Mock).mockReturnValue(['api.yaml']); (isDirectory as jest.Mock).mockReturnValue(false); (isYamlFile as jest.Mock).mockReturnValue(true); (readFile as jest.Mock).mockReturnValue(mockYamlContent); (readMultiYaml as jest.Mock).mockReturnValue([{ kind: 'api' }]); (isValidRestAPI as jest.Mock).mockReturnValue(false); (isValidAsset as jest.Mock).mockReturnValue(true); (convertToYAMLString as jest.Mock).mockReturnValue(mockCombinedYaml); checkAndAddValidYamlFile('zip/folder/api.yaml', mockZipFolderPath, mockZipFile, []); addValidAssetsToZip(mockFolderPath, mockZipFolderPath, mockZipFile, mockExcludeKinds); expect(mockZipFile.getEntries().length).toBe(1); const yamlEntry = mockZipFile.getEntry('zip/folder/api.yaml'); expect(yamlEntry).toBeDefined(); }); it('should handle YAML files with errors gracefully', () => { const mockFolderPath = 'folder'; const mockZipFolderPath = 'zip/folder'; const mockExcludeKinds: string[] = []; const mockFilePath = 'folder/error.yaml'; (isDirOrFileExists as jest.Mock).mockReturnValue(true); (readDirectoryContents as jest.Mock).mockReturnValue(['error.yaml']); (isDirectory as jest.Mock).mockReturnValue(false); (isYamlFile as jest.Mock).mockReturnValue(true); (readFile as jest.Mock).mockImplementation(() => { throw new Error('File read error'); }); expect(() => { checkAndAddValidYamlFile(mockFilePath, mockZipFolderPath, mockZipFile, mockExcludeKinds); }).toThrow(new Error(`File read error`)); }); it('should handle JSON files with errors gracefully', () => { const mockFolderPath = 'folder'; const mockZipFolderPath = 'zip/folder'; const mockFilePath = 'folder/error.json'; (isDirOrFileExists as jest.Mock).mockReturnValue(true); (readDirectoryContents as jest.Mock).mockReturnValue(['error.json']); (isDirectory as jest.Mock).mockReturnValue(false); (isJsonFile as jest.Mock).mockReturnValue(true); (readFile as jest.Mock).mockImplementation(() => { throw new Error('File read error'); }); expect(() => { checkAndAddValidJsonFile(mockFilePath, mockZipFolderPath, mockZipFile, []); }).toThrow(new Error(`File read error`)); }); test('should handle files that are not JSON or YAML', () => { (isDirOrFileExists as jest.Mock).mockReturnValue(true); (readDirectoryContents as jest.Mock).mockReturnValue(['other.txt']); (isDirectory as jest.Mock).mockReturnValue(false); (isYamlFile as jest.Mock).mockReturnValue(false); (isJsonFile as jest.Mock).mockReturnValue(false); addValidAssetsToZip('folder', 'zip/folder', mockZipFile, []); const entry = mockZipFile.getEntry('zip/folder/other.txt'); expect(entry).toBeNull(); }); test('should handle multi YAML contents and add it to zip', () => { const mockZipFolderPath = 'zip/folder'; const mockFileName = 'file.yaml'; const mockExcludeKinds: string[] = ['kindToExclude']; const mockYamlContents = [ { kind: 'api', name: 'API Asset' }, { kind: 'transport', name: 'Transport Asset' }, { kind: 'kindToExclude', name: 'Excluded Asset' }, ]; const convertedYaml = "---\nname: Converted Asset\n"; (readMultiYaml as jest.Mock).mockReturnValue(mockYamlContents); (getFileNameFromPath as jest.Mock).mockReturnValue(mockFileName); (isValidRestAPI as jest.Mock).mockReturnValue(false); (isValidAsset as jest.Mock).mockReturnValue(true); (convertToYAMLString as jest.Mock).mockReturnValue(convertedYaml); addValidAssetsToZip('folder', mockZipFolderPath, mockZipFile, mockExcludeKinds); expect(mockZipFile.getEntries().length).toBe(1); const yamlEntry = mockZipFile.getEntry('zip/folder/file.yaml'); expect(yamlEntry).toBeDefined(); }); it('should add non-YAML/JSON files to the zip', () => { const mockZipFolderPath = 'zip/folder'; const mockExcludeKinds: string[] = ['kindToExclude']; (isDirOrFileExists as jest.Mock).mockReturnValue(true); (readDirectoryContents as jest.Mock).mockReturnValue(['otherFile.txt']); (isDirectory as jest.Mock).mockReturnValue(false); (isOtherFile as jest.Mock).mockReturnValue(true); checkAndAddOtherFile('zip/folder/otherFile.txt', mockZipFolderPath, mockZipFile); addValidAssetsToZip('folder', mockZipFolderPath, mockZipFile, mockExcludeKinds); console.log(mockZipFile); expect(mockZipFile.getEntries().length).toBe(1); const otherEntry = mockZipFile.getEntry('zip/folder/otherFile.txt'); expect(otherEntry).toBeDefined(); }); it('should add json files to the zip', () => { const mockFolderPath = 'folder'; const mockZipFolderPath = 'zip/folder'; const mockExcludeKinds: string[] = ['kindToExclude']; const mockJsonContent = 'json content'; (isDirOrFileExists as jest.Mock).mockReturnValue(true); (readDirectoryContents as jest.Mock).mockReturnValue(['swagger.json']); (isDirectory as jest.Mock).mockReturnValue(false); (isJsonFile as jest.Mock).mockReturnValue(true); (readFile as jest.Mock).mockReturnValue(mockJsonContent); (readJson as jest.Mock).mockReturnValue({ "swagger": "2.0" }); (isValidRestAPI as jest.Mock).mockReturnValue(true); checkAndAddValidJsonFile('zip/folder/swagger.json', mockZipFolderPath, mockZipFile, []); addValidAssetsToZip(mockFolderPath, mockZipFolderPath, mockZipFile, mockExcludeKinds); expect(mockZipFile.getEntries().length).toBe(1); const jsonEntry = mockZipFile.getEntry('zip/folder/swagger.json'); expect(jsonEntry).toBeDefined(); }); });