fix(compliance): improve compliance
This commit is contained in:
@ -1,8 +1,8 @@
|
||||
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';
|
||||
import * as plugins from '../../../ts/plugins.js';
|
||||
import { EInvoice } from '../../../ts/index.js';
|
||||
import { CorpusLoader } from '../../helpers/corpus.loader.js';
|
||||
import { PerformanceTracker } from '../../helpers/performance.tracker.js';
|
||||
|
||||
const testTimeout = 300000; // 5 minutes timeout for corpus processing
|
||||
|
||||
@ -41,16 +41,16 @@ tap.test('VAL-09: Semantic Level Validation - Data Type Validation', async (tool
|
||||
|
||||
if (test.valid) {
|
||||
expect(parseResult).toBeTruthy();
|
||||
tools.log(`✓ Valid numeric value '${test.value}' accepted for ${test.field}`);
|
||||
console.log(`✓ Valid numeric value '${test.value}' accepted for ${test.field}`);
|
||||
} else {
|
||||
// Should either fail parsing or validation
|
||||
const validationResult = await invoice.validate();
|
||||
expect(validationResult.valid).toBe(false);
|
||||
tools.log(`✓ Invalid numeric value '${test.value}' rejected for ${test.field}`);
|
||||
expect(validationResult.valid).toBeFalse();
|
||||
console.log(`✓ Invalid numeric value '${test.value}' rejected for ${test.field}`);
|
||||
}
|
||||
} catch (error) {
|
||||
if (!test.valid) {
|
||||
tools.log(`✓ Invalid numeric value '${test.value}' properly rejected with error: ${error.message}`);
|
||||
console.log(`✓ Invalid numeric value '${test.value}' properly rejected with error: ${error.message}`);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
@ -58,7 +58,7 @@ tap.test('VAL-09: Semantic Level Validation - Data Type Validation', async (tool
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('semantic-validation-datatypes', duration);
|
||||
// PerformanceTracker.recordMetric('semantic-validation-datatypes', duration);
|
||||
});
|
||||
|
||||
tap.test('VAL-09: Semantic Level Validation - Date Format Validation', async (tools) => {
|
||||
@ -94,18 +94,18 @@ tap.test('VAL-09: Semantic Level Validation - Date Format Validation', async (to
|
||||
expect(parseResult).toBeTruthy();
|
||||
const validationResult = await invoice.validate();
|
||||
expect(validationResult.valid).toBeTrue();
|
||||
tools.log(`✓ Valid date '${test.value}' accepted`);
|
||||
console.log(`✓ Valid date '${test.value}' accepted`);
|
||||
} else {
|
||||
// Should either fail parsing or validation
|
||||
if (parseResult) {
|
||||
const validationResult = await invoice.validate();
|
||||
expect(validationResult.valid).toBe(false);
|
||||
expect(validationResult.valid).toBeFalse();
|
||||
}
|
||||
tools.log(`✓ Invalid date '${test.value}' rejected`);
|
||||
console.log(`✓ Invalid date '${test.value}' rejected`);
|
||||
}
|
||||
} catch (error) {
|
||||
if (!test.valid) {
|
||||
tools.log(`✓ Invalid date '${test.value}' properly rejected with error: ${error.message}`);
|
||||
console.log(`✓ Invalid date '${test.value}' properly rejected with error: ${error.message}`);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
@ -113,7 +113,7 @@ tap.test('VAL-09: Semantic Level Validation - Date Format Validation', async (to
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('semantic-validation-dates', duration);
|
||||
// PerformanceTracker.recordMetric('semantic-validation-dates', duration);
|
||||
});
|
||||
|
||||
tap.test('VAL-09: Semantic Level Validation - Currency Code Validation', async (tools) => {
|
||||
@ -154,18 +154,18 @@ tap.test('VAL-09: Semantic Level Validation - Currency Code Validation', async (
|
||||
|
||||
if (test.valid) {
|
||||
expect(parseResult).toBeTruthy();
|
||||
tools.log(`✓ Valid currency code '${test.code}' accepted`);
|
||||
console.log(`✓ Valid currency code '${test.code}' accepted`);
|
||||
} else {
|
||||
// Should either fail parsing or validation
|
||||
if (parseResult) {
|
||||
const validationResult = await invoice.validate();
|
||||
expect(validationResult.valid).toBe(false);
|
||||
expect(validationResult.valid).toBeFalse();
|
||||
}
|
||||
tools.log(`✓ Invalid currency code '${test.code}' rejected`);
|
||||
console.log(`✓ Invalid currency code '${test.code}' rejected`);
|
||||
}
|
||||
} catch (error) {
|
||||
if (!test.valid) {
|
||||
tools.log(`✓ Invalid currency code '${test.code}' properly rejected with error: ${error.message}`);
|
||||
console.log(`✓ Invalid currency code '${test.code}' properly rejected with error: ${error.message}`);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
@ -173,7 +173,7 @@ tap.test('VAL-09: Semantic Level Validation - Currency Code Validation', async (
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('semantic-validation-currency', duration);
|
||||
// PerformanceTracker.recordMetric('semantic-validation-currency', duration);
|
||||
});
|
||||
|
||||
tap.test('VAL-09: Semantic Level Validation - Cross-Field Dependencies', async (tools) => {
|
||||
@ -233,19 +233,19 @@ tap.test('VAL-09: Semantic Level Validation - Cross-Field Dependencies', async (
|
||||
|
||||
if (test.valid) {
|
||||
expect(validationResult.valid).toBeTrue();
|
||||
tools.log(`✓ ${test.name}: Valid cross-field dependency accepted`);
|
||||
console.log(`✓ ${test.name}: Valid cross-field dependency accepted`);
|
||||
} else {
|
||||
expect(validationResult.valid).toBe(false);
|
||||
tools.log(`✓ ${test.name}: Invalid cross-field dependency rejected`);
|
||||
expect(validationResult.valid).toBeFalse();
|
||||
console.log(`✓ ${test.name}: Invalid cross-field dependency rejected`);
|
||||
}
|
||||
} else if (!test.valid) {
|
||||
tools.log(`✓ ${test.name}: Invalid dependency rejected at parse time`);
|
||||
console.log(`✓ ${test.name}: Invalid dependency rejected at parse time`);
|
||||
} else {
|
||||
throw new Error(`Expected valid parse for ${test.name}`);
|
||||
}
|
||||
} catch (error) {
|
||||
if (!test.valid) {
|
||||
tools.log(`✓ ${test.name}: Invalid dependency properly rejected with error: ${error.message}`);
|
||||
console.log(`✓ ${test.name}: Invalid dependency properly rejected with error: ${error.message}`);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
@ -253,7 +253,7 @@ tap.test('VAL-09: Semantic Level Validation - Cross-Field Dependencies', async (
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('semantic-validation-dependencies', duration);
|
||||
// PerformanceTracker.recordMetric('semantic-validation-dependencies', duration);
|
||||
});
|
||||
|
||||
tap.test('VAL-09: Semantic Level Validation - Value Range Validation', async (tools) => {
|
||||
@ -314,18 +314,18 @@ tap.test('VAL-09: Semantic Level Validation - Value Range Validation', async (to
|
||||
|
||||
if (test.valid) {
|
||||
expect(parseResult).toBeTruthy();
|
||||
tools.log(`✓ ${test.description}: Valid value '${test.value}' accepted for ${test.field}`);
|
||||
console.log(`✓ ${test.description}: Valid value '${test.value}' accepted for ${test.field}`);
|
||||
} else {
|
||||
// Should either fail parsing or validation
|
||||
if (parseResult) {
|
||||
const validationResult = await invoice.validate();
|
||||
expect(validationResult.valid).toBe(false);
|
||||
expect(validationResult.valid).toBeFalse();
|
||||
}
|
||||
tools.log(`✓ ${test.description}: Invalid value '${test.value}' rejected for ${test.field}`);
|
||||
console.log(`✓ ${test.description}: Invalid value '${test.value}' rejected for ${test.field}`);
|
||||
}
|
||||
} catch (error) {
|
||||
if (!test.valid) {
|
||||
tools.log(`✓ ${test.description}: Invalid value properly rejected with error: ${error.message}`);
|
||||
console.log(`✓ ${test.description}: Invalid value properly rejected with error: ${error.message}`);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
@ -333,7 +333,7 @@ tap.test('VAL-09: Semantic Level Validation - Value Range Validation', async (to
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('semantic-validation-ranges', duration);
|
||||
// PerformanceTracker.recordMetric('semantic-validation-ranges', duration);
|
||||
});
|
||||
|
||||
tap.test('VAL-09: Semantic Level Validation - Corpus Semantic Validation', { timeout: testTimeout }, async (tools) => {
|
||||
@ -366,7 +366,7 @@ tap.test('VAL-09: Semantic Level Validation - Corpus Semantic Validation', { tim
|
||||
|
||||
if (hasSemanticErrors) {
|
||||
semanticErrors++;
|
||||
tools.log(`Semantic validation errors in ${plugins.path.basename(filePath)}`);
|
||||
console.log(`Semantic validation errors in ${plugins.path.basename(filePath)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -375,35 +375,35 @@ tap.test('VAL-09: Semantic Level Validation - Corpus Semantic Validation', { tim
|
||||
if (processedFiles % 5 === 0) {
|
||||
const currentDuration = Date.now() - startTime;
|
||||
const avgPerFile = currentDuration / processedFiles;
|
||||
tools.log(`Processed ${processedFiles} files, avg ${avgPerFile.toFixed(0)}ms per file`);
|
||||
console.log(`Processed ${processedFiles} files, avg ${avgPerFile.toFixed(0)}ms per file`);
|
||||
}
|
||||
} catch (error) {
|
||||
tools.log(`Failed to process ${plugins.path.basename(filePath)}: ${error.message}`);
|
||||
console.log(`Failed to process ${plugins.path.basename(filePath)}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
const successRate = processedFiles > 0 ? (validFiles / processedFiles) * 100 : 0;
|
||||
const semanticErrorRate = processedFiles > 0 ? (semanticErrors / processedFiles) * 100 : 0;
|
||||
|
||||
tools.log(`Semantic validation completed:`);
|
||||
tools.log(`- Processed: ${processedFiles} files`);
|
||||
tools.log(`- Valid: ${validFiles} files (${successRate.toFixed(1)}%)`);
|
||||
tools.log(`- Semantic errors: ${semanticErrors} files (${semanticErrorRate.toFixed(1)}%)`);
|
||||
console.log(`Semantic validation completed:`);
|
||||
console.log(`- Processed: ${processedFiles} files`);
|
||||
console.log(`- Valid: ${validFiles} files (${successRate.toFixed(1)}%)`);
|
||||
console.log(`- Semantic errors: ${semanticErrors} files (${semanticErrorRate.toFixed(1)}%)`);
|
||||
|
||||
// Semantic validation should have high success rate for well-formed corpus
|
||||
expect(successRate).toBeGreaterThan(70);
|
||||
|
||||
} catch (error) {
|
||||
tools.log(`Corpus semantic validation failed: ${error.message}`);
|
||||
console.log(`Corpus semantic validation failed: ${error.message}`);
|
||||
throw error;
|
||||
}
|
||||
|
||||
const totalDuration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('semantic-validation-corpus', totalDuration);
|
||||
// PerformanceTracker.recordMetric('semantic-validation-corpus', totalDuration);
|
||||
|
||||
// Performance expectation: should complete within reasonable time
|
||||
expect(totalDuration).toBeLessThan(60000); // 60 seconds max
|
||||
tools.log(`Semantic validation performance: ${totalDuration}ms total`);
|
||||
console.log(`Semantic validation performance: ${totalDuration}ms total`);
|
||||
});
|
||||
|
||||
tap.test('VAL-09: Performance Summary', async (tools) => {
|
||||
@ -419,7 +419,13 @@ tap.test('VAL-09: Performance Summary', async (tools) => {
|
||||
for (const operation of operations) {
|
||||
const summary = await PerformanceTracker.getSummary(operation);
|
||||
if (summary) {
|
||||
tools.log(`${operation}: avg=${summary.average}ms, min=${summary.min}ms, max=${summary.max}ms, p95=${summary.p95}ms`);
|
||||
console.log(`${operation}: avg=${summary.average}ms, min=${summary.min}ms, max=${summary.max}ms, p95=${summary.p95}ms`);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Start the test
|
||||
tap.start();
|
||||
|
||||
// Export for test runner compatibility
|
||||
export default tap;
|
@ -1,8 +1,8 @@
|
||||
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';
|
||||
import * as plugins from '../../../ts/plugins.js';
|
||||
import { EInvoice } from '../../../ts/index.js';
|
||||
import { CorpusLoader } from '../../helpers/corpus.loader.js';
|
||||
import { PerformanceTracker } from '../../helpers/performance.tracker.js';
|
||||
|
||||
const testTimeout = 300000; // 5 minutes timeout for corpus processing
|
||||
|
||||
@ -85,17 +85,17 @@ tap.test('VAL-10: Business Level Validation - Invoice Totals Consistency', async
|
||||
|
||||
if (test.valid) {
|
||||
expect(validationResult.valid).toBeTrue();
|
||||
tools.log(`✓ ${test.name}: Valid business logic accepted`);
|
||||
console.log(`✓ ${test.name}: Valid business logic accepted`);
|
||||
} else {
|
||||
expect(validationResult.valid).toBe(false);
|
||||
tools.log(`✓ ${test.name}: Invalid business logic rejected`);
|
||||
expect(validationResult.valid).toBeFalse();
|
||||
console.log(`✓ ${test.name}: Invalid business logic rejected`);
|
||||
}
|
||||
} else if (!test.valid) {
|
||||
tools.log(`✓ ${test.name}: Invalid invoice rejected at parse time`);
|
||||
console.log(`✓ ${test.name}: Invalid invoice rejected at parse time`);
|
||||
}
|
||||
} catch (error) {
|
||||
if (!test.valid) {
|
||||
tools.log(`✓ ${test.name}: Invalid business logic properly rejected: ${error.message}`);
|
||||
console.log(`✓ ${test.name}: Invalid business logic properly rejected: ${error.message}`);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
@ -103,7 +103,7 @@ tap.test('VAL-10: Business Level Validation - Invoice Totals Consistency', async
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('business-validation-totals', duration);
|
||||
// PerformanceTracker.recordMetric('business-validation-totals', duration);
|
||||
});
|
||||
|
||||
tap.test('VAL-10: Business Level Validation - Tax Calculation Consistency', async (tools) => {
|
||||
@ -189,26 +189,26 @@ tap.test('VAL-10: Business Level Validation - Tax Calculation Consistency', asyn
|
||||
);
|
||||
|
||||
if (!hasOnlyRoundingErrors) {
|
||||
tools.log(`Validation failed for ${test.name}: ${errors.map(e => e.message).join(', ')}`);
|
||||
console.log(`Validation failed for ${test.name}: ${errors.map(e => e.message).join(', ')}`);
|
||||
}
|
||||
}
|
||||
tools.log(`✓ ${test.name}: Tax calculation processed`);
|
||||
console.log(`✓ ${test.name}: Tax calculation processed`);
|
||||
} else {
|
||||
expect(validationResult.valid).toBe(false);
|
||||
tools.log(`✓ ${test.name}: Invalid tax calculation rejected`);
|
||||
expect(validationResult.valid).toBeFalse();
|
||||
console.log(`✓ ${test.name}: Invalid tax calculation rejected`);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
if (!test.valid) {
|
||||
tools.log(`✓ ${test.name}: Invalid calculation properly rejected: ${error.message}`);
|
||||
console.log(`✓ ${test.name}: Invalid calculation properly rejected: ${error.message}`);
|
||||
} else {
|
||||
tools.log(`⚠ ${test.name}: Unexpected error: ${error.message}`);
|
||||
console.log(`⚠ ${test.name}: Unexpected error: ${error.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('business-validation-tax', duration);
|
||||
// PerformanceTracker.recordMetric('business-validation-tax', duration);
|
||||
});
|
||||
|
||||
tap.test('VAL-10: Business Level Validation - Payment Terms Validation', async (tools) => {
|
||||
@ -270,23 +270,23 @@ tap.test('VAL-10: Business Level Validation - Payment Terms Validation', async (
|
||||
|
||||
if (test.valid) {
|
||||
// Valid payment terms should be accepted
|
||||
tools.log(`✓ ${test.name}: Valid payment terms accepted`);
|
||||
console.log(`✓ ${test.name}: Valid payment terms accepted`);
|
||||
} else {
|
||||
expect(validationResult.valid).toBe(false);
|
||||
tools.log(`✓ ${test.name}: Invalid payment terms rejected`);
|
||||
expect(validationResult.valid).toBeFalse();
|
||||
console.log(`✓ ${test.name}: Invalid payment terms rejected`);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
if (!test.valid) {
|
||||
tools.log(`✓ ${test.name}: Invalid payment terms properly rejected: ${error.message}`);
|
||||
console.log(`✓ ${test.name}: Invalid payment terms properly rejected: ${error.message}`);
|
||||
} else {
|
||||
tools.log(`⚠ ${test.name}: Unexpected error: ${error.message}`);
|
||||
console.log(`⚠ ${test.name}: Unexpected error: ${error.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('business-validation-payment', duration);
|
||||
// PerformanceTracker.recordMetric('business-validation-payment', duration);
|
||||
});
|
||||
|
||||
tap.test('VAL-10: Business Level Validation - Business Rules Compliance', async (tools) => {
|
||||
@ -344,17 +344,17 @@ tap.test('VAL-10: Business Level Validation - Business Rules Compliance', async
|
||||
|
||||
if (test.valid) {
|
||||
expect(validationResult.valid).toBeTrue();
|
||||
tools.log(`✓ ${test.name}: Business rule compliance verified`);
|
||||
console.log(`✓ ${test.name}: Business rule compliance verified`);
|
||||
} else {
|
||||
expect(validationResult.valid).toBe(false);
|
||||
tools.log(`✓ ${test.name}: Business rule violation detected`);
|
||||
expect(validationResult.valid).toBeFalse();
|
||||
console.log(`✓ ${test.name}: Business rule violation detected`);
|
||||
}
|
||||
} else if (!test.valid) {
|
||||
tools.log(`✓ ${test.name}: Invalid invoice rejected at parse time`);
|
||||
console.log(`✓ ${test.name}: Invalid invoice rejected at parse time`);
|
||||
}
|
||||
} catch (error) {
|
||||
if (!test.valid) {
|
||||
tools.log(`✓ ${test.name}: Business rule violation properly caught: ${error.message}`);
|
||||
console.log(`✓ ${test.name}: Business rule violation properly caught: ${error.message}`);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
@ -362,7 +362,7 @@ tap.test('VAL-10: Business Level Validation - Business Rules Compliance', async
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('business-validation-rules', duration);
|
||||
// PerformanceTracker.recordMetric('business-validation-rules', duration);
|
||||
});
|
||||
|
||||
tap.test('VAL-10: Business Level Validation - Multi-Line Invoice Logic', async (tools) => {
|
||||
@ -438,18 +438,18 @@ tap.test('VAL-10: Business Level Validation - Multi-Line Invoice Logic', async (
|
||||
|
||||
// Multi-line business logic should be valid
|
||||
if (!validationResult.valid) {
|
||||
tools.log(`Multi-line validation issues: ${validationResult.errors?.map(e => e.message).join(', ')}`);
|
||||
console.log(`Multi-line validation issues: ${validationResult.errors?.map(e => e.message).join(', ')}`);
|
||||
}
|
||||
|
||||
tools.log(`✓ Multi-line invoice business logic validation completed`);
|
||||
console.log(`✓ Multi-line invoice business logic validation completed`);
|
||||
|
||||
} catch (error) {
|
||||
tools.log(`Multi-line invoice test failed: ${error.message}`);
|
||||
console.log(`Multi-line invoice test failed: ${error.message}`);
|
||||
throw error;
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('business-validation-multiline', duration);
|
||||
// PerformanceTracker.recordMetric('business-validation-multiline', duration);
|
||||
});
|
||||
|
||||
tap.test('VAL-10: Business Level Validation - Corpus Business Logic', { timeout: testTimeout }, async (tools) => {
|
||||
@ -481,36 +481,36 @@ tap.test('VAL-10: Business Level Validation - Corpus Business Logic', { timeout:
|
||||
|
||||
if (hasBusinessErrors) {
|
||||
businessLogicErrors++;
|
||||
tools.log(`Business logic errors in ${plugins.path.basename(filePath)}`);
|
||||
console.log(`Business logic errors in ${plugins.path.basename(filePath)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
tools.log(`Failed to process ${plugins.path.basename(filePath)}: ${error.message}`);
|
||||
console.log(`Failed to process ${plugins.path.basename(filePath)}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
const businessLogicSuccessRate = processedFiles > 0 ? (validBusinessLogic / processedFiles) * 100 : 0;
|
||||
const businessErrorRate = processedFiles > 0 ? (businessLogicErrors / processedFiles) * 100 : 0;
|
||||
|
||||
tools.log(`Business logic validation completed:`);
|
||||
tools.log(`- Processed: ${processedFiles} files`);
|
||||
tools.log(`- Valid business logic: ${validBusinessLogic} files (${businessLogicSuccessRate.toFixed(1)}%)`);
|
||||
tools.log(`- Business logic errors: ${businessLogicErrors} files (${businessErrorRate.toFixed(1)}%)`);
|
||||
console.log(`Business logic validation completed:`);
|
||||
console.log(`- Processed: ${processedFiles} files`);
|
||||
console.log(`- Valid business logic: ${validBusinessLogic} files (${businessLogicSuccessRate.toFixed(1)}%)`);
|
||||
console.log(`- Business logic errors: ${businessLogicErrors} files (${businessErrorRate.toFixed(1)}%)`);
|
||||
|
||||
// Business logic should have reasonable success rate
|
||||
expect(businessLogicSuccessRate).toBeGreaterThan(60);
|
||||
|
||||
} catch (error) {
|
||||
tools.log(`Corpus business validation failed: ${error.message}`);
|
||||
console.log(`Corpus business validation failed: ${error.message}`);
|
||||
throw error;
|
||||
}
|
||||
|
||||
const totalDuration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('business-validation-corpus', totalDuration);
|
||||
// PerformanceTracker.recordMetric('business-validation-corpus', totalDuration);
|
||||
|
||||
expect(totalDuration).toBeLessThan(120000); // 2 minutes max
|
||||
tools.log(`Business validation performance: ${totalDuration}ms total`);
|
||||
console.log(`Business validation performance: ${totalDuration}ms total`);
|
||||
});
|
||||
|
||||
tap.test('VAL-10: Performance Summary', async (tools) => {
|
||||
@ -526,7 +526,13 @@ tap.test('VAL-10: Performance Summary', async (tools) => {
|
||||
for (const operation of operations) {
|
||||
const summary = await PerformanceTracker.getSummary(operation);
|
||||
if (summary) {
|
||||
tools.log(`${operation}: avg=${summary.average}ms, min=${summary.min}ms, max=${summary.max}ms, p95=${summary.p95}ms`);
|
||||
console.log(`${operation}: avg=${summary.average}ms, min=${summary.min}ms, max=${summary.max}ms, p95=${summary.p95}ms`);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Start the test
|
||||
tap.start();
|
||||
|
||||
// Export for test runner compatibility
|
||||
export default tap;
|
@ -1,8 +1,8 @@
|
||||
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';
|
||||
import * as plugins from '../../../ts/plugins.js';
|
||||
import { EInvoice } from '../../../ts/index.js';
|
||||
import { CorpusLoader } from '../../helpers/corpus.loader.js';
|
||||
import { PerformanceTracker } from '../../helpers/performance.tracker.js';
|
||||
|
||||
const testTimeout = 300000; // 5 minutes timeout for corpus processing
|
||||
|
||||
@ -41,7 +41,7 @@ tap.test('VAL-11: Custom Validation Rules - Invoice Number Format Rules', async
|
||||
];
|
||||
|
||||
for (const rule of invoiceNumberRules) {
|
||||
tools.log(`Testing custom rule: ${rule.name}`);
|
||||
console.log(`Testing custom rule: ${rule.name}`);
|
||||
|
||||
for (const testValue of rule.testValues) {
|
||||
const xml = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
@ -62,20 +62,20 @@ tap.test('VAL-11: Custom Validation Rules - Invoice Number Format Rules', async
|
||||
|
||||
if (testValue.valid) {
|
||||
expect(isValid).toBeTrue();
|
||||
tools.log(`✓ Valid format '${testValue.value}' accepted by ${rule.name}`);
|
||||
console.log(`✓ Valid format '${testValue.value}' accepted by ${rule.name}`);
|
||||
} else {
|
||||
expect(isValid).toBe(false);
|
||||
tools.log(`✓ Invalid format '${testValue.value}' rejected by ${rule.name}`);
|
||||
expect(isValid).toBeFalse();
|
||||
console.log(`✓ Invalid format '${testValue.value}' rejected by ${rule.name}`);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
tools.log(`Error testing '${testValue.value}': ${error.message}`);
|
||||
console.log(`Error testing '${testValue.value}': ${error.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('custom-validation-invoice-format', duration);
|
||||
// PerformanceTracker.recordMetric('custom-validation-invoice-format', duration);
|
||||
});
|
||||
|
||||
tap.test('VAL-11: Custom Validation Rules - Supplier Registration Validation', async (tools) => {
|
||||
@ -151,23 +151,23 @@ tap.test('VAL-11: Custom Validation Rules - Supplier Registration Validation', a
|
||||
|
||||
if (test.valid) {
|
||||
expect(isValidVAT).toBeTrue();
|
||||
tools.log(`✓ ${test.name}: Valid VAT number accepted`);
|
||||
console.log(`✓ ${test.name}: Valid VAT number accepted`);
|
||||
} else {
|
||||
expect(isValidVAT).toBe(false);
|
||||
tools.log(`✓ ${test.name}: Invalid VAT number rejected`);
|
||||
expect(isValidVAT).toBeFalse();
|
||||
console.log(`✓ ${test.name}: Invalid VAT number rejected`);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
if (!test.valid) {
|
||||
tools.log(`✓ ${test.name}: Invalid VAT properly rejected: ${error.message}`);
|
||||
console.log(`✓ ${test.name}: Invalid VAT properly rejected: ${error.message}`);
|
||||
} else {
|
||||
tools.log(`⚠ ${test.name}: Unexpected error: ${error.message}`);
|
||||
console.log(`⚠ ${test.name}: Unexpected error: ${error.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('custom-validation-vat', duration);
|
||||
// PerformanceTracker.recordMetric('custom-validation-vat', duration);
|
||||
});
|
||||
|
||||
tap.test('VAL-11: Custom Validation Rules - Industry-Specific Rules', async (tools) => {
|
||||
@ -240,15 +240,15 @@ tap.test('VAL-11: Custom Validation Rules - Industry-Specific Rules', async (too
|
||||
|
||||
if (test.valid) {
|
||||
expect(passesIndustryRules).toBeTrue();
|
||||
tools.log(`✓ ${test.name}: Industry rule compliance verified`);
|
||||
console.log(`✓ ${test.name}: Industry rule compliance verified`);
|
||||
} else {
|
||||
expect(passesIndustryRules).toBe(false);
|
||||
tools.log(`✓ ${test.name}: Industry rule violation detected`);
|
||||
expect(passesIndustryRules).toBeFalse();
|
||||
console.log(`✓ ${test.name}: Industry rule violation detected`);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
if (!test.valid) {
|
||||
tools.log(`✓ ${test.name}: Industry rule violation properly caught: ${error.message}`);
|
||||
console.log(`✓ ${test.name}: Industry rule violation properly caught: ${error.message}`);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
@ -256,7 +256,7 @@ tap.test('VAL-11: Custom Validation Rules - Industry-Specific Rules', async (too
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('custom-validation-industry', duration);
|
||||
// PerformanceTracker.recordMetric('custom-validation-industry', duration);
|
||||
});
|
||||
|
||||
tap.test('VAL-11: Custom Validation Rules - Payment Terms Constraints', async (tools) => {
|
||||
@ -335,29 +335,29 @@ tap.test('VAL-11: Custom Validation Rules - Payment Terms Constraints', async (t
|
||||
// Weekend check (Saturday = 6, Sunday = 0)
|
||||
if (dayOfWeek === 0 || dayOfWeek === 6) {
|
||||
// This would normally trigger an adjustment rule
|
||||
tools.log(`Due date falls on weekend: ${test.dueDate}`);
|
||||
console.log(`Due date falls on weekend: ${test.dueDate}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (test.valid) {
|
||||
expect(passesPaymentRules).toBeTrue();
|
||||
tools.log(`✓ ${test.name}: Payment terms validation passed`);
|
||||
console.log(`✓ ${test.name}: Payment terms validation passed`);
|
||||
} else {
|
||||
expect(passesPaymentRules).toBe(false);
|
||||
tools.log(`✓ ${test.name}: Payment terms validation failed as expected`);
|
||||
expect(passesPaymentRules).toBeFalse();
|
||||
console.log(`✓ ${test.name}: Payment terms validation failed as expected`);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
if (!test.valid) {
|
||||
tools.log(`✓ ${test.name}: Payment terms properly rejected: ${error.message}`);
|
||||
console.log(`✓ ${test.name}: Payment terms properly rejected: ${error.message}`);
|
||||
} else {
|
||||
tools.log(`⚠ ${test.name}: Unexpected error: ${error.message}`);
|
||||
console.log(`⚠ ${test.name}: Unexpected error: ${error.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('custom-validation-payment-terms', duration);
|
||||
// PerformanceTracker.recordMetric('custom-validation-payment-terms', duration);
|
||||
});
|
||||
|
||||
tap.test('VAL-11: Custom Validation Rules - Document Sequence Validation', async (tools) => {
|
||||
@ -440,23 +440,23 @@ tap.test('VAL-11: Custom Validation Rules - Document Sequence Validation', async
|
||||
|
||||
if (test.valid) {
|
||||
expect(passesSequenceRules).toBeTrue();
|
||||
tools.log(`✓ ${test.name}: Document sequence validation passed`);
|
||||
console.log(`✓ ${test.name}: Document sequence validation passed`);
|
||||
} else {
|
||||
expect(passesSequenceRules).toBe(false);
|
||||
tools.log(`✓ ${test.name}: Document sequence validation failed as expected`);
|
||||
expect(passesSequenceRules).toBeFalse();
|
||||
console.log(`✓ ${test.name}: Document sequence validation failed as expected`);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
if (!test.valid) {
|
||||
tools.log(`✓ ${test.name}: Sequence validation properly rejected: ${error.message}`);
|
||||
console.log(`✓ ${test.name}: Sequence validation properly rejected: ${error.message}`);
|
||||
} else {
|
||||
tools.log(`⚠ ${test.name}: Unexpected error: ${error.message}`);
|
||||
console.log(`⚠ ${test.name}: Unexpected error: ${error.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('custom-validation-sequence', duration);
|
||||
// PerformanceTracker.recordMetric('custom-validation-sequence', duration);
|
||||
});
|
||||
|
||||
tap.test('VAL-11: Custom Validation Rules - Corpus Custom Rules Application', { timeout: testTimeout }, async (tools) => {
|
||||
@ -493,31 +493,31 @@ tap.test('VAL-11: Custom Validation Rules - Corpus Custom Rules Application', {
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
tools.log(`Failed to process ${plugins.path.basename(filePath)}: ${error.message}`);
|
||||
console.log(`Failed to process ${plugins.path.basename(filePath)}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
const customRulesSuccessRate = processedFiles > 0 ? (customRulesPassed / processedFiles) * 100 : 0;
|
||||
const customRulesViolationRate = processedFiles > 0 ? (customRulesViolations / processedFiles) * 100 : 0;
|
||||
|
||||
tools.log(`Custom rules validation completed:`);
|
||||
tools.log(`- Processed: ${processedFiles} files`);
|
||||
tools.log(`- Passed custom rules: ${customRulesPassed} files (${customRulesSuccessRate.toFixed(1)}%)`);
|
||||
tools.log(`- Custom rule violations: ${customRulesViolations} files (${customRulesViolationRate.toFixed(1)}%)`);
|
||||
console.log(`Custom rules validation completed:`);
|
||||
console.log(`- Processed: ${processedFiles} files`);
|
||||
console.log(`- Passed custom rules: ${customRulesPassed} files (${customRulesSuccessRate.toFixed(1)}%)`);
|
||||
console.log(`- Custom rule violations: ${customRulesViolations} files (${customRulesViolationRate.toFixed(1)}%)`);
|
||||
|
||||
// Custom rules should have reasonable success rate
|
||||
expect(customRulesSuccessRate).toBeGreaterThan(50);
|
||||
|
||||
} catch (error) {
|
||||
tools.log(`Corpus custom validation failed: ${error.message}`);
|
||||
console.log(`Corpus custom validation failed: ${error.message}`);
|
||||
throw error;
|
||||
}
|
||||
|
||||
const totalDuration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('custom-validation-corpus', totalDuration);
|
||||
// PerformanceTracker.recordMetric('custom-validation-corpus', totalDuration);
|
||||
|
||||
expect(totalDuration).toBeLessThan(90000); // 90 seconds max
|
||||
tools.log(`Custom validation performance: ${totalDuration}ms total`);
|
||||
console.log(`Custom validation performance: ${totalDuration}ms total`);
|
||||
});
|
||||
|
||||
tap.test('VAL-11: Performance Summary', async (tools) => {
|
||||
@ -533,7 +533,13 @@ tap.test('VAL-11: Performance Summary', async (tools) => {
|
||||
for (const operation of operations) {
|
||||
const summary = await PerformanceTracker.getSummary(operation);
|
||||
if (summary) {
|
||||
tools.log(`${operation}: avg=${summary.average}ms, min=${summary.min}ms, max=${summary.max}ms, p95=${summary.p95}ms`);
|
||||
console.log(`${operation}: avg=${summary.average}ms, min=${summary.min}ms, max=${summary.max}ms, p95=${summary.p95}ms`);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Start the test
|
||||
tap.start();
|
||||
|
||||
// Export for test runner compatibility
|
||||
export default tap;
|
@ -1,8 +1,8 @@
|
||||
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';
|
||||
import * as plugins from '../../../ts/plugins.js';
|
||||
import { EInvoice } from '../../../ts/index.js';
|
||||
import { CorpusLoader } from '../../helpers/corpus.loader.js';
|
||||
import { PerformanceTracker } from '../../helpers/performance.tracker.js';
|
||||
|
||||
const testTimeout = 600000; // 10 minutes timeout for performance testing
|
||||
|
||||
@ -99,7 +99,7 @@ tap.test('VAL-12: Validation Performance - Single Invoice Validation Speed', asy
|
||||
expect(validationResult).toBeTruthy();
|
||||
|
||||
} catch (error) {
|
||||
tools.log(`Validation failed for ${test.name}: ${error.message}`);
|
||||
console.log(`Validation failed for ${test.name}: ${error.message}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@ -109,20 +109,20 @@ tap.test('VAL-12: Validation Performance - Single Invoice Validation Speed', asy
|
||||
const maxTime = Math.max(...times);
|
||||
const p95Time = times.sort((a, b) => a - b)[Math.floor(times.length * 0.95)];
|
||||
|
||||
tools.log(`${test.name} validation performance:`);
|
||||
tools.log(` Average: ${avgTime.toFixed(1)}ms`);
|
||||
tools.log(` Min: ${minTime}ms, Max: ${maxTime}ms`);
|
||||
tools.log(` P95: ${p95Time}ms`);
|
||||
console.log(`${test.name} validation performance:`);
|
||||
console.log(` Average: ${avgTime.toFixed(1)}ms`);
|
||||
console.log(` Min: ${minTime}ms, Max: ${maxTime}ms`);
|
||||
console.log(` P95: ${p95Time}ms`);
|
||||
|
||||
// Performance expectations
|
||||
expect(avgTime).toBeLessThan(test.expectedMaxTime);
|
||||
expect(p95Time).toBeLessThan(test.expectedMaxTime * 2);
|
||||
|
||||
PerformanceTracker.recordMetric(`validation-performance-${test.name.toLowerCase().replace(/\s+/g, '-')}`, avgTime);
|
||||
// PerformanceTracker.recordMetric(`validation-performance-${test.name.toLowerCase().replace(/\s+/g, '-')}`, avgTime);
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('validation-performance-single', duration);
|
||||
// PerformanceTracker.recordMetric('validation-performance-single', duration);
|
||||
});
|
||||
|
||||
tap.test('VAL-12: Validation Performance - Concurrent Validation', { timeout: testTimeout }, async (tools) => {
|
||||
@ -165,25 +165,25 @@ tap.test('VAL-12: Validation Performance - Concurrent Validation', { timeout: te
|
||||
|
||||
const avgTimePerValidation = concurrentDuration / concurrency;
|
||||
|
||||
tools.log(`Concurrent validation (${concurrency} parallel):`);
|
||||
tools.log(` Total time: ${concurrentDuration}ms`);
|
||||
tools.log(` Avg per validation: ${avgTimePerValidation.toFixed(1)}ms`);
|
||||
tools.log(` Throughput: ${(1000 / avgTimePerValidation).toFixed(1)} validations/sec`);
|
||||
console.log(`Concurrent validation (${concurrency} parallel):`);
|
||||
console.log(` Total time: ${concurrentDuration}ms`);
|
||||
console.log(` Avg per validation: ${avgTimePerValidation.toFixed(1)}ms`);
|
||||
console.log(` Throughput: ${(1000 / avgTimePerValidation).toFixed(1)} validations/sec`);
|
||||
|
||||
// Performance expectations
|
||||
expect(avgTimePerValidation).toBeLessThan(100); // 100ms max per validation
|
||||
expect(concurrentDuration).toBeLessThan(5000); // 5 seconds max total
|
||||
|
||||
PerformanceTracker.recordMetric(`validation-performance-concurrent-${concurrency}`, avgTimePerValidation);
|
||||
// PerformanceTracker.recordMetric(`validation-performance-concurrent-${concurrency}`, avgTimePerValidation);
|
||||
|
||||
} catch (error) {
|
||||
tools.log(`Concurrent validation failed at level ${concurrency}: ${error.message}`);
|
||||
console.log(`Concurrent validation failed at level ${concurrency}: ${error.message}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
const totalDuration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('validation-performance-concurrent', totalDuration);
|
||||
// PerformanceTracker.recordMetric('validation-performance-concurrent', totalDuration);
|
||||
});
|
||||
|
||||
tap.test('VAL-12: Validation Performance - Large Invoice Handling', { timeout: testTimeout }, async (tools) => {
|
||||
@ -241,24 +241,24 @@ tap.test('VAL-12: Validation Performance - Large Invoice Handling', { timeout: t
|
||||
|
||||
const timePerLine = largeInvoiceDuration / lineCount;
|
||||
|
||||
tools.log(`Large invoice validation (${lineCount} lines):`);
|
||||
tools.log(` Total time: ${largeInvoiceDuration}ms`);
|
||||
tools.log(` Time per line: ${timePerLine.toFixed(2)}ms`);
|
||||
console.log(`Large invoice validation (${lineCount} lines):`);
|
||||
console.log(` Total time: ${largeInvoiceDuration}ms`);
|
||||
console.log(` Time per line: ${timePerLine.toFixed(2)}ms`);
|
||||
|
||||
// Performance expectations scale with line count
|
||||
const maxExpectedTime = Math.max(100, lineCount * 2); // 2ms per line minimum
|
||||
expect(largeInvoiceDuration).toBeLessThan(maxExpectedTime);
|
||||
|
||||
PerformanceTracker.recordMetric(`validation-performance-large-${lineCount}-lines`, largeInvoiceDuration);
|
||||
// PerformanceTracker.recordMetric(`validation-performance-large-${lineCount}-lines`, largeInvoiceDuration);
|
||||
|
||||
} catch (error) {
|
||||
tools.log(`Large invoice validation failed (${lineCount} lines): ${error.message}`);
|
||||
console.log(`Large invoice validation failed (${lineCount} lines): ${error.message}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
const totalDuration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('validation-performance-large', totalDuration);
|
||||
// PerformanceTracker.recordMetric('validation-performance-large', totalDuration);
|
||||
});
|
||||
|
||||
tap.test('VAL-12: Validation Performance - Memory Usage Monitoring', async (tools) => {
|
||||
@ -296,17 +296,17 @@ tap.test('VAL-12: Validation Performance - Memory Usage Monitoring', async (tool
|
||||
const heapGrowth = memoryAfter.heapUsed - memoryBefore.heapUsed;
|
||||
const rssGrowth = memoryAfter.rss - memoryBefore.rss;
|
||||
|
||||
tools.log(`Memory usage for ${iterations} validations:`);
|
||||
tools.log(` Heap growth: ${(heapGrowth / 1024 / 1024).toFixed(2)} MB`);
|
||||
tools.log(` RSS growth: ${(rssGrowth / 1024 / 1024).toFixed(2)} MB`);
|
||||
tools.log(` Heap per validation: ${(heapGrowth / iterations / 1024).toFixed(2)} KB`);
|
||||
console.log(`Memory usage for ${iterations} validations:`);
|
||||
console.log(` Heap growth: ${(heapGrowth / 1024 / 1024).toFixed(2)} MB`);
|
||||
console.log(` RSS growth: ${(rssGrowth / 1024 / 1024).toFixed(2)} MB`);
|
||||
console.log(` Heap per validation: ${(heapGrowth / iterations / 1024).toFixed(2)} KB`);
|
||||
|
||||
// Memory expectations
|
||||
const heapPerValidation = heapGrowth / iterations;
|
||||
expect(heapPerValidation).toBeLessThan(50 * 1024); // Less than 50KB per validation
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('validation-performance-memory', duration);
|
||||
// PerformanceTracker.recordMetric('validation-performance-memory', duration);
|
||||
});
|
||||
|
||||
tap.test('VAL-12: Validation Performance - Corpus Performance Analysis', { timeout: testTimeout }, async (tools) => {
|
||||
@ -353,20 +353,20 @@ tap.test('VAL-12: Validation Performance - Corpus Performance Analysis', { timeo
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
tools.log(`Failed to process ${plugins.path.basename(filePath)}: ${error.message}`);
|
||||
console.log(`Failed to process ${plugins.path.basename(filePath)}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
const categoryTime = Date.now() - categoryStart;
|
||||
const avgCategoryTime = categoryValidations > 0 ? categoryTime / categoryValidations : 0;
|
||||
|
||||
tools.log(`${category} performance:`);
|
||||
tools.log(` Files processed: ${categoryValidations}`);
|
||||
tools.log(` Total time: ${categoryTime}ms`);
|
||||
tools.log(` Avg per file: ${avgCategoryTime.toFixed(1)}ms`);
|
||||
console.log(`${category} performance:`);
|
||||
console.log(` Files processed: ${categoryValidations}`);
|
||||
console.log(` Total time: ${categoryTime}ms`);
|
||||
console.log(` Avg per file: ${avgCategoryTime.toFixed(1)}ms`);
|
||||
|
||||
} catch (error) {
|
||||
tools.log(`Failed to process category ${category}: ${error.message}`);
|
||||
console.log(`Failed to process category ${category}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -376,11 +376,11 @@ tap.test('VAL-12: Validation Performance - Corpus Performance Analysis', { timeo
|
||||
const avgSize = performanceResults.reduce((sum, r) => sum + r.sizeKB, 0) / performanceResults.length;
|
||||
const avgTimePerKB = performanceResults.reduce((sum, r) => sum + r.timePerKB, 0) / performanceResults.length;
|
||||
|
||||
tools.log(`Overall corpus performance analysis:`);
|
||||
tools.log(` Total validations: ${totalValidations}`);
|
||||
tools.log(` Average time: ${avgTime.toFixed(1)}ms`);
|
||||
tools.log(` Average file size: ${avgSize.toFixed(1)}KB`);
|
||||
tools.log(` Average time per KB: ${avgTimePerKB.toFixed(2)}ms/KB`);
|
||||
console.log(`Overall corpus performance analysis:`);
|
||||
console.log(` Total validations: ${totalValidations}`);
|
||||
console.log(` Average time: ${avgTime.toFixed(1)}ms`);
|
||||
console.log(` Average file size: ${avgSize.toFixed(1)}KB`);
|
||||
console.log(` Average time per KB: ${avgTimePerKB.toFixed(2)}ms/KB`);
|
||||
|
||||
// Performance expectations
|
||||
expect(avgTime).toBeLessThan(200); // 200ms max average
|
||||
@ -391,22 +391,22 @@ tap.test('VAL-12: Validation Performance - Corpus Performance Analysis', { timeo
|
||||
.sort((a, b) => b.time - a.time)
|
||||
.slice(0, 3);
|
||||
|
||||
tools.log(`Slowest files:`);
|
||||
console.log(`Slowest files:`);
|
||||
for (const file of slowestFiles) {
|
||||
tools.log(` ${file.file}: ${file.time}ms (${file.sizeKB.toFixed(1)}KB)`);
|
||||
console.log(` ${file.file}: ${file.time}ms (${file.sizeKB.toFixed(1)}KB)`);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
tools.log(`Corpus performance analysis failed: ${error.message}`);
|
||||
console.log(`Corpus performance analysis failed: ${error.message}`);
|
||||
throw error;
|
||||
}
|
||||
|
||||
const totalDuration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('validation-performance-corpus', totalDuration);
|
||||
// PerformanceTracker.recordMetric('validation-performance-corpus', totalDuration);
|
||||
|
||||
expect(totalDuration).toBeLessThan(300000); // 5 minutes max
|
||||
tools.log(`Corpus performance analysis completed in ${totalDuration}ms`);
|
||||
console.log(`Corpus performance analysis completed in ${totalDuration}ms`);
|
||||
});
|
||||
|
||||
tap.test('VAL-12: Validation Performance - Stress Testing', { timeout: testTimeout }, async (tools) => {
|
||||
@ -441,7 +441,7 @@ tap.test('VAL-12: Validation Performance - Stress Testing', { timeout: testTimeo
|
||||
// Log progress every 50 iterations
|
||||
if ((i + 1) % 50 === 0) {
|
||||
const currentAvg = stressTimes.slice(-50).reduce((a, b) => a + b, 0) / 50;
|
||||
tools.log(`Stress test progress: ${i + 1}/${stressIterations}, avg last 50: ${currentAvg.toFixed(1)}ms`);
|
||||
console.log(`Stress test progress: ${i + 1}/${stressIterations}, avg last 50: ${currentAvg.toFixed(1)}ms`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -458,11 +458,11 @@ tap.test('VAL-12: Validation Performance - Stress Testing', { timeout: testTimeo
|
||||
const secondHalfAvg = secondHalf.reduce((a, b) => a + b, 0) / secondHalf.length;
|
||||
const degradation = ((secondHalfAvg - firstHalfAvg) / firstHalfAvg) * 100;
|
||||
|
||||
tools.log(`Stress test results (${stressIterations} iterations):`);
|
||||
tools.log(` Average time: ${avgStressTime.toFixed(1)}ms`);
|
||||
tools.log(` Min: ${minStressTime}ms, Max: ${maxStressTime}ms`);
|
||||
tools.log(` Standard deviation: ${stdDev.toFixed(1)}ms`);
|
||||
tools.log(` Performance degradation: ${degradation.toFixed(1)}%`);
|
||||
console.log(`Stress test results (${stressIterations} iterations):`);
|
||||
console.log(` Average time: ${avgStressTime.toFixed(1)}ms`);
|
||||
console.log(` Min: ${minStressTime}ms, Max: ${maxStressTime}ms`);
|
||||
console.log(` Standard deviation: ${stdDev.toFixed(1)}ms`);
|
||||
console.log(` Performance degradation: ${degradation.toFixed(1)}%`);
|
||||
|
||||
// Performance expectations
|
||||
expect(avgStressTime).toBeLessThan(50); // 50ms average max
|
||||
@ -470,14 +470,14 @@ tap.test('VAL-12: Validation Performance - Stress Testing', { timeout: testTimeo
|
||||
expect(stdDev).toBeLessThan(avgStressTime); // Standard deviation should be reasonable
|
||||
|
||||
} catch (error) {
|
||||
tools.log(`Stress test failed: ${error.message}`);
|
||||
console.log(`Stress test failed: ${error.message}`);
|
||||
throw error;
|
||||
}
|
||||
|
||||
const totalDuration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('validation-performance-stress', totalDuration);
|
||||
// PerformanceTracker.recordMetric('validation-performance-stress', totalDuration);
|
||||
|
||||
tools.log(`Stress test completed in ${totalDuration}ms`);
|
||||
console.log(`Stress test completed in ${totalDuration}ms`);
|
||||
});
|
||||
|
||||
tap.test('VAL-12: Performance Summary', async (tools) => {
|
||||
@ -490,15 +490,21 @@ tap.test('VAL-12: Performance Summary', async (tools) => {
|
||||
'validation-performance-stress'
|
||||
];
|
||||
|
||||
tools.log(`\n=== Validation Performance Summary ===`);
|
||||
console.log(`\n=== Validation 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`);
|
||||
console.log(`${operation}:`);
|
||||
console.log(` avg=${summary.average}ms, min=${summary.min}ms, max=${summary.max}ms, p95=${summary.p95}ms`);
|
||||
}
|
||||
}
|
||||
|
||||
tools.log(`\nValidation performance testing completed successfully.`);
|
||||
});
|
||||
console.log(`\nValidation performance testing completed successfully.`);
|
||||
});
|
||||
|
||||
// Start the test
|
||||
tap.start();
|
||||
|
||||
// Export for test runner compatibility
|
||||
export default tap;
|
@ -1,8 +1,8 @@
|
||||
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';
|
||||
import * as plugins from '../../../ts/plugins.js';
|
||||
import { EInvoice } from '../../../ts/index.js';
|
||||
import { CorpusLoader } from '../../helpers/corpus.loader.js';
|
||||
import { PerformanceTracker } from '../../helpers/performance.tracker.js';
|
||||
|
||||
const testTimeout = 300000; // 5 minutes timeout for corpus processing
|
||||
|
||||
@ -76,9 +76,9 @@ tap.test('VAL-13: Error Reporting - Error Message Quality', async (tools) => {
|
||||
|
||||
// Expect validation to fail
|
||||
if (validationResult && validationResult.valid) {
|
||||
tools.log(`⚠ Expected validation to fail for ${testCase.name} but it passed`);
|
||||
console.log(`⚠ Expected validation to fail for ${testCase.name} but it passed`);
|
||||
} else {
|
||||
tools.log(`✓ ${testCase.name}: Validation correctly failed`);
|
||||
console.log(`✓ ${testCase.name}: Validation correctly failed`);
|
||||
|
||||
// Check error quality if errors are available
|
||||
if (validationResult?.errors && validationResult.errors.length > 0) {
|
||||
@ -89,14 +89,14 @@ tap.test('VAL-13: Error Reporting - Error Message Quality', async (tools) => {
|
||||
expect(error.message).toBeTruthy();
|
||||
expect(error.message.length).toBeGreaterThan(10); // Should be descriptive
|
||||
|
||||
tools.log(` Error: ${error.message}`);
|
||||
console.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}`);
|
||||
console.log(` ✓ Error message includes field name: ${testCase.expectedFieldName}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -105,14 +105,14 @@ tap.test('VAL-13: Error Reporting - Error Message Quality', async (tools) => {
|
||||
|
||||
} catch (parseError) {
|
||||
// Parse errors are also valid for testing error reporting
|
||||
tools.log(`✓ ${testCase.name}: Parse error caught: ${parseError.message}`);
|
||||
console.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);
|
||||
// PerformanceTracker.recordMetric('error-reporting-message-quality', duration);
|
||||
});
|
||||
|
||||
tap.test('VAL-13: Error Reporting - Error Code Classification', async (tools) => {
|
||||
@ -175,7 +175,7 @@ tap.test('VAL-13: Error Reporting - Error Code Classification', async (tools) =>
|
||||
} catch (parseError) {
|
||||
// Handle syntax errors at parse level
|
||||
if (test.expectedCategory === 'syntax') {
|
||||
tools.log(`✓ ${test.name}: Syntax error correctly detected at parse time`);
|
||||
console.log(`✓ ${test.name}: Syntax error correctly detected at parse time`);
|
||||
expect(parseError.message).toBeTruthy();
|
||||
continue;
|
||||
} else {
|
||||
@ -187,41 +187,41 @@ tap.test('VAL-13: Error Reporting - Error Code Classification', async (tools) =>
|
||||
const validationResult = await invoice.validate();
|
||||
|
||||
if (validationResult && !validationResult.valid && validationResult.errors) {
|
||||
tools.log(`✓ ${test.name}: Validation errors detected`);
|
||||
console.log(`✓ ${test.name}: Validation errors detected`);
|
||||
|
||||
for (const error of validationResult.errors) {
|
||||
tools.log(` Error: ${error.message}`);
|
||||
console.log(` Error: ${error.message}`);
|
||||
|
||||
// Check error classification properties
|
||||
if (error.code) {
|
||||
tools.log(` Code: ${error.code}`);
|
||||
console.log(` Code: ${error.code}`);
|
||||
}
|
||||
|
||||
if (error.severity) {
|
||||
tools.log(` Severity: ${error.severity}`);
|
||||
console.log(` Severity: ${error.severity}`);
|
||||
expect(['error', 'warning', 'info']).toContain(error.severity);
|
||||
}
|
||||
|
||||
if (error.category) {
|
||||
tools.log(` Category: ${error.category}`);
|
||||
console.log(` Category: ${error.category}`);
|
||||
}
|
||||
|
||||
if (error.path) {
|
||||
tools.log(` Path: ${error.path}`);
|
||||
console.log(` Path: ${error.path}`);
|
||||
}
|
||||
}
|
||||
} else if (test.expectedCategory !== 'format') {
|
||||
tools.log(`⚠ Expected validation errors for ${test.name} but validation passed`);
|
||||
console.log(`⚠ Expected validation errors for ${test.name} but validation passed`);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
tools.log(`Error processing ${test.name}: ${error.message}`);
|
||||
console.log(`Error processing ${test.name}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('error-reporting-classification', duration);
|
||||
// PerformanceTracker.recordMetric('error-reporting-classification', duration);
|
||||
});
|
||||
|
||||
tap.test('VAL-13: Error Reporting - Error Context and Location', async (tools) => {
|
||||
@ -262,49 +262,49 @@ tap.test('VAL-13: Error Reporting - Error Context and Location', async (tools) =
|
||||
const validationResult = await invoice.validate();
|
||||
|
||||
if (validationResult && !validationResult.valid && validationResult.errors) {
|
||||
tools.log(`Error context testing - found ${validationResult.errors.length} errors:`);
|
||||
console.log(`Error context testing - found ${validationResult.errors.length} errors:`);
|
||||
|
||||
for (const error of validationResult.errors) {
|
||||
tools.log(`\nError: ${error.message}`);
|
||||
console.log(`\nError: ${error.message}`);
|
||||
|
||||
// Check for location information
|
||||
if (error.path) {
|
||||
tools.log(` XPath/Path: ${error.path}`);
|
||||
console.log(` XPath/Path: ${error.path}`);
|
||||
expect(error.path).toBeTruthy();
|
||||
}
|
||||
|
||||
if (error.lineNumber) {
|
||||
tools.log(` Line: ${error.lineNumber}`);
|
||||
console.log(` Line: ${error.lineNumber}`);
|
||||
expect(error.lineNumber).toBeGreaterThan(0);
|
||||
}
|
||||
|
||||
if (error.columnNumber) {
|
||||
tools.log(` Column: ${error.columnNumber}`);
|
||||
console.log(` Column: ${error.columnNumber}`);
|
||||
expect(error.columnNumber).toBeGreaterThan(0);
|
||||
}
|
||||
|
||||
// Check for additional context
|
||||
if (error.context) {
|
||||
tools.log(` Context: ${JSON.stringify(error.context)}`);
|
||||
console.log(` Context: ${JSON.stringify(error.context)}`);
|
||||
}
|
||||
|
||||
if (error.element) {
|
||||
tools.log(` Element: ${error.element}`);
|
||||
console.log(` Element: ${error.element}`);
|
||||
}
|
||||
}
|
||||
|
||||
tools.log(`✓ Error context information available`);
|
||||
console.log(`✓ Error context information available`);
|
||||
} else {
|
||||
tools.log(`⚠ Expected validation errors but validation passed`);
|
||||
console.log(`⚠ Expected validation errors but validation passed`);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
tools.log(`Context test failed: ${error.message}`);
|
||||
console.log(`Context test failed: ${error.message}`);
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('error-reporting-context', duration);
|
||||
// PerformanceTracker.recordMetric('error-reporting-context', duration);
|
||||
});
|
||||
|
||||
tap.test('VAL-13: Error Reporting - Error Aggregation and Summarization', async (tools) => {
|
||||
@ -350,7 +350,7 @@ tap.test('VAL-13: Error Reporting - Error Aggregation and Summarization', async
|
||||
|
||||
if (validationResult && !validationResult.valid && validationResult.errors) {
|
||||
const errors = validationResult.errors;
|
||||
tools.log(`Error aggregation test - found ${errors.length} errors:`);
|
||||
console.log(`Error aggregation test - found ${errors.length} errors:`);
|
||||
|
||||
// Group errors by category
|
||||
const errorsByCategory = {};
|
||||
@ -365,24 +365,24 @@ tap.test('VAL-13: Error Reporting - Error Aggregation and Summarization', async
|
||||
const severity = error.severity || 'error';
|
||||
errorsBySeverity[severity] = (errorsBySeverity[severity] || 0) + 1;
|
||||
|
||||
tools.log(` - ${error.message}`);
|
||||
console.log(` - ${error.message}`);
|
||||
if (error.path) {
|
||||
tools.log(` Path: ${error.path}`);
|
||||
console.log(` Path: ${error.path}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Display error summary
|
||||
tools.log(`\nError Summary:`);
|
||||
tools.log(` Total errors: ${errors.length}`);
|
||||
console.log(`\nError Summary:`);
|
||||
console.log(` Total errors: ${errors.length}`);
|
||||
|
||||
tools.log(` By category:`);
|
||||
console.log(` By category:`);
|
||||
for (const [category, count] of Object.entries(errorsByCategory)) {
|
||||
tools.log(` ${category}: ${count}`);
|
||||
console.log(` ${category}: ${count}`);
|
||||
}
|
||||
|
||||
tools.log(` By severity:`);
|
||||
console.log(` By severity:`);
|
||||
for (const [severity, count] of Object.entries(errorsBySeverity)) {
|
||||
tools.log(` ${severity}: ${count}`);
|
||||
console.log(` ${severity}: ${count}`);
|
||||
}
|
||||
|
||||
// Expect multiple errors to be found
|
||||
@ -394,16 +394,16 @@ tap.test('VAL-13: Error Reporting - Error Aggregation and Summarization', async
|
||||
expect(typeof error.message).toBe('string');
|
||||
}
|
||||
|
||||
tools.log(`✓ Error aggregation and categorization working`);
|
||||
console.log(`✓ Error aggregation and categorization working`);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
tools.log(`Error aggregation test failed: ${error.message}`);
|
||||
console.log(`Error aggregation test failed: ${error.message}`);
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('error-reporting-aggregation', duration);
|
||||
// PerformanceTracker.recordMetric('error-reporting-aggregation', duration);
|
||||
});
|
||||
|
||||
tap.test('VAL-13: Error Reporting - Localized Error Messages', async (tools) => {
|
||||
@ -427,9 +427,9 @@ tap.test('VAL-13: Error Reporting - Localized Error Messages', async (tools) =>
|
||||
// Set locale if the API supports it
|
||||
if (typeof invoice.setLocale === 'function') {
|
||||
invoice.setLocale(locale);
|
||||
tools.log(`Testing error messages in locale: ${locale}`);
|
||||
console.log(`Testing error messages in locale: ${locale}`);
|
||||
} else {
|
||||
tools.log(`Locale setting not supported, testing default messages`);
|
||||
console.log(`Locale setting not supported, testing default messages`);
|
||||
}
|
||||
|
||||
const parseResult = await invoice.fromXmlString(localizationTestXml);
|
||||
@ -439,7 +439,7 @@ tap.test('VAL-13: Error Reporting - Localized Error Messages', async (tools) =>
|
||||
|
||||
if (validationResult && !validationResult.valid && validationResult.errors) {
|
||||
for (const error of validationResult.errors) {
|
||||
tools.log(` ${locale}: ${error.message}`);
|
||||
console.log(` ${locale}: ${error.message}`);
|
||||
|
||||
// Check that error message is not empty and reasonably descriptive
|
||||
expect(error.message).toBeTruthy();
|
||||
@ -447,21 +447,21 @@ tap.test('VAL-13: Error Reporting - Localized Error Messages', async (tools) =>
|
||||
|
||||
// Check for locale-specific characteristics (if implemented)
|
||||
if (locale === 'de' && error.message.includes('ungültig')) {
|
||||
tools.log(` ✓ German localization detected`);
|
||||
console.log(` ✓ German localization detected`);
|
||||
} else if (locale === 'fr' && error.message.includes('invalide')) {
|
||||
tools.log(` ✓ French localization detected`);
|
||||
console.log(` ✓ French localization detected`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
tools.log(`Localization test failed for ${locale}: ${error.message}`);
|
||||
console.log(`Localization test failed for ${locale}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('error-reporting-localization', duration);
|
||||
// PerformanceTracker.recordMetric('error-reporting-localization', duration);
|
||||
});
|
||||
|
||||
tap.test('VAL-13: Error Reporting - Corpus Error Analysis', { timeout: testTimeout }, async (tools) => {
|
||||
@ -517,33 +517,33 @@ tap.test('VAL-13: Error Reporting - Corpus Error Analysis', { timeout: testTimeo
|
||||
} catch (error) {
|
||||
errorStatistics.filesWithErrors++;
|
||||
errorStatistics.totalErrors++;
|
||||
tools.log(`Parse error in ${plugins.path.basename(filePath)}: ${error.message}`);
|
||||
console.log(`Parse error in ${plugins.path.basename(filePath)}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
tools.log(`Failed to process category ${category}: ${error.message}`);
|
||||
console.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)}`);
|
||||
console.log(`\n=== Corpus Error Analysis ===`);
|
||||
console.log(`Total files analyzed: ${errorStatistics.totalFiles}`);
|
||||
console.log(`Files with errors: ${errorStatistics.filesWithErrors} (${(errorStatistics.filesWithErrors / errorStatistics.totalFiles * 100).toFixed(1)}%)`);
|
||||
console.log(`Total errors found: ${errorStatistics.totalErrors}`);
|
||||
console.log(`Average errors per file: ${(errorStatistics.totalErrors / errorStatistics.totalFiles).toFixed(1)}`);
|
||||
|
||||
if (Object.keys(errorStatistics.errorsByCategory).length > 0) {
|
||||
tools.log(`\nErrors by category:`);
|
||||
console.log(`\nErrors by category:`);
|
||||
for (const [category, count] of Object.entries(errorStatistics.errorsByCategory)) {
|
||||
tools.log(` ${category}: ${count}`);
|
||||
console.log(` ${category}: ${count}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(errorStatistics.errorsBySeverity).length > 0) {
|
||||
tools.log(`\nErrors by severity:`);
|
||||
console.log(`\nErrors by severity:`);
|
||||
for (const [severity, count] of Object.entries(errorStatistics.errorsBySeverity)) {
|
||||
tools.log(` ${severity}: ${count}`);
|
||||
console.log(` ${severity}: ${count}`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -553,9 +553,9 @@ tap.test('VAL-13: Error Reporting - Corpus Error Analysis', { timeout: testTimeo
|
||||
.slice(0, 5);
|
||||
|
||||
if (commonErrors.length > 0) {
|
||||
tools.log(`\nMost common errors:`);
|
||||
console.log(`\nMost common errors:`);
|
||||
for (const [errorKey, count] of commonErrors) {
|
||||
tools.log(` ${count}x: ${errorKey}`);
|
||||
console.log(` ${count}x: ${errorKey}`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -563,15 +563,15 @@ tap.test('VAL-13: Error Reporting - Corpus Error Analysis', { timeout: testTimeo
|
||||
expect(errorStatistics.totalFiles).toBeGreaterThan(0);
|
||||
|
||||
} catch (error) {
|
||||
tools.log(`Corpus error analysis failed: ${error.message}`);
|
||||
console.log(`Corpus error analysis failed: ${error.message}`);
|
||||
throw error;
|
||||
}
|
||||
|
||||
const totalDuration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('error-reporting-corpus', totalDuration);
|
||||
// PerformanceTracker.recordMetric('error-reporting-corpus', totalDuration);
|
||||
|
||||
expect(totalDuration).toBeLessThan(120000); // 2 minutes max
|
||||
tools.log(`Error analysis completed in ${totalDuration}ms`);
|
||||
console.log(`Error analysis completed in ${totalDuration}ms`);
|
||||
});
|
||||
|
||||
tap.test('VAL-13: Performance Summary', async (tools) => {
|
||||
@ -584,15 +584,21 @@ tap.test('VAL-13: Performance Summary', async (tools) => {
|
||||
'error-reporting-corpus'
|
||||
];
|
||||
|
||||
tools.log(`\n=== Error Reporting Performance Summary ===`);
|
||||
console.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`);
|
||||
console.log(`${operation}:`);
|
||||
console.log(` avg=${summary.average}ms, min=${summary.min}ms, max=${summary.max}ms, p95=${summary.p95}ms`);
|
||||
}
|
||||
}
|
||||
|
||||
tools.log(`\nError reporting testing completed successfully.`);
|
||||
});
|
||||
console.log(`\nError reporting testing completed successfully.`);
|
||||
});
|
||||
|
||||
// Start the test
|
||||
tap.start();
|
||||
|
||||
// Export for test runner compatibility
|
||||
export default tap;
|
@ -113,7 +113,7 @@ tap.test('VAL-14: Multi-Format Validation - UBL vs CII Validation Consistency',
|
||||
];
|
||||
|
||||
for (const testInvoice of testInvoices) {
|
||||
tools.log(`Testing format consistency for: ${testInvoice.name}`);
|
||||
console.log(`Testing format consistency for: ${testInvoice.name}`);
|
||||
|
||||
try {
|
||||
// Validate UBL version
|
||||
@ -137,31 +137,31 @@ tap.test('VAL-14: Multi-Format Validation - UBL vs CII Validation Consistency',
|
||||
const ublValid = ublValidationResult.valid;
|
||||
const ciiValid = ciiValidationResult.valid;
|
||||
|
||||
tools.log(` UBL validation: ${ublValid ? 'PASS' : 'FAIL'}`);
|
||||
tools.log(` CII validation: ${ciiValid ? 'PASS' : 'FAIL'}`);
|
||||
console.log(` UBL validation: ${ublValid ? 'PASS' : 'FAIL'}`);
|
||||
console.log(` CII validation: ${ciiValid ? 'PASS' : 'FAIL'}`);
|
||||
|
||||
// Both should have consistent validation results for equivalent content
|
||||
if (ublValid !== ciiValid) {
|
||||
tools.log(` ⚠ Validation inconsistency detected between UBL and CII formats`);
|
||||
console.log(` ⚠ Validation inconsistency detected between UBL and CII formats`);
|
||||
|
||||
if (ublValidationResult.errors) {
|
||||
tools.log(` UBL errors: ${ublValidationResult.errors.map(e => e.message).join(', ')}`);
|
||||
console.log(` UBL errors: ${ublValidationResult.errors.map(e => e.message).join(', ')}`);
|
||||
}
|
||||
if (ciiValidationResult.errors) {
|
||||
tools.log(` CII errors: ${ciiValidationResult.errors.map(e => e.message).join(', ')}`);
|
||||
console.log(` CII errors: ${ciiValidationResult.errors.map(e => e.message).join(', ')}`);
|
||||
}
|
||||
} else {
|
||||
tools.log(` ✓ Validation consistency maintained between formats`);
|
||||
console.log(` ✓ Validation consistency maintained between formats`);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
tools.log(` Error testing ${testInvoice.name}: ${error.message}`);
|
||||
console.log(` Error testing ${testInvoice.name}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('multi-format-validation-consistency', duration);
|
||||
// PerformanceTracker.recordMetric('multi-format-validation-consistency', duration);
|
||||
});
|
||||
|
||||
tap.test('VAL-14: Multi-Format Validation - Cross-Format Business Rule Application', async (tools) => {
|
||||
@ -218,7 +218,7 @@ tap.test('VAL-14: Multi-Format Validation - Cross-Format Business Rule Applicati
|
||||
];
|
||||
|
||||
for (const test of businessRuleTests) {
|
||||
tools.log(`Testing business rule: ${test.name}`);
|
||||
console.log(`Testing business rule: ${test.name}`);
|
||||
|
||||
const formatResults = {};
|
||||
|
||||
@ -234,18 +234,18 @@ tap.test('VAL-14: Multi-Format Validation - Cross-Format Business Rule Applicati
|
||||
errors: validationResult.errors || []
|
||||
};
|
||||
|
||||
tools.log(` ${formatName.toUpperCase()}: ${validationResult.valid ? 'PASS' : 'FAIL'}`);
|
||||
console.log(` ${formatName.toUpperCase()}: ${validationResult.valid ? 'PASS' : 'FAIL'}`);
|
||||
if (!validationResult.valid && validationResult.errors) {
|
||||
tools.log(` Errors: ${validationResult.errors.length}`);
|
||||
console.log(` Errors: ${validationResult.errors.length}`);
|
||||
}
|
||||
} else {
|
||||
formatResults[formatName] = { valid: false, errors: ['Parse failed'] };
|
||||
tools.log(` ${formatName.toUpperCase()}: PARSE_FAIL`);
|
||||
console.log(` ${formatName.toUpperCase()}: PARSE_FAIL`);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
formatResults[formatName] = { valid: false, errors: [error.message] };
|
||||
tools.log(` ${formatName.toUpperCase()}: ERROR - ${error.message}`);
|
||||
console.log(` ${formatName.toUpperCase()}: ERROR - ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -254,24 +254,24 @@ tap.test('VAL-14: Multi-Format Validation - Cross-Format Business Rule Applicati
|
||||
const allSame = validationResults.every(result => result === validationResults[0]);
|
||||
|
||||
if (allSame) {
|
||||
tools.log(` ✓ Business rule applied consistently across formats`);
|
||||
console.log(` ✓ Business rule applied consistently across formats`);
|
||||
|
||||
// Check if result matches expectation
|
||||
if (validationResults[0] === test.expectedValid) {
|
||||
tools.log(` ✓ Validation result matches expectation: ${test.expectedValid}`);
|
||||
console.log(` ✓ Validation result matches expectation: ${test.expectedValid}`);
|
||||
} else {
|
||||
tools.log(` ⚠ Validation result (${validationResults[0]}) differs from expectation (${test.expectedValid})`);
|
||||
console.log(` ⚠ Validation result (${validationResults[0]}) differs from expectation (${test.expectedValid})`);
|
||||
}
|
||||
} else {
|
||||
tools.log(` ⚠ Inconsistent business rule application across formats`);
|
||||
console.log(` ⚠ Inconsistent business rule application across formats`);
|
||||
for (const [format, result] of Object.entries(formatResults)) {
|
||||
tools.log(` ${format}: ${result.valid} (${result.errors.length} errors)`);
|
||||
console.log(` ${format}: ${result.valid} (${result.errors.length} errors)`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('multi-format-validation-business-rules', duration);
|
||||
// PerformanceTracker.recordMetric('multi-format-validation-business-rules', duration);
|
||||
});
|
||||
|
||||
tap.test('VAL-14: Multi-Format Validation - Profile-Specific Validation', async (tools) => {
|
||||
@ -334,7 +334,7 @@ tap.test('VAL-14: Multi-Format Validation - Profile-Specific Validation', async
|
||||
];
|
||||
|
||||
for (const test of profileTests) {
|
||||
tools.log(`Testing profile-specific validation: ${test.name}`);
|
||||
console.log(`Testing profile-specific validation: ${test.name}`);
|
||||
|
||||
try {
|
||||
const invoice = new EInvoice();
|
||||
@ -343,44 +343,44 @@ tap.test('VAL-14: Multi-Format Validation - Profile-Specific Validation', async
|
||||
if (parseResult) {
|
||||
const validationResult = await invoice.validate();
|
||||
|
||||
tools.log(` Parse: ${parseResult ? 'SUCCESS' : 'FAILED'}`);
|
||||
tools.log(` Validation: ${validationResult.valid ? 'PASS' : 'FAIL'}`);
|
||||
console.log(` Parse: ${parseResult ? 'SUCCESS' : 'FAILED'}`);
|
||||
console.log(` Validation: ${validationResult.valid ? 'PASS' : 'FAIL'}`);
|
||||
|
||||
if (!validationResult.valid && validationResult.errors) {
|
||||
tools.log(` Errors (${validationResult.errors.length}):`);
|
||||
console.log(` Errors (${validationResult.errors.length}):`);
|
||||
for (const error of validationResult.errors) {
|
||||
tools.log(` - ${error.message}`);
|
||||
console.log(` - ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (test.expectedValid) {
|
||||
// For profile tests, we expect validation to pass or at least parse successfully
|
||||
expect(parseResult).toBeTruthy();
|
||||
tools.log(` ✓ ${test.name} processed successfully`);
|
||||
console.log(` ✓ ${test.name} processed successfully`);
|
||||
} else {
|
||||
expect(validationResult.valid).toBe(false);
|
||||
tools.log(` ✓ ${test.name} correctly rejected`);
|
||||
expect(validationResult.valid).toBeFalse();
|
||||
console.log(` ✓ ${test.name} correctly rejected`);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (!test.expectedValid) {
|
||||
tools.log(` ✓ ${test.name} correctly failed to parse`);
|
||||
console.log(` ✓ ${test.name} correctly failed to parse`);
|
||||
} else {
|
||||
tools.log(` ⚠ ${test.name} failed to parse but was expected to be valid`);
|
||||
console.log(` ⚠ ${test.name} failed to parse but was expected to be valid`);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
if (!test.expectedValid) {
|
||||
tools.log(` ✓ ${test.name} correctly threw error: ${error.message}`);
|
||||
console.log(` ✓ ${test.name} correctly threw error: ${error.message}`);
|
||||
} else {
|
||||
tools.log(` ⚠ ${test.name} unexpected error: ${error.message}`);
|
||||
console.log(` ⚠ ${test.name} unexpected error: ${error.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('multi-format-validation-profiles', duration);
|
||||
// PerformanceTracker.recordMetric('multi-format-validation-profiles', duration);
|
||||
});
|
||||
|
||||
tap.test('VAL-14: Multi-Format Validation - Corpus Cross-Format Analysis', { timeout: testTimeout }, async (tools) => {
|
||||
@ -397,7 +397,7 @@ tap.test('VAL-14: Multi-Format Validation - Corpus Cross-Format Analysis', { tim
|
||||
};
|
||||
|
||||
for (const [formatName, category] of Object.entries(formatCategories)) {
|
||||
tools.log(`Analyzing ${formatName} format validation...`);
|
||||
console.log(`Analyzing ${formatName} format validation...`);
|
||||
|
||||
const categoryAnalysis = {
|
||||
totalFiles: 0,
|
||||
@ -451,7 +451,7 @@ tap.test('VAL-14: Multi-Format Validation - Corpus Cross-Format Analysis', { tim
|
||||
|
||||
} catch (error) {
|
||||
categoryAnalysis.parseErrors++;
|
||||
tools.log(` Parse error in ${plugins.path.basename(filePath)}: ${error.message}`);
|
||||
console.log(` Parse error in ${plugins.path.basename(filePath)}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -463,26 +463,26 @@ tap.test('VAL-14: Multi-Format Validation - Corpus Cross-Format Analysis', { tim
|
||||
formatAnalysis[formatName] = categoryAnalysis;
|
||||
|
||||
// Display format-specific results
|
||||
tools.log(`${formatName} Analysis Results:`);
|
||||
tools.log(` Total files: ${categoryAnalysis.totalFiles}`);
|
||||
tools.log(` Successful parse: ${categoryAnalysis.successfulParse} (${(categoryAnalysis.successfulParse / categoryAnalysis.totalFiles * 100).toFixed(1)}%)`);
|
||||
tools.log(` Successful validation: ${categoryAnalysis.successfulValidation} (${(categoryAnalysis.successfulValidation / categoryAnalysis.totalFiles * 100).toFixed(1)}%)`);
|
||||
tools.log(` Average validation time: ${categoryAnalysis.averageValidationTime.toFixed(1)}ms`);
|
||||
console.log(`${formatName} Analysis Results:`);
|
||||
console.log(` Total files: ${categoryAnalysis.totalFiles}`);
|
||||
console.log(` Successful parse: ${categoryAnalysis.successfulParse} (${(categoryAnalysis.successfulParse / categoryAnalysis.totalFiles * 100).toFixed(1)}%)`);
|
||||
console.log(` Successful validation: ${categoryAnalysis.successfulValidation} (${(categoryAnalysis.successfulValidation / categoryAnalysis.totalFiles * 100).toFixed(1)}%)`);
|
||||
console.log(` Average validation time: ${categoryAnalysis.averageValidationTime.toFixed(1)}ms`);
|
||||
|
||||
if (Object.keys(categoryAnalysis.errorCategories).length > 0) {
|
||||
tools.log(` Error categories:`);
|
||||
console.log(` Error categories:`);
|
||||
for (const [category, count] of Object.entries(categoryAnalysis.errorCategories)) {
|
||||
tools.log(` ${category}: ${count}`);
|
||||
console.log(` ${category}: ${count}`);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
tools.log(`Failed to analyze ${formatName} format: ${error.message}`);
|
||||
console.log(`Failed to analyze ${formatName} format: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Cross-format comparison
|
||||
tools.log(`\n=== Cross-Format Validation Analysis ===`);
|
||||
console.log(`\n=== Cross-Format Validation Analysis ===`);
|
||||
|
||||
const formats = Object.keys(formatAnalysis);
|
||||
if (formats.length > 1) {
|
||||
@ -493,7 +493,7 @@ tap.test('VAL-14: Multi-Format Validation - Corpus Cross-Format Analysis', { tim
|
||||
const analysis1 = formatAnalysis[format1];
|
||||
const analysis2 = formatAnalysis[format2];
|
||||
|
||||
tools.log(`\n${format1} vs ${format2}:`);
|
||||
console.log(`\n${format1} vs ${format2}:`);
|
||||
|
||||
const parseRate1 = analysis1.successfulParse / analysis1.totalFiles;
|
||||
const parseRate2 = analysis2.successfulParse / analysis2.totalFiles;
|
||||
@ -505,15 +505,15 @@ tap.test('VAL-14: Multi-Format Validation - Corpus Cross-Format Analysis', { tim
|
||||
|
||||
const timeDiff = Math.abs(analysis1.averageValidationTime - analysis2.averageValidationTime);
|
||||
|
||||
tools.log(` Parse rate difference: ${parseRateDiff.toFixed(1)}%`);
|
||||
tools.log(` Validation rate difference: ${validationRateDiff.toFixed(1)}%`);
|
||||
tools.log(` Validation time difference: ${timeDiff.toFixed(1)}ms`);
|
||||
console.log(` Parse rate difference: ${parseRateDiff.toFixed(1)}%`);
|
||||
console.log(` Validation rate difference: ${validationRateDiff.toFixed(1)}%`);
|
||||
console.log(` Validation time difference: ${timeDiff.toFixed(1)}ms`);
|
||||
|
||||
// Check for reasonable consistency
|
||||
if (parseRateDiff < 20 && validationRateDiff < 25) {
|
||||
tools.log(` ✓ Reasonable consistency between formats`);
|
||||
console.log(` ✓ Reasonable consistency between formats`);
|
||||
} else {
|
||||
tools.log(` ⚠ Significant differences detected between formats`);
|
||||
console.log(` ⚠ Significant differences detected between formats`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -523,15 +523,15 @@ tap.test('VAL-14: Multi-Format Validation - Corpus Cross-Format Analysis', { tim
|
||||
expect(totalProcessed).toBeGreaterThan(0);
|
||||
|
||||
} catch (error) {
|
||||
tools.log(`Corpus cross-format analysis failed: ${error.message}`);
|
||||
console.log(`Corpus cross-format analysis failed: ${error.message}`);
|
||||
throw error;
|
||||
}
|
||||
|
||||
const totalDuration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('multi-format-validation-corpus', totalDuration);
|
||||
// PerformanceTracker.recordMetric('multi-format-validation-corpus', totalDuration);
|
||||
|
||||
expect(totalDuration).toBeLessThan(180000); // 3 minutes max
|
||||
tools.log(`Cross-format analysis completed in ${totalDuration}ms`);
|
||||
console.log(`Cross-format analysis completed in ${totalDuration}ms`);
|
||||
});
|
||||
|
||||
tap.test('VAL-14: Multi-Format Validation - Format Detection and Validation Integration', async (tools) => {
|
||||
@ -584,7 +584,7 @@ tap.test('VAL-14: Multi-Format Validation - Format Detection and Validation Inte
|
||||
];
|
||||
|
||||
for (const test of formatDetectionTests) {
|
||||
tools.log(`Testing format detection integration: ${test.name}`);
|
||||
console.log(`Testing format detection integration: ${test.name}`);
|
||||
|
||||
try {
|
||||
const invoice = new EInvoice();
|
||||
@ -593,7 +593,7 @@ tap.test('VAL-14: Multi-Format Validation - Format Detection and Validation Inte
|
||||
let detectedFormat = 'UNKNOWN';
|
||||
if (typeof invoice.detectFormat === 'function') {
|
||||
detectedFormat = await invoice.detectFormat(test.xml);
|
||||
tools.log(` Detected format: ${detectedFormat}`);
|
||||
console.log(` Detected format: ${detectedFormat}`);
|
||||
}
|
||||
|
||||
// Then parse and validate
|
||||
@ -602,15 +602,15 @@ tap.test('VAL-14: Multi-Format Validation - Format Detection and Validation Inte
|
||||
if (parseResult) {
|
||||
const validationResult = await invoice.validate();
|
||||
|
||||
tools.log(` Parse: SUCCESS`);
|
||||
tools.log(` Validation: ${validationResult.valid ? 'PASS' : 'FAIL'}`);
|
||||
console.log(` Parse: SUCCESS`);
|
||||
console.log(` Validation: ${validationResult.valid ? 'PASS' : 'FAIL'}`);
|
||||
|
||||
if (test.expectedValid) {
|
||||
expect(parseResult).toBeTruthy();
|
||||
tools.log(` ✓ ${test.name} processed as expected`);
|
||||
console.log(` ✓ ${test.name} processed as expected`);
|
||||
} else {
|
||||
if (!validationResult.valid) {
|
||||
tools.log(` ✓ ${test.name} correctly failed validation`);
|
||||
console.log(` ✓ ${test.name} correctly failed validation`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -622,23 +622,23 @@ tap.test('VAL-14: Multi-Format Validation - Format Detection and Validation Inte
|
||||
|
||||
} else {
|
||||
if (!test.expectedValid) {
|
||||
tools.log(` ✓ ${test.name} correctly failed to parse`);
|
||||
console.log(` ✓ ${test.name} correctly failed to parse`);
|
||||
} else {
|
||||
tools.log(` ⚠ ${test.name} failed to parse but was expected to be valid`);
|
||||
console.log(` ⚠ ${test.name} failed to parse but was expected to be valid`);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
if (!test.expectedValid) {
|
||||
tools.log(` ✓ ${test.name} correctly threw error: ${error.message}`);
|
||||
console.log(` ✓ ${test.name} correctly threw error: ${error.message}`);
|
||||
} else {
|
||||
tools.log(` ⚠ ${test.name} unexpected error: ${error.message}`);
|
||||
console.log(` ⚠ ${test.name} unexpected error: ${error.message}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
PerformanceTracker.recordMetric('multi-format-validation-detection', duration);
|
||||
// PerformanceTracker.recordMetric('multi-format-validation-detection', duration);
|
||||
});
|
||||
|
||||
tap.test('VAL-14: Performance Summary', async (tools) => {
|
||||
@ -650,16 +650,19 @@ tap.test('VAL-14: Performance Summary', async (tools) => {
|
||||
'multi-format-validation-detection'
|
||||
];
|
||||
|
||||
tools.log(`\n=== Multi-Format Validation Performance Summary ===`);
|
||||
console.log(`\n=== Multi-Format Validation 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`);
|
||||
console.log(`${operation}:`);
|
||||
console.log(` avg=${summary.average}ms, min=${summary.min}ms, max=${summary.max}ms, p95=${summary.p95}ms`);
|
||||
}
|
||||
}
|
||||
|
||||
tools.log(`\nMulti-format validation testing completed successfully.`);
|
||||
tools.log(`\n🎉 Validation test suite (VAL-01 through VAL-14) implementation complete!`);
|
||||
});
|
||||
console.log(`\nMulti-format validation testing completed successfully.`);
|
||||
console.log(`\n🎉 Validation test suite (VAL-01 through VAL-14) implementation complete!`);
|
||||
});
|
||||
|
||||
// Start the tests
|
||||
tap.start();
|
Reference in New Issue
Block a user