import { tap, expect } from '@git.zone/tstest/tapbundle';
import { SchematronValidator, HybridValidator } from '../ts/formats/validation/schematron.validator.js';
import { SchematronDownloader } from '../ts/formats/validation/schematron.downloader.js';
import { SchematronWorkerPool } from '../ts/formats/validation/schematron.worker.js';
tap.test('Schematron Infrastructure - should initialize correctly', async () => {
const validator = new SchematronValidator();
expect(validator).toBeInstanceOf(SchematronValidator);
expect(validator.hasRules()).toBeFalse();
});
tap.test('Schematron Infrastructure - should load Schematron rules', async () => {
const validator = new SchematronValidator();
// Load a simple test Schematron
const testSchematron = `
Invoice must have an ID
`;
await validator.loadSchematron(testSchematron, false);
expect(validator.hasRules()).toBeTrue();
});
tap.test('Schematron Infrastructure - should detect phases', async () => {
const validator = new SchematronValidator();
const schematronWithPhases = `
Invoice must have ID
`;
await validator.loadSchematron(schematronWithPhases, false);
const phases = await validator.getPhases();
expect(phases).toContain('basic');
expect(phases).toContain('extended');
});
tap.test('Schematron Downloader - should initialize', async () => {
const downloader = new SchematronDownloader('.nogit/schematron-test');
await downloader.initialize();
// Check that sources are defined
expect(downloader).toBeInstanceOf(SchematronDownloader);
});
tap.test('Schematron Downloader - should list available sources', async () => {
const { SCHEMATRON_SOURCES } = await import('../ts/formats/validation/schematron.downloader.js');
// Check EN16931 sources
expect(SCHEMATRON_SOURCES.EN16931).toBeDefined();
expect(SCHEMATRON_SOURCES.EN16931.length).toBeGreaterThan(0);
const en16931Ubl = SCHEMATRON_SOURCES.EN16931.find(s => s.format === 'UBL');
expect(en16931Ubl).toBeDefined();
expect(en16931Ubl?.name).toEqual('EN16931-UBL');
// Check PEPPOL sources
expect(SCHEMATRON_SOURCES.PEPPOL).toBeDefined();
expect(SCHEMATRON_SOURCES.PEPPOL.length).toBeGreaterThan(0);
// Check XRechnung sources
expect(SCHEMATRON_SOURCES.XRECHNUNG).toBeDefined();
expect(SCHEMATRON_SOURCES.XRECHNUNG.length).toBeGreaterThan(0);
});
tap.test('Hybrid Validator - should combine validators', async () => {
const schematronValidator = new SchematronValidator();
const hybrid = new HybridValidator(schematronValidator);
// Add a mock TypeScript validator
const mockTSValidator = {
validate: (xml: string) => [{
ruleId: 'TS-TEST-01',
severity: 'error' as const,
message: 'Test error from TS validator',
btReference: undefined,
bgReference: undefined
}]
};
hybrid.addTSValidator(mockTSValidator);
// Test validation (will only run TS validator since no Schematron loaded)
const results = await hybrid.validate('');
expect(results.length).toEqual(1);
expect(results[0].ruleId).toEqual('TS-TEST-01');
});
tap.test('Schematron Worker Pool - should initialize', async () => {
const pool = new SchematronWorkerPool(2);
// Test pool stats
const stats = pool.getStats();
expect(stats.totalWorkers).toEqual(0); // Not initialized yet
expect(stats.queuedTasks).toEqual(0);
// Note: Full worker pool test would require actual worker thread setup
// which may not work in all test environments
});
tap.test('Schematron Validator - SVRL parsing', async () => {
const validator = new SchematronValidator();
// Test SVRL output parsing
const testSVRL = `
[BR-01] Invoice must have exactly one ID
Currency is EUR
`;
// This would test the SVRL parsing logic
// The actual implementation would parse this and return ValidationResult[]
expect(testSVRL).toContain('failed-assert');
expect(testSVRL).toContain('BR-01');
});
tap.test('Schematron Integration - should handle missing files gracefully', async () => {
const validator = new SchematronValidator();
try {
await validator.loadSchematron('non-existent-file.sch', true);
expect(true).toBeFalse(); // Should not reach here
} catch (error) {
expect(error).toBeDefined();
}
});
tap.start();