Frontend: - Refactored CSS architecture with new utility classes - Updated dashboard components styling - Improved responsive grid system - Enhanced typography and variables - Updated E2E and integration tests Added: - Claude Code slash commands for validation - SSH tunnel and start test scripts 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
390 lines
15 KiB
JavaScript
390 lines
15 KiB
JavaScript
/**
|
||
* Cross-Schema Data Validation Tests
|
||
* Validates data consistency between CONTAFIN_ORACLE authentication schema
|
||
* and ROMFAST company data, ensuring proper Oracle data flow
|
||
*/
|
||
|
||
import { test, expect } from '@playwright/test';
|
||
import {
|
||
authenticateWithRealCredentials,
|
||
selectCompany,
|
||
REAL_CREDENTIALS,
|
||
API_ENDPOINTS
|
||
} from '../../utils/real-auth.js';
|
||
import {
|
||
setupConsoleCapture,
|
||
assertNoCriticalErrors,
|
||
generateErrorReport
|
||
} from '../../utils/console-monitor.js';
|
||
|
||
test.describe('Oracle Cross-Schema Data Consistency', () => {
|
||
test.beforeEach(async ({ page }) => {
|
||
setupConsoleCapture(page);
|
||
});
|
||
|
||
test.afterEach(async ({ page }) => {
|
||
const report = generateErrorReport(page, test.info().title);
|
||
if (report.summary.classifications.critical > 0) {
|
||
console.warn('🚨 Critical errors in data consistency test:', report.details.criticalErrors);
|
||
}
|
||
});
|
||
|
||
test('should validate CONTAFIN_ORACLE → ROMFAST data flow', async ({ page }) => {
|
||
console.log('🔄 Testing Oracle cross-schema data flow...');
|
||
|
||
// Authenticate with CONTAFIN_ORACLE schema credentials
|
||
const authResult = await authenticateWithRealCredentials(page);
|
||
expect(authResult.success, 'CONTAFIN_ORACLE authentication failed').toBe(true);
|
||
|
||
console.log('✅ CONTAFIN_ORACLE authentication successful');
|
||
|
||
// Test companies endpoint returns ROMFAST from NOM_FIRME table
|
||
console.log('🏢 Validating companies data from NOM_FIRME...');
|
||
const companiesResponse = await page.request.get(`${API_ENDPOINTS.backend}${API_ENDPOINTS.companies}`);
|
||
expect(companiesResponse.status()).toBe(200);
|
||
|
||
const companies = await companiesResponse.json();
|
||
expect(companies).toBeInstanceOf(Array);
|
||
expect(companies.length).toBeGreaterThan(0);
|
||
|
||
console.log(`📊 Found ${companies.length} companies in NOM_FIRME table`);
|
||
|
||
// Validate ROMFAST company exists
|
||
const romfast = companies.find(c => c.id_firma === 'ROMFAST');
|
||
expect(romfast, 'ROMFAST company not found in NOM_FIRME table').toBeDefined();
|
||
expect(romfast.name).toContain('ROMFAST');
|
||
|
||
console.log('✅ ROMFAST company validated in NOM_FIRME table:', romfast);
|
||
|
||
// Validate company data structure matches Oracle schema
|
||
expect(romfast).toHaveProperty('id_firma');
|
||
expect(romfast).toHaveProperty('name');
|
||
|
||
// Additional Oracle-specific fields that might be present
|
||
const oracleFields = ['cui', 'reg_com', 'adresa', 'telefon', 'email'];
|
||
oracleFields.forEach(field => {
|
||
if (Object.prototype.hasOwnProperty.call(romfast, field)) {
|
||
console.log(`ℹ️ Oracle field '${field}' present:`, romfast[field]);
|
||
}
|
||
});
|
||
|
||
console.log('✅ Cross-schema authentication and company data flow validated');
|
||
});
|
||
|
||
test('should validate invoice schema consistency', async ({ page }) => {
|
||
console.log('📋 Validating invoice data schema consistency...');
|
||
|
||
await authenticateWithRealCredentials(page);
|
||
await selectCompany(page, REAL_CREDENTIALS.company);
|
||
|
||
// Get invoices data for ROMFAST
|
||
console.log('📥 Fetching ROMFAST invoice data...');
|
||
const invoicesResponse = await page.request.get(`${API_ENDPOINTS.backend}/api/invoices/ROMFAST`);
|
||
expect(invoicesResponse.status()).toBe(200);
|
||
|
||
const invoicesData = await invoicesResponse.json();
|
||
expect(invoicesData).toHaveProperty('data');
|
||
expect(invoicesData.data).toBeInstanceOf(Array);
|
||
|
||
if (invoicesData.data.length > 0) {
|
||
const sampleInvoice = invoicesData.data[0];
|
||
console.log('📋 Sample invoice structure:', Object.keys(sampleInvoice));
|
||
|
||
// Validate Oracle-specific invoice fields are present
|
||
const requiredOracleFields = [
|
||
'numar_factura', // Invoice number
|
||
'data_scadenta', // Due date
|
||
'suma_totala' // Total amount
|
||
];
|
||
|
||
requiredOracleFields.forEach(field => {
|
||
expect(sampleInvoice, `Missing Oracle field: ${field}`).toHaveProperty(field);
|
||
console.log(`✅ Oracle field '${field}':`, sampleInvoice[field]);
|
||
});
|
||
|
||
// Validate data types
|
||
expect(typeof sampleInvoice.numar_factura).toBe('string');
|
||
expect(sampleInvoice.suma_totala).toBeGreaterThanOrEqual(0);
|
||
|
||
// Validate date format (should be ISO string or valid date)
|
||
if (sampleInvoice.data_scadenta) {
|
||
const date = new Date(sampleInvoice.data_scadenta);
|
||
expect(date.toString()).not.toBe('Invalid Date');
|
||
console.log(`✅ Date validation passed: ${sampleInvoice.data_scadenta}`);
|
||
}
|
||
|
||
console.log(`✅ Invoice schema validation passed (${invoicesData.data.length} invoices)`);
|
||
} else {
|
||
console.log('ℹ️ No invoice data found for ROMFAST - schema validation skipped');
|
||
}
|
||
|
||
// Check for console errors during data retrieval
|
||
assertNoCriticalErrors(page, expect);
|
||
});
|
||
|
||
test('should validate payment schema consistency', async ({ page }) => {
|
||
console.log('💰 Validating payment data schema consistency...');
|
||
|
||
await authenticateWithRealCredentials(page);
|
||
await selectCompany(page, REAL_CREDENTIALS.company);
|
||
|
||
// Get payments data for ROMFAST
|
||
console.log('💳 Fetching ROMFAST payment data...');
|
||
const paymentsResponse = await page.request.get(`${API_ENDPOINTS.backend}/api/payments/ROMFAST`);
|
||
expect(paymentsResponse.status()).toBe(200);
|
||
|
||
const paymentsData = await paymentsResponse.json();
|
||
expect(paymentsData).toHaveProperty('data');
|
||
expect(paymentsData.data).toBeInstanceOf(Array);
|
||
|
||
if (paymentsData.data.length > 0) {
|
||
const samplePayment = paymentsData.data[0];
|
||
console.log('💳 Sample payment structure:', Object.keys(samplePayment));
|
||
|
||
// Validate Oracle-specific payment fields
|
||
const requiredOracleFields = [
|
||
'numar_plata', // Payment number
|
||
'data_plata', // Payment date
|
||
'suma_plata' // Payment amount
|
||
];
|
||
|
||
requiredOracleFields.forEach(field => {
|
||
expect(samplePayment, `Missing Oracle payment field: ${field}`).toHaveProperty(field);
|
||
console.log(`✅ Oracle payment field '${field}':`, samplePayment[field]);
|
||
});
|
||
|
||
// Validate payment data types
|
||
expect(typeof samplePayment.numar_plata).toBe('string');
|
||
expect(samplePayment.suma_plata).toBeGreaterThanOrEqual(0);
|
||
|
||
// Validate payment date
|
||
if (samplePayment.data_plata) {
|
||
const date = new Date(samplePayment.data_plata);
|
||
expect(date.toString()).not.toBe('Invalid Date');
|
||
console.log(`✅ Payment date validation passed: ${samplePayment.data_plata}`);
|
||
}
|
||
|
||
console.log(`✅ Payment schema validation passed (${paymentsData.data.length} payments)`);
|
||
} else {
|
||
console.log('ℹ️ No payment data found for ROMFAST - schema validation skipped');
|
||
}
|
||
|
||
// Check for console errors during data retrieval
|
||
assertNoCriticalErrors(page, expect);
|
||
});
|
||
|
||
test('should validate user permissions across schemas', async ({ page }) => {
|
||
console.log('🔐 Validating user permissions across Oracle schemas...');
|
||
|
||
const authResult = await authenticateWithRealCredentials(page);
|
||
expect(authResult.success).toBe(true);
|
||
|
||
// Test access to different endpoints with authenticated user
|
||
const endpointsToTest = [
|
||
{ url: '/api/companies', name: 'Companies List', expectAccess: true },
|
||
{ url: '/api/invoices/ROMFAST', name: 'ROMFAST Invoices', expectAccess: true },
|
||
{ url: '/api/payments/ROMFAST', name: 'ROMFAST Payments', expectAccess: true },
|
||
{ url: '/api/user/profile', name: 'User Profile', expectAccess: true },
|
||
{ url: '/api/admin/users', name: 'Admin Users', expectAccess: false } // Should fail
|
||
];
|
||
|
||
const accessResults = [];
|
||
|
||
for (const endpoint of endpointsToTest) {
|
||
console.log(`🔍 Testing access to ${endpoint.name}...`);
|
||
|
||
try {
|
||
const response = await page.request.get(`${API_ENDPOINTS.backend}${endpoint.url}`);
|
||
const hasAccess = response.status() < 400;
|
||
|
||
accessResults.push({
|
||
endpoint: endpoint.name,
|
||
url: endpoint.url,
|
||
status: response.status(),
|
||
hasAccess: hasAccess,
|
||
expectAccess: endpoint.expectAccess
|
||
});
|
||
|
||
if (endpoint.expectAccess) {
|
||
expect(hasAccess, `Expected access to ${endpoint.name} but got ${response.status()}`).toBe(true);
|
||
console.log(`✅ ${endpoint.name}: Access granted (${response.status()})`);
|
||
} else {
|
||
expect(hasAccess, `Expected no access to ${endpoint.name} but got ${response.status()}`).toBe(false);
|
||
console.log(`✅ ${endpoint.name}: Access denied as expected (${response.status()})`);
|
||
}
|
||
|
||
} catch (error) {
|
||
console.log(`⚠️ ${endpoint.name}: Request failed - ${error.message}`);
|
||
accessResults.push({
|
||
endpoint: endpoint.name,
|
||
url: endpoint.url,
|
||
error: error.message,
|
||
hasAccess: false,
|
||
expectAccess: endpoint.expectAccess
|
||
});
|
||
}
|
||
}
|
||
|
||
// Summary of access results
|
||
console.log('📊 Permission Validation Summary:');
|
||
accessResults.forEach(result => {
|
||
const status = result.hasAccess === result.expectAccess ? '✅' : '❌';
|
||
console.log(` ${status} ${result.endpoint}: ${result.hasAccess ? 'Access' : 'No Access'}`);
|
||
});
|
||
|
||
console.log('✅ User permission validation completed');
|
||
});
|
||
|
||
test('should validate data relationships between tables', async ({ page }) => {
|
||
console.log('🔗 Validating data relationships between Oracle tables...');
|
||
|
||
await authenticateWithRealCredentials(page);
|
||
|
||
// Get company data
|
||
const companiesResponse = await page.request.get(`${API_ENDPOINTS.backend}${API_ENDPOINTS.companies}`);
|
||
const companies = await companiesResponse.json();
|
||
const romfast = companies.find(c => c.id_firma === 'ROMFAST');
|
||
|
||
expect(romfast).toBeDefined();
|
||
|
||
// Get invoices for ROMFAST
|
||
const invoicesResponse = await page.request.get(`${API_ENDPOINTS.backend}/api/invoices/ROMFAST`);
|
||
const invoicesData = await invoicesResponse.json();
|
||
|
||
// Get payments for ROMFAST
|
||
const paymentsResponse = await page.request.get(`${API_ENDPOINTS.backend}/api/payments/ROMFAST`);
|
||
const paymentsData = await paymentsResponse.json();
|
||
|
||
console.log('📊 Data relationship summary:');
|
||
console.log(` Company: ${romfast.name} (${romfast.id_firma})`);
|
||
console.log(` Invoices: ${invoicesData.data?.length || 0}`);
|
||
console.log(` Payments: ${paymentsData.data?.length || 0}`);
|
||
|
||
// Validate referential integrity
|
||
if (invoicesData.data && invoicesData.data.length > 0) {
|
||
const sampleInvoice = invoicesData.data[0];
|
||
|
||
// Invoice should reference the company
|
||
if (sampleInvoice.cod_firma) {
|
||
expect(sampleInvoice.cod_firma).toBe(romfast.id_firma);
|
||
console.log('✅ Invoice-Company relationship validated');
|
||
}
|
||
|
||
// Check if there are related payments
|
||
if (paymentsData.data && paymentsData.data.length > 0) {
|
||
console.log('✅ Payment data exists for company with invoices');
|
||
|
||
// Look for potential invoice-payment relationships
|
||
const samplePayment = paymentsData.data[0];
|
||
if (samplePayment.cod_firma) {
|
||
expect(samplePayment.cod_firma).toBe(romfast.id_firma);
|
||
console.log('✅ Payment-Company relationship validated');
|
||
}
|
||
}
|
||
}
|
||
|
||
// Validate data consistency
|
||
const totalInvoicesFromApi = invoicesData.data?.length || 0;
|
||
const totalPaymentsFromApi = paymentsData.data?.length || 0;
|
||
|
||
// These should be reasonable numbers for a real company
|
||
if (totalInvoicesFromApi > 0) {
|
||
console.log(`✅ Company has ${totalInvoicesFromApi} invoices`);
|
||
}
|
||
|
||
if (totalPaymentsFromApi > 0) {
|
||
console.log(`✅ Company has ${totalPaymentsFromApi} payments`);
|
||
}
|
||
|
||
// Check for console errors during relationship validation
|
||
assertNoCriticalErrors(page, expect);
|
||
|
||
console.log('✅ Data relationship validation completed');
|
||
});
|
||
|
||
test('should validate Oracle connection persistence during operations', async ({ page }) => {
|
||
console.log('🔄 Testing Oracle connection persistence...');
|
||
|
||
await authenticateWithRealCredentials(page);
|
||
|
||
// Perform multiple operations to test connection persistence
|
||
const operations = [
|
||
{ name: 'Companies Load', action: () => page.request.get(`${API_ENDPOINTS.backend}${API_ENDPOINTS.companies}`) },
|
||
{ name: 'Invoice Load', action: () => page.request.get(`${API_ENDPOINTS.backend}/api/invoices/ROMFAST`) },
|
||
{ name: 'Payment Load', action: () => page.request.get(`${API_ENDPOINTS.backend}/api/payments/ROMFAST`) },
|
||
{ name: 'Health Check', action: () => page.request.get(`${API_ENDPOINTS.backend}${API_ENDPOINTS.health}`) }
|
||
];
|
||
|
||
const connectionResults = [];
|
||
|
||
for (let cycle = 1; cycle <= 3; cycle++) {
|
||
console.log(`🔄 Connection persistence test cycle ${cycle}/3`);
|
||
|
||
for (const operation of operations) {
|
||
const startTime = Date.now();
|
||
|
||
try {
|
||
const response = await operation.action();
|
||
const responseTime = Date.now() - startTime;
|
||
const success = response.status() < 400;
|
||
|
||
connectionResults.push({
|
||
cycle,
|
||
operation: operation.name,
|
||
success,
|
||
status: response.status(),
|
||
responseTime
|
||
});
|
||
|
||
if (success) {
|
||
console.log(` ✅ ${operation.name}: ${response.status()} (${responseTime}ms)`);
|
||
} else {
|
||
console.log(` ❌ ${operation.name}: ${response.status()} (${responseTime}ms)`);
|
||
}
|
||
|
||
// Brief delay between operations
|
||
await new Promise(resolve => setTimeout(resolve, 500));
|
||
|
||
} catch (error) {
|
||
console.log(` ❌ ${operation.name}: ${error.message}`);
|
||
connectionResults.push({
|
||
cycle,
|
||
operation: operation.name,
|
||
success: false,
|
||
error: error.message
|
||
});
|
||
}
|
||
}
|
||
|
||
// Delay between cycles
|
||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||
}
|
||
|
||
// Analyze connection persistence
|
||
const totalOperations = connectionResults.length;
|
||
const successfulOperations = connectionResults.filter(r => r.success).length;
|
||
const successRate = (successfulOperations / totalOperations) * 100;
|
||
|
||
console.log('📊 Connection Persistence Analysis:');
|
||
console.log(` Total Operations: ${totalOperations}`);
|
||
console.log(` Successful: ${successfulOperations}`);
|
||
console.log(` Success Rate: ${successRate.toFixed(1)}%`);
|
||
|
||
// Connection should be persistent (>90% success rate)
|
||
expect(successRate, 'Oracle connection not persistent enough').toBeGreaterThan(90);
|
||
|
||
// No connection should fail in the same cycle
|
||
const cycleFailures = {};
|
||
connectionResults.filter(r => !r.success).forEach(r => {
|
||
cycleFailures[r.cycle] = (cycleFailures[r.cycle] || 0) + 1;
|
||
});
|
||
|
||
Object.entries(cycleFailures).forEach(([cycle, failures]) => {
|
||
if (failures === operations.length) {
|
||
throw new Error(`Complete connection failure in cycle ${cycle}`);
|
||
}
|
||
});
|
||
|
||
console.log('✅ Oracle connection persistence validated');
|
||
});
|
||
}); |