223 lines
6.8 KiB
JavaScript
223 lines
6.8 KiB
JavaScript
/**
|
|
* Manifest Validation Unit Tests
|
|
* Tests for validating manifest structure and fields
|
|
* File: test/unit/manifest-validation.test.js
|
|
*/
|
|
|
|
const { ManifestValidator } = require('../../tools/cli/installers/lib/core/manifest');
|
|
|
|
describe('Manifest Validation', () => {
|
|
let validator;
|
|
|
|
beforeEach(() => {
|
|
validator = new ManifestValidator();
|
|
});
|
|
|
|
describe('validateManifest', () => {
|
|
// Test 2.1: Validate Complete Manifest
|
|
it('should validate complete valid manifest', () => {
|
|
const completeManifest = {
|
|
version: '4.36.2',
|
|
installed_at: '2025-08-12T23:51:04.439Z',
|
|
install_type: 'full',
|
|
ides_setup: ['claude-code', 'cline'],
|
|
expansion_packs: ['bmad-infrastructure-devops'],
|
|
};
|
|
|
|
const result = validator.validateManifest(completeManifest);
|
|
|
|
expect(result.isValid).toBe(true);
|
|
expect(result.errors).toEqual([]);
|
|
});
|
|
|
|
// Test 2.2: Reject Missing Required Fields
|
|
it('should reject manifest missing "version"', () => {
|
|
const manifestMissingVersion = {
|
|
installed_at: '2025-08-12T23:51:04.439Z',
|
|
install_type: 'full',
|
|
};
|
|
|
|
const result = validator.validateManifest(manifestMissingVersion);
|
|
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.errors.length).toBeGreaterThan(0);
|
|
expect(result.errors.some((e) => e.includes('version'))).toBe(true);
|
|
});
|
|
|
|
it('should reject manifest missing "installed_at"', () => {
|
|
const manifestMissingDate = {
|
|
version: '4.36.2',
|
|
install_type: 'full',
|
|
};
|
|
|
|
const result = validator.validateManifest(manifestMissingDate);
|
|
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.errors.some((e) => e.includes('installed_at'))).toBe(true);
|
|
});
|
|
|
|
it('should reject manifest missing "install_type"', () => {
|
|
const manifestMissingType = {
|
|
version: '4.36.2',
|
|
installed_at: '2025-08-12T23:51:04.439Z',
|
|
};
|
|
|
|
const result = validator.validateManifest(manifestMissingType);
|
|
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.errors.some((e) => e.includes('install_type'))).toBe(true);
|
|
});
|
|
|
|
// Test 2.3: Reject Invalid Version Format
|
|
it('should reject invalid semver version', () => {
|
|
const manifestInvalidVersion = {
|
|
version: 'not-semver',
|
|
installed_at: '2025-08-12T23:51:04.439Z',
|
|
install_type: 'full',
|
|
};
|
|
|
|
const result = validator.validateManifest(manifestInvalidVersion);
|
|
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.errors.some((e) => e.includes('version') && e.includes('format'))).toBe(true);
|
|
});
|
|
|
|
it('should accept valid semver versions', () => {
|
|
const validVersions = ['4.36.2', '1.0.0', '10.20.30', '0.0.1', '4.36.2-beta'];
|
|
|
|
for (const version of validVersions) {
|
|
const manifest = {
|
|
version,
|
|
installed_at: '2025-08-12T23:51:04.439Z',
|
|
install_type: 'full',
|
|
};
|
|
|
|
const result = validator.validateManifest(manifest);
|
|
expect(result.isValid).toBe(true);
|
|
}
|
|
});
|
|
|
|
// Test 2.4: Reject Invalid Date Format
|
|
it('should reject invalid ISO date', () => {
|
|
const manifestInvalidDate = {
|
|
version: '4.36.2',
|
|
installed_at: '2025-13-45T99:99:99Z',
|
|
install_type: 'full',
|
|
};
|
|
|
|
const result = validator.validateManifest(manifestInvalidDate);
|
|
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.errors.some((e) => e.includes('installed_at') && e.includes('date'))).toBe(true);
|
|
});
|
|
|
|
it('should accept valid ISO dates', () => {
|
|
const validDates = ['2025-08-12T23:51:04.439Z', '2025-01-01T00:00:00Z', '2024-12-31T23:59:59Z'];
|
|
|
|
for (const date of validDates) {
|
|
const manifest = {
|
|
version: '4.36.2',
|
|
installed_at: date,
|
|
install_type: 'full',
|
|
};
|
|
|
|
const result = validator.validateManifest(manifest);
|
|
expect(result.isValid).toBe(true);
|
|
}
|
|
});
|
|
|
|
// Test 2.5: Accept Optional Fields Missing
|
|
it('should allow missing optional fields', () => {
|
|
const manifestMinimal = {
|
|
version: '4.36.2',
|
|
installed_at: '2025-08-12T23:51:04.439Z',
|
|
install_type: 'full',
|
|
// Note: ides_setup and expansion_packs intentionally missing
|
|
};
|
|
|
|
const result = validator.validateManifest(manifestMinimal);
|
|
|
|
expect(result.isValid).toBe(true);
|
|
expect(result.errors).toEqual([]);
|
|
});
|
|
|
|
// Test 2.6: Validate Array Fields
|
|
it('should validate ides_setup is array of strings', () => {
|
|
const manifestInvalidIdes = {
|
|
version: '4.36.2',
|
|
installed_at: '2025-08-12T23:51:04.439Z',
|
|
install_type: 'full',
|
|
ides_setup: ['claude-code', 123], // Invalid: contains non-string
|
|
};
|
|
|
|
const result = validator.validateManifest(manifestInvalidIdes);
|
|
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.errors.some((e) => e.includes('ides_setup'))).toBe(true);
|
|
});
|
|
|
|
it('should accept valid ides_setup array', () => {
|
|
const manifestValidIdes = {
|
|
version: '4.36.2',
|
|
installed_at: '2025-08-12T23:51:04.439Z',
|
|
install_type: 'full',
|
|
ides_setup: ['claude-code', 'cline', 'roo'],
|
|
};
|
|
|
|
const result = validator.validateManifest(manifestValidIdes);
|
|
|
|
expect(result.isValid).toBe(true);
|
|
});
|
|
|
|
// Test 2.7: Type Validation for All Fields
|
|
it('should validate field types', () => {
|
|
const manifestWrongTypes = {
|
|
version: 123, // Should be string
|
|
installed_at: '2025-08-12T23:51:04.439Z',
|
|
install_type: 'full',
|
|
};
|
|
|
|
const result = validator.validateManifest(manifestWrongTypes);
|
|
|
|
expect(result.isValid).toBe(false);
|
|
expect(result.errors.some((e) => e.includes('type'))).toBe(true);
|
|
});
|
|
|
|
it('should validate install_type field', () => {
|
|
const validTypes = ['full', 'minimal', 'custom'];
|
|
|
|
for (const type of validTypes) {
|
|
const manifest = {
|
|
version: '4.36.2',
|
|
installed_at: '2025-08-12T23:51:04.439Z',
|
|
install_type: type,
|
|
};
|
|
|
|
const result = validator.validateManifest(manifest);
|
|
expect(result.isValid).toBe(true);
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('getRequiredFields', () => {
|
|
it('should list all required fields', () => {
|
|
const required = validator.getRequiredFields();
|
|
|
|
expect(Array.isArray(required)).toBe(true);
|
|
expect(required).toContain('version');
|
|
expect(required).toContain('installed_at');
|
|
expect(required).toContain('install_type');
|
|
});
|
|
});
|
|
|
|
describe('getOptionalFields', () => {
|
|
it('should list all optional fields', () => {
|
|
const optional = validator.getOptionalFields();
|
|
|
|
expect(Array.isArray(optional)).toBe(true);
|
|
expect(optional).toContain('ides_setup');
|
|
expect(optional).toContain('expansion_packs');
|
|
});
|
|
});
|
|
});
|