Modern ERP Reports Application with microservices architecture Tech Stack: - Backend: FastAPI + python-oracledb (Oracle DB integration) - Frontend: Vue.js 3 + PrimeVue + Vite - Telegram Bot: python-telegram-bot + SQLite - Infrastructure: Shared database pool, JWT authentication, SSH tunnel Features: - FastAPI backend with async Oracle connection pool - Vue.js 3 responsive frontend with PrimeVue components - Telegram bot alternative interface - Microservices architecture with shared components - Complete deployment support (Linux Docker + Windows IIS) - Comprehensive testing (Playwright E2E + pytest) Repository Structure: - reports-app/ - Main application (backend, frontend, telegram-bot) - shared/ - Shared components (database pool, auth, utils) - deployment/ - Deployment scripts (Linux & Windows) - docs/ - Project documentation - security/ - Security scanning and git hooks
366 lines
14 KiB
JavaScript
366 lines
14 KiB
JavaScript
/**
|
|
* ROMFAST Company Data Integration Tests
|
|
* Tests real Oracle data loading and validation for ROMFAST company
|
|
* Monitors console errors during data operations
|
|
*/
|
|
|
|
import { test, expect } from '@playwright/test';
|
|
import {
|
|
authenticateWithRealCredentials,
|
|
selectCompany,
|
|
getRealCompanies,
|
|
REAL_CREDENTIALS,
|
|
API_ENDPOINTS
|
|
} from '../../utils/real-auth.js';
|
|
import {
|
|
setupConsoleCapture,
|
|
assertNoCriticalErrors,
|
|
generateErrorReport,
|
|
PerformanceMonitor,
|
|
PerformanceBaselines,
|
|
assertPerformanceBaseline
|
|
} from '../../utils/console-monitor.js';
|
|
|
|
test.describe('ROMFAST Company Data Integration', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
// Setup console monitoring
|
|
setupConsoleCapture(page);
|
|
|
|
// Authenticate with real credentials
|
|
const authResult = await authenticateWithRealCredentials(page);
|
|
expect(authResult.success, `Authentication failed: ${authResult.error}`).toBe(true);
|
|
|
|
console.log('🔐 Authenticated successfully for ROMFAST data tests');
|
|
});
|
|
|
|
test.afterEach(async ({ page }) => {
|
|
// Generate comprehensive error report
|
|
const report = generateErrorReport(page, test.info().title);
|
|
|
|
if (report.summary.classifications.critical > 0) {
|
|
console.warn('❌ Critical errors in ROMFAST data test:', report.details.criticalErrors);
|
|
}
|
|
|
|
if (report.summary.classifications.warning > 3) {
|
|
console.warn('⚠️ High number of warnings:', report.summary.classifications.warning);
|
|
}
|
|
});
|
|
|
|
test('should load ROMFAST company data correctly', async ({ page }) => {
|
|
console.log('🏢 Testing ROMFAST company data loading...');
|
|
|
|
const startTime = Date.now();
|
|
|
|
// Select ROMFAST from real companies list
|
|
const selectSuccess = await selectCompany(page, REAL_CREDENTIALS.company);
|
|
expect(selectSuccess, 'Failed to select ROMFAST company').toBe(true);
|
|
|
|
const selectionTime = Date.now() - startTime;
|
|
|
|
// Verify company stats loaded
|
|
await page.waitForSelector('[data-testid="company-stats"]', { timeout: 15000 });
|
|
|
|
// Verify company name display
|
|
const companyName = await page.locator('[data-testid="company-name"]').textContent();
|
|
expect(companyName).toContain('ROMFAST');
|
|
|
|
// Check for console errors during data load
|
|
const criticalErrors = (page.consoleMessages || [])
|
|
.filter(msg => msg.type === 'error' && !msg.text.includes('404'));
|
|
|
|
expect(criticalErrors, `Critical errors during ROMFAST data load: ${JSON.stringify(criticalErrors)}`).toHaveLength(0);
|
|
|
|
// Validate performance
|
|
assertPerformanceBaseline(
|
|
selectionTime,
|
|
PerformanceBaselines.dashboardLoad,
|
|
'ROMFAST company selection',
|
|
expect
|
|
);
|
|
|
|
console.log(`✅ ROMFAST company data loaded successfully in ${selectionTime}ms`);
|
|
});
|
|
|
|
test('should validate ROMFAST invoice data structure', async ({ page }) => {
|
|
console.log('📋 Testing ROMFAST invoice data structure...');
|
|
|
|
// Select ROMFAST company
|
|
await selectCompany(page, REAL_CREDENTIALS.company);
|
|
|
|
// Navigate to invoices
|
|
await page.click('[data-testid="nav-invoices"]');
|
|
await page.waitForURL('/invoices');
|
|
|
|
// Measure API response time
|
|
const apiStartTime = Date.now();
|
|
await page.waitForResponse(response =>
|
|
response.url().includes('/api/invoices') && response.status() === 200,
|
|
{ timeout: 10000 }
|
|
);
|
|
const apiResponseTime = Date.now() - apiStartTime;
|
|
|
|
// Wait for invoice data to load
|
|
await page.waitForSelector('[data-testid="invoices-table"]', { timeout: 15000 });
|
|
|
|
// Verify Oracle-specific data fields are present
|
|
const invoiceRows = await page.locator('[data-testid="invoice-row"]').count();
|
|
expect(invoiceRows).toBeGreaterThan(0);
|
|
|
|
if (invoiceRows > 0) {
|
|
// Check first invoice for Oracle schema fields
|
|
const firstInvoice = page.locator('[data-testid="invoice-row"]').first();
|
|
|
|
// These should match Oracle CONTAFIN schema
|
|
await expect(firstInvoice.locator('[data-testid="numar-factura"]')).toBeVisible();
|
|
await expect(firstInvoice.locator('[data-testid="data-scadenta"]')).toBeVisible();
|
|
await expect(firstInvoice.locator('[data-testid="suma-totala"]')).toBeVisible();
|
|
|
|
console.log(`📊 Found ${invoiceRows} ROMFAST invoices with Oracle schema fields`);
|
|
}
|
|
|
|
// Validate API performance
|
|
assertPerformanceBaseline(
|
|
apiResponseTime,
|
|
PerformanceBaselines.apiResponse,
|
|
'ROMFAST invoices API',
|
|
expect
|
|
);
|
|
|
|
// Check for no critical console errors
|
|
assertNoCriticalErrors(page, expect);
|
|
|
|
console.log(`✅ ROMFAST invoice data structure validated (API: ${apiResponseTime}ms)`);
|
|
});
|
|
|
|
test('should validate ROMFAST payment data integration', async ({ page }) => {
|
|
console.log('💰 Testing ROMFAST payment data integration...');
|
|
|
|
// Select ROMFAST company
|
|
await selectCompany(page, REAL_CREDENTIALS.company);
|
|
|
|
// Navigate to payments
|
|
await page.click('[data-testid="nav-payments"]');
|
|
await page.waitForURL('/payments');
|
|
|
|
// Measure payment data loading
|
|
const loadStartTime = Date.now();
|
|
await page.waitForSelector('[data-testid="payments-table"]', { timeout: 15000 });
|
|
const loadTime = Date.now() - loadStartTime;
|
|
|
|
// Verify payment data structure
|
|
const paymentRows = await page.locator('[data-testid="payment-row"]').count();
|
|
console.log(`💳 Found ${paymentRows} ROMFAST payments`);
|
|
|
|
if (paymentRows > 0) {
|
|
// Verify Oracle payment schema fields
|
|
const firstPayment = page.locator('[data-testid="payment-row"]').first();
|
|
|
|
await expect(firstPayment.locator('[data-testid="numar-plata"]')).toBeVisible();
|
|
await expect(firstPayment.locator('[data-testid="data-plata"]')).toBeVisible();
|
|
await expect(firstPayment.locator('[data-testid="suma-plata"]')).toBeVisible();
|
|
}
|
|
|
|
// Validate performance
|
|
assertPerformanceBaseline(
|
|
loadTime,
|
|
PerformanceBaselines.reportGeneration,
|
|
'ROMFAST payments loading',
|
|
expect
|
|
);
|
|
|
|
// Check console for errors
|
|
assertNoCriticalErrors(page, expect);
|
|
|
|
console.log(`✅ ROMFAST payment data validated (Load: ${loadTime}ms)`);
|
|
});
|
|
|
|
test('should handle ROMFAST data filtering and search', async ({ page }) => {
|
|
console.log('🔍 Testing ROMFAST data filtering capabilities...');
|
|
|
|
// Select ROMFAST company
|
|
await selectCompany(page, REAL_CREDENTIALS.company);
|
|
|
|
// Go to invoices for filtering test
|
|
await page.click('[data-testid="nav-invoices"]');
|
|
await page.waitForSelector('[data-testid="invoices-table"]', { timeout: 15000 });
|
|
|
|
// Get initial row count
|
|
const initialCount = await page.locator('[data-testid="invoice-row"]').count();
|
|
console.log(`📊 Initial ROMFAST invoices: ${initialCount}`);
|
|
|
|
if (initialCount > 0) {
|
|
// Test date range filtering
|
|
if (await page.locator('[data-testid="date-filter-from"]').isVisible()) {
|
|
const filterStartTime = Date.now();
|
|
|
|
// Set date filter for last 30 days
|
|
const thirtyDaysAgo = new Date();
|
|
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
|
|
|
|
await page.fill('[data-testid="date-filter-from"]', thirtyDaysAgo.toISOString().split('T')[0]);
|
|
await page.click('[data-testid="apply-filter"]');
|
|
|
|
// Wait for filtered results
|
|
await page.waitForTimeout(2000); // Allow for filtering
|
|
|
|
const filteredCount = await page.locator('[data-testid="invoice-row"]').count();
|
|
const filterTime = Date.now() - filterStartTime;
|
|
|
|
console.log(`🗓️ Filtered to ${filteredCount} invoices in ${filterTime}ms`);
|
|
|
|
// Performance check for filtering
|
|
expect(filterTime).toBeLessThan(3000); // Max 3s for filtering
|
|
}
|
|
|
|
// Test search functionality
|
|
if (await page.locator('[data-testid="search-input"]').isVisible()) {
|
|
const searchStartTime = Date.now();
|
|
|
|
// Search for specific criteria
|
|
await page.fill('[data-testid="search-input"]', 'ROMFAST');
|
|
await page.keyboard.press('Enter');
|
|
|
|
await page.waitForTimeout(1500); // Allow for search
|
|
|
|
const searchResults = await page.locator('[data-testid="invoice-row"]').count();
|
|
const searchTime = Date.now() - searchStartTime;
|
|
|
|
console.log(`🔎 Search returned ${searchResults} results in ${searchTime}ms`);
|
|
|
|
// Performance check for search
|
|
expect(searchTime).toBeLessThan(2000); // Max 2s for search
|
|
}
|
|
}
|
|
|
|
// Verify no critical errors during filtering operations
|
|
assertNoCriticalErrors(page, expect);
|
|
|
|
console.log('✅ ROMFAST data filtering and search validated');
|
|
});
|
|
|
|
test('should validate ROMFAST dashboard metrics accuracy', async ({ page }) => {
|
|
console.log('📈 Testing ROMFAST dashboard metrics accuracy...');
|
|
|
|
// Select ROMFAST company
|
|
await selectCompany(page, REAL_CREDENTIALS.company);
|
|
|
|
// Wait for dashboard stats to load
|
|
await page.waitForSelector('[data-testid="company-stats"]', { timeout: 15000 });
|
|
|
|
// Capture dashboard metrics
|
|
const dashboardMetrics = await page.evaluate(() => {
|
|
const getMetric = (selector) => {
|
|
const element = document.querySelector(selector);
|
|
return element ? element.textContent.trim() : null;
|
|
};
|
|
|
|
return {
|
|
totalInvoices: getMetric('[data-testid="total-invoices"]'),
|
|
totalPayments: getMetric('[data-testid="total-payments"]'),
|
|
pendingAmount: getMetric('[data-testid="pending-amount"]'),
|
|
overdueCount: getMetric('[data-testid="overdue-count"]')
|
|
};
|
|
});
|
|
|
|
console.log('📊 ROMFAST Dashboard Metrics:', dashboardMetrics);
|
|
|
|
// Validate metrics are present and reasonable
|
|
if (dashboardMetrics.totalInvoices) {
|
|
const invoiceCount = parseInt(dashboardMetrics.totalInvoices.replace(/\D/g, ''));
|
|
expect(invoiceCount).toBeGreaterThanOrEqual(0);
|
|
}
|
|
|
|
if (dashboardMetrics.totalPayments) {
|
|
const paymentCount = parseInt(dashboardMetrics.totalPayments.replace(/\D/g, ''));
|
|
expect(paymentCount).toBeGreaterThanOrEqual(0);
|
|
}
|
|
|
|
// Cross-validate with individual pages
|
|
await page.click('[data-testid="nav-invoices"]');
|
|
await page.waitForSelector('[data-testid="invoices-table"]', { timeout: 10000 });
|
|
|
|
const actualInvoiceCount = await page.locator('[data-testid="invoice-row"]').count();
|
|
console.log(`🔄 Cross-validation: Dashboard vs Invoices page (${actualInvoiceCount})`);
|
|
|
|
// Return to dashboard
|
|
await page.click('[data-testid="nav-dashboard"]');
|
|
|
|
// Check for console errors during metric calculations
|
|
assertNoCriticalErrors(page, expect);
|
|
|
|
console.log('✅ ROMFAST dashboard metrics accuracy validated');
|
|
});
|
|
|
|
test('should measure ROMFAST data loading performance under load', async ({ page }) => {
|
|
console.log('⚡ Testing ROMFAST data performance under simulated load...');
|
|
|
|
const performanceMetrics = [];
|
|
|
|
// Perform multiple data loading operations
|
|
for (let i = 0; i < 3; i++) {
|
|
console.log(`🔄 Performance test iteration ${i + 1}/3`);
|
|
|
|
const iterationStart = Date.now();
|
|
|
|
// Select company
|
|
await selectCompany(page, REAL_CREDENTIALS.company);
|
|
const companySelectTime = Date.now() - iterationStart;
|
|
|
|
// Load invoices
|
|
const invoicesStart = Date.now();
|
|
await page.click('[data-testid="nav-invoices"]');
|
|
await page.waitForSelector('[data-testid="invoices-table"]', { timeout: 15000 });
|
|
const invoicesLoadTime = Date.now() - invoicesStart;
|
|
|
|
// Load payments
|
|
const paymentsStart = Date.now();
|
|
await page.click('[data-testid="nav-payments"]');
|
|
await page.waitForSelector('[data-testid="payments-table"]', { timeout: 15000 });
|
|
const paymentsLoadTime = Date.now() - paymentsStart;
|
|
|
|
// Return to dashboard
|
|
const dashboardStart = Date.now();
|
|
await page.click('[data-testid="nav-dashboard"]');
|
|
await page.waitForSelector('[data-testid="company-stats"]', { timeout: 10000 });
|
|
const dashboardLoadTime = Date.now() - dashboardStart;
|
|
|
|
const totalIterationTime = Date.now() - iterationStart;
|
|
|
|
performanceMetrics.push({
|
|
iteration: i + 1,
|
|
companySelect: companySelectTime,
|
|
invoicesLoad: invoicesLoadTime,
|
|
paymentsLoad: paymentsLoadTime,
|
|
dashboardLoad: dashboardLoadTime,
|
|
total: totalIterationTime
|
|
});
|
|
|
|
console.log(`📊 Iteration ${i + 1} - Total: ${totalIterationTime}ms`);
|
|
}
|
|
|
|
// Calculate averages
|
|
const averages = {
|
|
companySelect: performanceMetrics.reduce((sum, m) => sum + m.companySelect, 0) / performanceMetrics.length,
|
|
invoicesLoad: performanceMetrics.reduce((sum, m) => sum + m.invoicesLoad, 0) / performanceMetrics.length,
|
|
paymentsLoad: performanceMetrics.reduce((sum, m) => sum + m.paymentsLoad, 0) / performanceMetrics.length,
|
|
dashboardLoad: performanceMetrics.reduce((sum, m) => sum + m.dashboardLoad, 0) / performanceMetrics.length,
|
|
total: performanceMetrics.reduce((sum, m) => sum + m.total, 0) / performanceMetrics.length
|
|
};
|
|
|
|
console.log('📈 Average Performance Metrics:', averages);
|
|
|
|
// Validate against baselines
|
|
assertPerformanceBaseline(averages.companySelect, PerformanceBaselines.dashboardLoad, 'Company selection', expect);
|
|
assertPerformanceBaseline(averages.invoicesLoad, PerformanceBaselines.reportGeneration, 'Invoices loading', expect);
|
|
assertPerformanceBaseline(averages.paymentsLoad, PerformanceBaselines.reportGeneration, 'Payments loading', expect);
|
|
assertPerformanceBaseline(averages.dashboardLoad, PerformanceBaselines.dashboardLoad, 'Dashboard loading', expect);
|
|
|
|
// Total workflow should complete reasonably quickly
|
|
expect(averages.total).toBeLessThan(15000); // Max 15s for full workflow
|
|
|
|
// Check for no critical errors across all iterations
|
|
assertNoCriticalErrors(page, expect);
|
|
|
|
console.log('✅ ROMFAST performance under load validated');
|
|
});
|
|
}); |