UNPKG

@apistudio/apim-cli

Version:

CLI for API Management Products

291 lines (242 loc) 8.53 kB
import { ZipProcessor } from '../core/impl/zip-processor.impl'; import JSZip from 'jszip'; describe('ZipProcessor', () => { let zipProcessor: ZipProcessor; beforeEach(() => { zipProcessor = new ZipProcessor(); }); // Helper function to create a test ZIP file function createTestZip(): JSZip { const zip = new JSZip(); // Add a test YAML file with multiple assets const yamlContent = ` kind: API apiVersion: api.ibm.com/v1 metadata: name: test-api version: 1.0.0 namespace: test spec: value: test-value $ref: test:referenced-asset:1.0.0 --- kind: TestAsset apiVersion: api.ibm.com/v1 metadata: name: referenced-asset version: 1.0.0 namespace: test spec: value: asset-value `; zip.file('api.yaml', yamlContent); // Add another YAML file const anotherYamlContent = ` kind: AnotherAsset apiVersion: api.ibm.com/v1 metadata: name: another-asset version: 1.0.0 spec: value: another-value `; zip.file('another.yaml', anotherYamlContent); // Add a resource file zip.file('resources/test.txt', 'test resource content'); // Add a non-YAML file zip.file('test.json', '{"test": "value"}'); // Add a directory zip.folder('empty-dir'); return zip; } describe('getMultiYamlFiles', () => { it('should extract YAML files from ZIP', async () => { // Arrange const zip = createTestZip(); // Act const result = await zipProcessor.getMultiYamlFiles(zip); // Assert expect(result).toHaveLength(2); // api.yaml and another.yaml expect(result[0].fileName).toMatch(/api\.yaml$/); expect(result[1].fileName).toMatch(/another\.yaml$/); }); it('should parse YAML documents correctly', async () => { // Arrange const zip = createTestZip(); // Act const result = await zipProcessor.getMultiYamlFiles(zip); // Assert const apiYaml = result.find(file => file.fileName.endsWith('api.yaml')); expect(apiYaml).toBeDefined(); expect(apiYaml?.assets).toHaveLength(2); expect(apiYaml?.assets[0].kind).toBe('API'); expect(apiYaml?.assets[1].kind).toBe('TestAsset'); }); it('should handle errors gracefully', async () => { // Arrange const zip = new JSZip(); zip.file('invalid.yaml', Buffer.from('invalid: yaml: content: - -', 'utf8')); // Act const result = await zipProcessor.getMultiYamlFiles(zip); // Assert expect(result).toHaveLength(0); }); }); describe('getAssetsFromZip', () => { it('should extract assets grouped by API', async () => { // Arrange const zip = createTestZip(); // Act const result = await zipProcessor.getAssetsFromZip(zip); // Assert expect(Object.keys(result)).toHaveLength(1); expect(result['test-api']).toBeDefined(); expect(result['test-api'].api.kind).toBe('API'); expect(result['test-api'].relatedAssets).toHaveLength(1); expect(result['test-api'].relatedAssets[0].kind).toBe('TestAsset'); }); it('should collect related assets based on references', async () => { // Arrange const zip = createTestZip(); // Act const result = await zipProcessor.getAssetsFromZip(zip); // Assert const api = result['test-api']; expect(api.relatedAssets[0].metadata.name).toBe('referenced-asset'); }); }); describe('getResourcesFromZip', () => { it('should extract resources from ZIP', async () => { // Arrange const zip = createTestZip(); // Act const result = await zipProcessor.getResourcesFromZip(zip); // Assert expect(Object.keys(result)).toHaveLength(1); expect(result['resources/test.txt']).toBe('test resource content'); }); it('should skip non-resource files', async () => { // Arrange const zip = createTestZip(); // Act const result = await zipProcessor.getResourcesFromZip(zip); // Assert expect(result['test.json']).toBeUndefined(); }); }); describe('findReferences', () => { it('should find references in an asset', () => { // Arrange const asset = { spec: { $ref: 'test:reference1:1.0.0', nested: { $ref: 'test:reference2:1.0.0' }, array: [ { $ref: 'test:reference3:1.0.0' }, { value: 'not a reference' } ] } }; // Act const result = (zipProcessor as any).findReferences(asset); // Assert expect(result).toHaveLength(3); expect(result).toContain('test:reference1:1.0.0'); expect(result).toContain('test:reference2:1.0.0'); expect(result).toContain('test:reference3:1.0.0'); }); }); describe('findAssetByRef', () => { it('should find an asset by reference', () => { // Arrange const assets = [ { kind: 'Test', apiVersion: 'v1', metadata: { name: 'asset1', namespace: 'test', version: '1.0.0' } }, { kind: 'Test', apiVersion: 'v1', metadata: { name: 'asset2', namespace: 'test', version: '2.0.0' } } ]; // Act const result = (zipProcessor as any).findAssetByRef('test:asset1:1.0.0', assets); // Assert expect(result).toBe(assets[0]); }); it('should find asset by name only', () => { // Arrange const assets = [ { kind: 'Test', apiVersion: 'v1', metadata: { name: 'asset1', namespace: 'test', version: '1.0.0' } } ]; // Act - Just use the name without namespace const result = (zipProcessor as any).findAssetByRef('test:asset1', assets); // Assert expect(result).toBeDefined(); if (result) { expect(result.metadata.name).toBe('asset1'); expect(result.metadata.namespace).toBe('test'); } }); it('should handle missing version in reference', () => { // Arrange const assets = [ { kind: 'Test', apiVersion: 'v1', metadata: { name: 'asset1', namespace: 'test', version: '1.0.0' } } ]; // Act const result = (zipProcessor as any).findAssetByRef('test:asset1', assets); // Assert expect(result).toBeDefined(); if (result) { expect(result.metadata.name).toBe('asset1'); expect(result.metadata.namespace).toBe('test'); } }); it('should handle invalid reference format', () => { // Arrange const assets = [ { kind: 'Test', apiVersion: 'v1', metadata: { name: 'asset1', namespace: 'test', version: '1.0.0' } } ]; // Act const result = (zipProcessor as any).findAssetByRef('invalid-ref', assets); // Assert expect(result).toBeUndefined(); }); }); });