update
This commit is contained in:
598
test/suite/einvoice_validation/test.val-13.error-reporting.ts
Normal file
598
test/suite/einvoice_validation/test.val-13.error-reporting.ts
Normal file
@ -0,0 +1,598 @@
|
||||
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
||||
import * as plugins from '../../../ts/plugins.ts';
|
||||
import { EInvoice } from '../../../ts/classes.xinvoice.ts';
|
||||
import { CorpusLoader } from '../../helpers/corpus.loader.ts';
|
||||
import { PerformanceTracker } from '../../helpers/performance.tracker.ts';
|
||||
|
||||
const testTimeout = 300000; // 5 minutes timeout for corpus processing
|
||||
|
||||
// VAL-13: Validation Error Reporting
|
||||
// Tests validation error reporting functionality including error messages,
|
||||
// error codes, error context, and error aggregation
|
||||
|
||||
tap.test('VAL-13: Error Reporting - Error Message Quality', async (tools) => {
|
||||
const startTime = Date.now();
|
||||
|
||||
// Test validation errors with clear, actionable messages
|
||||
const errorTestCases = [
|
||||
{
|
||||
name: 'Missing Required Field',
|
||||
xml: `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
|
||||
<IssueDate>2024-01-01</IssueDate>
|
||||
<InvoiceTypeCode>380</InvoiceTypeCode>
|
||||
</Invoice>`,
|
||||
expectedErrorType: 'missing-required-field',
|
||||
expectedFieldName: 'ID'
|
||||
},
|
||||
{
|
||||
name: 'Invalid Date Format',
|
||||
xml: `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
|
||||
<ID>TEST-001</ID>
|
||||
<IssueDate>31-01-2024</IssueDate>
|
||||
<InvoiceTypeCode>380</InvoiceTypeCode>
|
||||
</Invoice>`,
|
||||
expectedErrorType: 'invalid-date-format',
|
||||
expectedFieldName: 'IssueDate'
|
||||
},
|
||||
{
|
||||
name: 'Invalid Currency Code',
|
||||
xml: `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
|
||||
<ID>TEST-001</ID>
|
||||
<IssueDate>2024-01-01</IssueDate>
|
||||
<InvoiceTypeCode>380</InvoiceTypeCode>
|
||||
<DocumentCurrencyCode>INVALID</DocumentCurrencyCode>
|
||||
</Invoice>`,
|
||||
expectedErrorType: 'invalid-currency-code',
|
||||
expectedFieldName: 'DocumentCurrencyCode'
|
||||
},
|
||||
{
|
||||
name: 'Invalid Numeric Value',
|
||||
xml: `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
|
||||
<ID>TEST-001</ID>
|
||||
<IssueDate>2024-01-01</IssueDate>
|
||||
<InvoiceTypeCode>380</InvoiceTypeCode>
|
||||
<LegalMonetaryTotal>
|
||||
<PayableAmount currencyID="EUR">NOT_A_NUMBER</PayableAmount>
|
||||
</LegalMonetaryTotal>
|
||||
</Invoice>`,
|
||||
expectedErrorType: 'invalid-numeric-value',
|
||||
expectedFieldName: 'PayableAmount'
|
||||
}
|
||||
];
|
||||
|
||||
for (const testCase of errorTestCases) {
|
||||
try {
|
||||
const invoice = new EInvoice();
|
||||
const parseResult = await invoice.fromXmlString(testCase.xml);
|
||||
|
||||
let validationResult;
|
||||
if (parseResult) {
|
||||
validationResult = await invoice.validate();
|
||||
}
|
||||
|
||||
// Expect validation to fail
|
||||
if (validationResult && validationResult.valid) {
|
||||
tools.log(`⚠ Expected validation to fail for ${testCase.name} but it passed`);
|
||||
} else {
|
||||
tools.log(`✓ ${testCase.name}: Validation correctly failed`);
|
||||
|
||||
// Check error quality if errors are available
|
||||
if (validationResult?.errors && validationResult.errors.length > 0) {
|
||||
const errors = validationResult.errors;
|
||||
|
||||
// Check for descriptive error messages
|
||||
for (const error of errors) {
|
||||
expect(error.message).toBeTruthy();
|
||||
expect(error.message.length).toBeGreaterThan(10); // Should be descriptive
|
||||
|
||||
tools.log(` Error: ${error.message}`);
|
||||
|
||||
// Check if error message contains relevant context
|
||||
if (testCase.expectedFieldName) {
|
||||
const containsFieldName = error.message.toLowerCase().includes(testCase.expectedFieldName.toLowerCase()) ||
|
||||
error.path?.includes(testCase.expectedFieldName);
|
||||
if (containsFieldName) {
|
||||
tools.log(` ✓ Error message includes field name: ${testCase.expectedFieldName}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (parseError) {
|
||||
// Parse errors are also valid for testing error reporting
|
||||
tools.log(`✓ ${testCase.name}: Parse error caught: ${parseError.message}`);
|
||||
expect(parseError.message).toBeTruthy();
|
||||
expect(parseError.message.length).toBeGreaterThan(5);
|
||||
}
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('error-reporting-message-quality', duration);
|
||||
});
|
||||
|
||||
tap.test('VAL-13: Error Reporting - Error Code Classification', async (tools) => {
|
||||
const startTime = Date.now();
|
||||
|
||||
// Test error classification and categorization
|
||||
const errorClassificationTests = [
|
||||
{
|
||||
name: 'Syntax Error',
|
||||
xml: `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
|
||||
<ID>TEST-001</ID>
|
||||
<IssueDate>2024-01-01</IssueDate>
|
||||
<InvoiceTypeCode>380</InvoiceTypeCode>
|
||||
<UnclosedTag>
|
||||
</Invoice>`,
|
||||
expectedCategory: 'syntax',
|
||||
expectedSeverity: 'error'
|
||||
},
|
||||
{
|
||||
name: 'Business Rule Violation',
|
||||
xml: `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
|
||||
<ID>TEST-001</ID>
|
||||
<IssueDate>2024-01-01</IssueDate>
|
||||
<InvoiceTypeCode>380</InvoiceTypeCode>
|
||||
<TaxTotal>
|
||||
<TaxAmount currencyID="EUR">20.00</TaxAmount>
|
||||
<TaxSubtotal>
|
||||
<TaxableAmount currencyID="EUR">100.00</TaxableAmount>
|
||||
<TaxAmount currencyID="EUR">19.00</TaxAmount>
|
||||
<TaxCategory><Percent>19.00</Percent></TaxCategory>
|
||||
</TaxSubtotal>
|
||||
</TaxTotal>
|
||||
</Invoice>`,
|
||||
expectedCategory: 'business-rule',
|
||||
expectedSeverity: 'error'
|
||||
},
|
||||
{
|
||||
name: 'Format Warning',
|
||||
xml: `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
|
||||
<ID>TEST-001</ID>
|
||||
<IssueDate>2024-01-01</IssueDate>
|
||||
<InvoiceTypeCode>380</InvoiceTypeCode>
|
||||
<Note>This is a very long note that exceeds recommended character limits for invoice notes and should trigger a warning about readability and processing efficiency in some systems</Note>
|
||||
</Invoice>`,
|
||||
expectedCategory: 'format',
|
||||
expectedSeverity: 'warning'
|
||||
}
|
||||
];
|
||||
|
||||
for (const test of errorClassificationTests) {
|
||||
try {
|
||||
const invoice = new EInvoice();
|
||||
let parseResult;
|
||||
|
||||
try {
|
||||
parseResult = await invoice.fromXmlString(test.xml);
|
||||
} catch (parseError) {
|
||||
// Handle syntax errors at parse level
|
||||
if (test.expectedCategory === 'syntax') {
|
||||
tools.log(`✓ ${test.name}: Syntax error correctly detected at parse time`);
|
||||
expect(parseError.message).toBeTruthy();
|
||||
continue;
|
||||
} else {
|
||||
throw parseError;
|
||||
}
|
||||
}
|
||||
|
||||
if (parseResult) {
|
||||
const validationResult = await invoice.validate();
|
||||
|
||||
if (validationResult && !validationResult.valid && validationResult.errors) {
|
||||
tools.log(`✓ ${test.name}: Validation errors detected`);
|
||||
|
||||
for (const error of validationResult.errors) {
|
||||
tools.log(` Error: ${error.message}`);
|
||||
|
||||
// Check error classification properties
|
||||
if (error.code) {
|
||||
tools.log(` Code: ${error.code}`);
|
||||
}
|
||||
|
||||
if (error.severity) {
|
||||
tools.log(` Severity: ${error.severity}`);
|
||||
expect(['error', 'warning', 'info']).toContain(error.severity);
|
||||
}
|
||||
|
||||
if (error.category) {
|
||||
tools.log(` Category: ${error.category}`);
|
||||
}
|
||||
|
||||
if (error.path) {
|
||||
tools.log(` Path: ${error.path}`);
|
||||
}
|
||||
}
|
||||
} else if (test.expectedCategory !== 'format') {
|
||||
tools.log(`⚠ Expected validation errors for ${test.name} but validation passed`);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
tools.log(`Error processing ${test.name}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('error-reporting-classification', duration);
|
||||
});
|
||||
|
||||
tap.test('VAL-13: Error Reporting - Error Context and Location', async (tools) => {
|
||||
const startTime = Date.now();
|
||||
|
||||
// Test error context information (line numbers, XPath, etc.)
|
||||
const contextTestXml = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
|
||||
<ID>CONTEXT-TEST-001</ID>
|
||||
<IssueDate>2024-01-01</IssueDate>
|
||||
<InvoiceTypeCode>380</InvoiceTypeCode>
|
||||
<DocumentCurrencyCode>EUR</DocumentCurrencyCode>
|
||||
<AccountingSupplierParty>
|
||||
<Party>
|
||||
<PartyName>
|
||||
<Name></Name>
|
||||
</PartyName>
|
||||
<PostalAddress>
|
||||
<StreetName>Test Street</StreetName>
|
||||
<CityName></CityName>
|
||||
<PostalZone>12345</PostalZone>
|
||||
<Country>
|
||||
<IdentificationCode>DE</IdentificationCode>
|
||||
</Country>
|
||||
</PostalAddress>
|
||||
</Party>
|
||||
</AccountingSupplierParty>
|
||||
<LegalMonetaryTotal>
|
||||
<PayableAmount currencyID="EUR">INVALID_AMOUNT</PayableAmount>
|
||||
</LegalMonetaryTotal>
|
||||
</Invoice>`;
|
||||
|
||||
try {
|
||||
const invoice = new EInvoice();
|
||||
const parseResult = await invoice.fromXmlString(contextTestXml);
|
||||
|
||||
if (parseResult) {
|
||||
const validationResult = await invoice.validate();
|
||||
|
||||
if (validationResult && !validationResult.valid && validationResult.errors) {
|
||||
tools.log(`Error context testing - found ${validationResult.errors.length} errors:`);
|
||||
|
||||
for (const error of validationResult.errors) {
|
||||
tools.log(`\nError: ${error.message}`);
|
||||
|
||||
// Check for location information
|
||||
if (error.path) {
|
||||
tools.log(` XPath/Path: ${error.path}`);
|
||||
expect(error.path).toBeTruthy();
|
||||
}
|
||||
|
||||
if (error.lineNumber) {
|
||||
tools.log(` Line: ${error.lineNumber}`);
|
||||
expect(error.lineNumber).toBeGreaterThan(0);
|
||||
}
|
||||
|
||||
if (error.columnNumber) {
|
||||
tools.log(` Column: ${error.columnNumber}`);
|
||||
expect(error.columnNumber).toBeGreaterThan(0);
|
||||
}
|
||||
|
||||
// Check for additional context
|
||||
if (error.context) {
|
||||
tools.log(` Context: ${JSON.stringify(error.context)}`);
|
||||
}
|
||||
|
||||
if (error.element) {
|
||||
tools.log(` Element: ${error.element}`);
|
||||
}
|
||||
}
|
||||
|
||||
tools.log(`✓ Error context information available`);
|
||||
} else {
|
||||
tools.log(`⚠ Expected validation errors but validation passed`);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
tools.log(`Context test failed: ${error.message}`);
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('error-reporting-context', duration);
|
||||
});
|
||||
|
||||
tap.test('VAL-13: Error Reporting - Error Aggregation and Summarization', async (tools) => {
|
||||
const startTime = Date.now();
|
||||
|
||||
// Test error aggregation for multiple issues
|
||||
const multiErrorXml = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
|
||||
<ID></ID>
|
||||
<IssueDate>invalid-date</IssueDate>
|
||||
<InvoiceTypeCode>999</InvoiceTypeCode>
|
||||
<DocumentCurrencyCode>INVALID</DocumentCurrencyCode>
|
||||
<AccountingSupplierParty>
|
||||
<Party>
|
||||
<PartyName>
|
||||
<Name></Name>
|
||||
</PartyName>
|
||||
</Party>
|
||||
</AccountingSupplierParty>
|
||||
<AccountingCustomerParty>
|
||||
<Party>
|
||||
<PartyName>
|
||||
<Name></Name>
|
||||
</PartyName>
|
||||
</Party>
|
||||
</AccountingCustomerParty>
|
||||
<InvoiceLine>
|
||||
<ID></ID>
|
||||
<InvoicedQuantity unitCode="">0</InvoicedQuantity>
|
||||
<LineExtensionAmount currencyID="EUR">invalid-amount</LineExtensionAmount>
|
||||
</InvoiceLine>
|
||||
<LegalMonetaryTotal>
|
||||
<PayableAmount currencyID="EUR">another-invalid-amount</PayableAmount>
|
||||
</LegalMonetaryTotal>
|
||||
</Invoice>`;
|
||||
|
||||
try {
|
||||
const invoice = new EInvoice();
|
||||
const parseResult = await invoice.fromXmlString(multiErrorXml);
|
||||
|
||||
if (parseResult) {
|
||||
const validationResult = await invoice.validate();
|
||||
|
||||
if (validationResult && !validationResult.valid && validationResult.errors) {
|
||||
const errors = validationResult.errors;
|
||||
tools.log(`Error aggregation test - found ${errors.length} errors:`);
|
||||
|
||||
// Group errors by category
|
||||
const errorsByCategory = {};
|
||||
const errorsBySeverity = {};
|
||||
|
||||
for (const error of errors) {
|
||||
// Count by category
|
||||
const category = error.category || 'unknown';
|
||||
errorsByCategory[category] = (errorsByCategory[category] || 0) + 1;
|
||||
|
||||
// Count by severity
|
||||
const severity = error.severity || 'error';
|
||||
errorsBySeverity[severity] = (errorsBySeverity[severity] || 0) + 1;
|
||||
|
||||
tools.log(` - ${error.message}`);
|
||||
if (error.path) {
|
||||
tools.log(` Path: ${error.path}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Display error summary
|
||||
tools.log(`\nError Summary:`);
|
||||
tools.log(` Total errors: ${errors.length}`);
|
||||
|
||||
tools.log(` By category:`);
|
||||
for (const [category, count] of Object.entries(errorsByCategory)) {
|
||||
tools.log(` ${category}: ${count}`);
|
||||
}
|
||||
|
||||
tools.log(` By severity:`);
|
||||
for (const [severity, count] of Object.entries(errorsBySeverity)) {
|
||||
tools.log(` ${severity}: ${count}`);
|
||||
}
|
||||
|
||||
// Expect multiple errors to be found
|
||||
expect(errors.length).toBeGreaterThan(3);
|
||||
|
||||
// Check that errors are properly structured
|
||||
for (const error of errors) {
|
||||
expect(error.message).toBeTruthy();
|
||||
expect(typeof error.message).toBe('string');
|
||||
}
|
||||
|
||||
tools.log(`✓ Error aggregation and categorization working`);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
tools.log(`Error aggregation test failed: ${error.message}`);
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('error-reporting-aggregation', duration);
|
||||
});
|
||||
|
||||
tap.test('VAL-13: Error Reporting - Localized Error Messages', async (tools) => {
|
||||
const startTime = Date.now();
|
||||
|
||||
// Test error message localization (if supported)
|
||||
const localizationTestXml = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
|
||||
<ID>LOC-TEST-001</ID>
|
||||
<IssueDate>2024-01-01</IssueDate>
|
||||
<InvoiceTypeCode>380</InvoiceTypeCode>
|
||||
<DocumentCurrencyCode>INVALID</DocumentCurrencyCode>
|
||||
</Invoice>`;
|
||||
|
||||
const locales = ['en', 'de', 'fr'];
|
||||
|
||||
for (const locale of locales) {
|
||||
try {
|
||||
const invoice = new EInvoice();
|
||||
|
||||
// Set locale if the API supports it
|
||||
if (typeof invoice.setLocale === 'function') {
|
||||
invoice.setLocale(locale);
|
||||
tools.log(`Testing error messages in locale: ${locale}`);
|
||||
} else {
|
||||
tools.log(`Locale setting not supported, testing default messages`);
|
||||
}
|
||||
|
||||
const parseResult = await invoice.fromXmlString(localizationTestXml);
|
||||
|
||||
if (parseResult) {
|
||||
const validationResult = await invoice.validate();
|
||||
|
||||
if (validationResult && !validationResult.valid && validationResult.errors) {
|
||||
for (const error of validationResult.errors) {
|
||||
tools.log(` ${locale}: ${error.message}`);
|
||||
|
||||
// Check that error message is not empty and reasonably descriptive
|
||||
expect(error.message).toBeTruthy();
|
||||
expect(error.message.length).toBeGreaterThan(5);
|
||||
|
||||
// Check for locale-specific characteristics (if implemented)
|
||||
if (locale === 'de' && error.message.includes('ungültig')) {
|
||||
tools.log(` ✓ German localization detected`);
|
||||
} else if (locale === 'fr' && error.message.includes('invalide')) {
|
||||
tools.log(` ✓ French localization detected`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
tools.log(`Localization test failed for ${locale}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('error-reporting-localization', duration);
|
||||
});
|
||||
|
||||
tap.test('VAL-13: Error Reporting - Corpus Error Analysis', { timeout: testTimeout }, async (tools) => {
|
||||
const startTime = Date.now();
|
||||
|
||||
const errorStatistics = {
|
||||
totalFiles: 0,
|
||||
filesWithErrors: 0,
|
||||
totalErrors: 0,
|
||||
errorsByCategory: {},
|
||||
errorsBySeverity: {},
|
||||
mostCommonErrors: {}
|
||||
};
|
||||
|
||||
try {
|
||||
// Analyze errors across corpus files
|
||||
const categories = ['UBL_XML_RECHNUNG', 'CII_XML_RECHNUNG'];
|
||||
|
||||
for (const category of categories) {
|
||||
try {
|
||||
const files = await CorpusLoader.getFiles(category);
|
||||
|
||||
for (const filePath of files.slice(0, 8)) { // Process first 8 files per category
|
||||
errorStatistics.totalFiles++;
|
||||
|
||||
try {
|
||||
const invoice = new EInvoice();
|
||||
const parseResult = await invoice.fromFile(filePath);
|
||||
|
||||
if (parseResult) {
|
||||
const validationResult = await invoice.validate();
|
||||
|
||||
if (validationResult && !validationResult.valid && validationResult.errors) {
|
||||
errorStatistics.filesWithErrors++;
|
||||
errorStatistics.totalErrors += validationResult.errors.length;
|
||||
|
||||
for (const error of validationResult.errors) {
|
||||
// Count by category
|
||||
const category = error.category || 'unknown';
|
||||
errorStatistics.errorsByCategory[category] = (errorStatistics.errorsByCategory[category] || 0) + 1;
|
||||
|
||||
// Count by severity
|
||||
const severity = error.severity || 'error';
|
||||
errorStatistics.errorsBySeverity[severity] = (errorStatistics.errorsBySeverity[severity] || 0) + 1;
|
||||
|
||||
// Track common error patterns
|
||||
const errorKey = error.code || error.message.substring(0, 50);
|
||||
errorStatistics.mostCommonErrors[errorKey] = (errorStatistics.mostCommonErrors[errorKey] || 0) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
errorStatistics.filesWithErrors++;
|
||||
errorStatistics.totalErrors++;
|
||||
tools.log(`Parse error in ${plugins.path.basename(filePath)}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
tools.log(`Failed to process category ${category}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Display error analysis results
|
||||
tools.log(`\n=== Corpus Error Analysis ===`);
|
||||
tools.log(`Total files analyzed: ${errorStatistics.totalFiles}`);
|
||||
tools.log(`Files with errors: ${errorStatistics.filesWithErrors} (${(errorStatistics.filesWithErrors / errorStatistics.totalFiles * 100).toFixed(1)}%)`);
|
||||
tools.log(`Total errors found: ${errorStatistics.totalErrors}`);
|
||||
tools.log(`Average errors per file: ${(errorStatistics.totalErrors / errorStatistics.totalFiles).toFixed(1)}`);
|
||||
|
||||
if (Object.keys(errorStatistics.errorsByCategory).length > 0) {
|
||||
tools.log(`\nErrors by category:`);
|
||||
for (const [category, count] of Object.entries(errorStatistics.errorsByCategory)) {
|
||||
tools.log(` ${category}: ${count}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(errorStatistics.errorsBySeverity).length > 0) {
|
||||
tools.log(`\nErrors by severity:`);
|
||||
for (const [severity, count] of Object.entries(errorStatistics.errorsBySeverity)) {
|
||||
tools.log(` ${severity}: ${count}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Show most common errors
|
||||
const commonErrors = Object.entries(errorStatistics.mostCommonErrors)
|
||||
.sort(([,a], [,b]) => b - a)
|
||||
.slice(0, 5);
|
||||
|
||||
if (commonErrors.length > 0) {
|
||||
tools.log(`\nMost common errors:`);
|
||||
for (const [errorKey, count] of commonErrors) {
|
||||
tools.log(` ${count}x: ${errorKey}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Error analysis should complete successfully
|
||||
expect(errorStatistics.totalFiles).toBeGreaterThan(0);
|
||||
|
||||
} catch (error) {
|
||||
tools.log(`Corpus error analysis failed: ${error.message}`);
|
||||
throw error;
|
||||
}
|
||||
|
||||
const totalDuration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('error-reporting-corpus', totalDuration);
|
||||
|
||||
expect(totalDuration).toBeLessThan(120000); // 2 minutes max
|
||||
tools.log(`Error analysis completed in ${totalDuration}ms`);
|
||||
});
|
||||
|
||||
tap.test('VAL-13: Performance Summary', async (tools) => {
|
||||
const operations = [
|
||||
'error-reporting-message-quality',
|
||||
'error-reporting-classification',
|
||||
'error-reporting-context',
|
||||
'error-reporting-aggregation',
|
||||
'error-reporting-localization',
|
||||
'error-reporting-corpus'
|
||||
];
|
||||
|
||||
tools.log(`\n=== Error Reporting Performance Summary ===`);
|
||||
|
||||
for (const operation of operations) {
|
||||
const summary = await PerformanceTracker.getSummary(operation);
|
||||
if (summary) {
|
||||
tools.log(`${operation}:`);
|
||||
tools.log(` avg=${summary.average}ms, min=${summary.min}ms, max=${summary.max}ms, p95=${summary.p95}ms`);
|
||||
}
|
||||
}
|
||||
|
||||
tools.log(`\nError reporting testing completed successfully.`);
|
||||
});
|
Reference in New Issue
Block a user