UNPKG

@accordproject/concerto-linter

Version:

Concerto Linter using Spectral rulesets

150 lines (116 loc) 4.48 kB
// tests/unit/index.test.ts import { jest } from '@jest/globals'; import { lintModel } from '../../src/index'; import * as configLoader from '../../src/config-loader'; // Only mock our own functions when needed jest.mock('../../src/config-loader'); const mockedConfigLoader = configLoader as jest.Mocked<typeof configLoader>; describe('formatResults', () => { test('should format spectral results correctly', async () => { // Create a model that will likely trigger some linting results const modelWithIssues = ` namespace com.example concept class { // 'class' is a reserved keyword o String value } `; mockedConfigLoader.resolveRulesetPath.mockResolvedValue(null); const results = await lintModel(modelWithIssues, { ruleset: 'default', excludeNamespaces: [] // Don't exclude anything to see all results }); if (results.length > 0) { const result = results[0]; expect(result).toHaveProperty('code'); expect(result).toHaveProperty('message'); expect(result).toHaveProperty('severity'); expect(result).toHaveProperty('path'); expect(result).toHaveProperty('namespace'); expect(typeof result.code).toBe('string'); expect(typeof result.message).toBe('string'); expect(['error', 'warning', 'info', 'hint']).toContain(result.severity); expect(Array.isArray(result.path)).toBe(true); expect(typeof result.namespace).toBe('string'); } }); test('should exclude specified namespaces', async () => { const modelWithMultipleNamespaces = ` namespace concerto.test concept TestConcept { o String value } `; mockedConfigLoader.resolveRulesetPath.mockResolvedValue(null); const results = await lintModel(modelWithMultipleNamespaces, { ruleset: 'default', excludeNamespaces: ['concerto.*'] }); // All results should be filtered out due to namespace exclusion results.forEach(result => { expect(result.namespace).not.toMatch(/^concerto\./); }); }); test('should handle wildcard exclusion patterns', async () => { const model = ` namespace org.accordproject.test concept TestConcept { o String value } `; mockedConfigLoader.resolveRulesetPath.mockResolvedValue(null); const results = await lintModel(model, { ruleset: 'default', excludeNamespaces: ['org.accordproject.*'] }); results.forEach(result => { expect(result.namespace).not.toMatch(/^org\.accordproject\./); }); }); test('should handle exact namespace exclusion', async () => { const model = ` namespace exact.match concept TestConcept { o String value } `; mockedConfigLoader.resolveRulesetPath.mockResolvedValue(null); const results = await lintModel(model, { ruleset: 'default', excludeNamespaces: ['exact.match'] }); results.forEach(result => { expect(result.namespace).not.toBe('exact.match'); }); }); test('should handle string exclusion pattern', async () => { const model = ` namespace test.namespace concept TestConcept { o String value } `; mockedConfigLoader.resolveRulesetPath.mockResolvedValue(null); const results = await lintModel(model, { ruleset: 'default', excludeNamespaces: 'test.*' }); results.forEach(result => { expect(result.namespace).not.toMatch(/^test\./); }); }); test('should use default exclusion patterns when none specified', async () => { const concertoModel = ` namespace concerto.test concept TestConcept { o String value } `; mockedConfigLoader.resolveRulesetPath.mockResolvedValue(null); const results = await lintModel(concertoModel, { ruleset: 'default' }); // Default exclusions should filter out concerto.* namespaces results.forEach(result => { expect(result.namespace).not.toMatch(/^concerto\./); expect(result.namespace).not.toMatch(/^org\.accordproject\./); }); }); });