@apistudio/apim-cli
Version:
CLI for API Management Products
220 lines (200 loc) • 10.2 kB
text/typescript
import path from 'path';
import fs from 'fs';
import {BuildProjectAssets} from '../../src/build-project-assets.js';
import {ProjectAssetValidator} from '../../src/validator/asset-validator.js';
import JSZip from 'jszip';
import {normalizeZipPaths, resolveRelativePaths} from '../../src/index.js';
jest.mock('../../src/service/log-wrapper.ts');
jest.mock('@apic/studio-shared', () => ({
ErrorResponse: jest.fn(),
Metadata_Ref: jest.fn(),
SpecObject: jest.fn(),
YamlContent: jest.fn(),
UpperCaseKinds: jest.fn(),
}));
describe('Build Asset Project Modules', () => {
it('should validate that given entry and return true if it is yaml ', async () => {
const zipFilePath = path.resolve(__dirname, '../assets/gateway-multi-project-asset.zip');
const Buffer = fs.readFileSync(zipFilePath);
const obj = new BuildProjectAssets();
const zip2 = await JSZip.loadAsync(Buffer);
const normalizedBuffer=await normalizeZipPaths(zip2);
const buffer2=await normalizedBuffer.generateAsync({ type: 'nodebuffer' });
const result=await obj['loadZipFromBuffer'](buffer2);
const entry = result.files[path.normalize('project1/api.yaml')];
const obj2 = new ProjectAssetValidator();
const bool=obj2['isYamlFileForFolder'](entry,'project1');
expect(bool).toBe(true);
});
it('should load zip from buffer ', async () => {
const zipFilePath = path.resolve(__dirname, '../assets/gateway-multi-project-asset.zip');
const Buffer = fs.readFileSync(zipFilePath);
const obj = new ProjectAssetValidator();
const result=await obj['loadZipFromBuffer'](Buffer);
expect(result).not.toBe(undefined);
expect(result).not.toBe(null);
expect(result).not.toBe(false);
});
it('should create asset reference map for the project', async () => {
const zipFilePath = path.resolve(__dirname, '../assets/gateway-multi-project-asset.zip');
const Buffer = fs.readFileSync(zipFilePath);
const obj = new ProjectAssetValidator();
const allFolderNames = new Set<string>();
allFolderNames.add('project1');
allFolderNames.add('project2');
const result=await obj['createProjectAssetReferenceMap'](Buffer,'project1',allFolderNames);
for (const value of result.values()) {
expect(value).toBe(true);
}
});
it('should execute catch if createProjectAssetReferenceMap throws an error', async () => {
const spy = jest.spyOn(BuildProjectAssets.prototype, 'createVersionProcessingMap').mockImplementation(() => {
throw new Error('Error processing zip');
});
const buffer = fs.readFileSync(path.resolve(__dirname, '../assets/gateway-multi-project-asset.zip'));
const obj = new ProjectAssetValidator();
const allFolderNames = new Set(['project1', 'project2']);
const result = await obj['createProjectAssetReferenceMap'](buffer, 'project1', allFolderNames);
expect(result).toBeInstanceOf(Map);
spy.mockRestore();
});
it('should process other folders if unresolved refs exist', async () => {
const buffer = fs.readFileSync(path.resolve(__dirname, '../assets/gateway-multi-project-asset.zip'));
const obj = new ProjectAssetValidator();
const allFolderNames = new Set(['project1', 'project2']);
const processedFolders: string[] = [];
const spy = jest.spyOn(ProjectAssetValidator.prototype as any, 'processYamlFiles')
.mockImplementation(async function (
zipContent: unknown,
folder: unknown,
refMap: unknown,
versionMap: unknown,
) {
const typedRefMap = refMap as Map<string, boolean>;
processedFolders.push(folder as string);
if (folder === 'project1') {
typedRefMap.set('ref1', false);
}
});
const result = await obj['createProjectAssetReferenceMap'](buffer, 'project1', allFolderNames);
expect(result).toBeInstanceOf(Map);
expect(result.get('ref1')).toBe(false);
expect(processedFolders).toContain('project2');
spy.mockRestore();
});
it('should create asset path reference map for the project', async () => {
const zipFilePath = path.resolve(__dirname, '../assets/gateway-multi-project-asset.zip');
const Buffer = fs.readFileSync(zipFilePath);
const obj = new ProjectAssetValidator();
const result=await obj['createProjectPathReferenceMap'](Buffer,'project1');
for (const value of result.values()) {
expect(value).toBe(false);
}
});
it('should execute catch if createProjectPathReferenceMap throws an error', async () => {
const spy = jest.spyOn(BuildProjectAssets.prototype, 'createVersionProcessingMap').mockImplementation(() => {
throw new Error('Error processing zip');
})
const buffer = fs.readFileSync(path.resolve(__dirname, '../assets/gateway-multi-project-asset.zip'));
const obj = new ProjectAssetValidator();
const result = await obj['createProjectPathReferenceMap'](buffer, 'project1');
expect(result).toBeInstanceOf(Map);
spy.mockRestore();
});
it('should create asset path reference map for the project and update the map with filepath ', async () => {
const zipFilePath = path.resolve(__dirname, '../assets/gateway-multi-project-asset.zip');
const Buffer = fs.readFileSync(zipFilePath);
const obj = new ProjectAssetValidator();
const zip2 = await JSZip.loadAsync(Buffer);
const normalizedBuffer=await normalizeZipPaths(zip2);
const zip3= await resolveRelativePaths(await normalizedBuffer.generateAsync({ type: 'nodebuffer' }));
const buffer2=await zip3.generateAsync({ type: 'nodebuffer' });
const obj2 = new BuildProjectAssets();
const folderNames = new Set<string>();
const filePathsInFolder = new Set<string>();
await obj2['extractFolderNamesAndPaths'](buffer2,folderNames,filePathsInFolder);
const result=await obj['validateProjectPathReference'](buffer2,'project1',filePathsInFolder);
expect(result).toBe(true);
});
it('should throw an error if ValidateProjectPathReference throws an error', async () => {
const obj = new ProjectAssetValidator();
const spy = jest.spyOn(ProjectAssetValidator.prototype as any, 'createProjectPathReferenceMap').mockImplementation(() => {
throw new Error('Error validating asset');
})
const refMap = new Map<string, boolean>();
const buffer = fs.readFileSync(path.resolve(__dirname, '../assets/gateway-multi-project-asset.zip'));
const allFolderNames = new Set(['project1', 'project2']);
const result = await obj['validateProjectPathReference'](buffer, 'project1', allFolderNames);
expect(result).toBe(false);
spy.mockRestore();
})
it('should throw an error if validateProjectPathReference encounters invalid references', async() => {
const obj = new ProjectAssetValidator();
const spy = jest.spyOn(ProjectAssetValidator.prototype as any, 'createProjectPathReferenceMap').mockResolvedValue(new Map([
['ref1', false],
['ref2', true],
]))
const Buffer = fs.readFileSync(path.resolve(__dirname, '../assets/gateway-multi-project-asset.zip'));
const filePathsInFolder = new Set<string>();
const result = await obj['validateProjectPathReference'](Buffer, 'project1', filePathsInFolder);
expect(result).toBe(false);
})
it('should throw an error if ValidateProjectAssetReference encounters invalid references', async () => {
const obj = new ProjectAssetValidator();
const spy = jest.spyOn(ProjectAssetValidator.prototype as any, 'createProjectAssetReferenceMap').mockImplementation(() => {
throw new Error('Error validating asset');
})
const refMap = new Map<string, boolean>();
const buffer = fs.readFileSync(path.resolve(__dirname, '../assets/gateway-multi-project-asset.zip'));
const allFolderNames = new Set(['project1', 'project2']);
const result = await obj['validateProjectAssetReference'](buffer, 'project1', allFolderNames);
expect(result.isValid).toBe(false);
expect(result.refMap).toBeInstanceOf(Map);
spy.mockRestore();
})
it('should create asset reference map for the project and update the map with filepath ', async () => {
const zipFilePath = path.resolve(__dirname, '../assets/gateway-multi-project-asset.zip');
const Buffer = fs.readFileSync(zipFilePath);
const obj = new ProjectAssetValidator();
const zip2 = await JSZip.loadAsync(Buffer);
const normalizedBuffer=await normalizeZipPaths(zip2);
const zip3= await resolveRelativePaths(await normalizedBuffer.generateAsync({ type: 'nodebuffer' }));
const buffer2=await zip3.generateAsync({ type: 'nodebuffer' });
const obj2 = new BuildProjectAssets();
const folderNames = new Set<string>();
const filePathsInFolder = new Set<string>();
await obj2['extractFolderNamesAndPaths'](buffer2,folderNames,filePathsInFolder);
const result=await obj['validateProjectAssetReference'](buffer2,'project1',filePathsInFolder);
expect(result.isValid).toBe(true);
expect(result.refMap).not.toBe(null);
expect(result.refMap).not.toBe(undefined);
});
it('should validate the minimum assets required for deployment ', async () => {
const zipFilePath = path.resolve(__dirname, '../assets/gateway-multi-project-asset.zip');
const Buffer = fs.readFileSync(zipFilePath);
const obj = new ProjectAssetValidator();
const result=await obj['validateProjectHasMinimumAssets'](Buffer);
expect(result).toBe(true);
});
it('should return false the minimum assets required for deployment is not found ', async () => {
const zipFilePath = path.resolve(__dirname, '../assets/gateway-project-with-no-valid-assets.zip');
const Buffer = fs.readFileSync(zipFilePath);
const obj = new ProjectAssetValidator();
const result=await obj['validateProjectHasMinimumAssets'](Buffer);
expect(result).toBe(false);
});
it('should validate the api spec for kind api files ', async () => {
const zipFilePath = path.resolve(__dirname, '../assets/gateway-multi-project-asset.zip');
const Buffer = fs.readFileSync(zipFilePath);
const obj = new ProjectAssetValidator();
const result=await obj['validateProjectApiSpecVariable'](Buffer,'project1');
expect(result).toBe(true);
});
it('should validate the all the yaml contents have their mandatory fields ', async () => {
const zipFilePath = path.resolve(__dirname, '../assets/gateway-multi-project-asset.zip');
const Buffer = fs.readFileSync(zipFilePath);
const obj = new ProjectAssetValidator();
const result=await obj['validateYaml'](Buffer);
expect(result).toBe(true);
});
});