Files
roa2web-service-auto/reports-app/frontend/tests/e2e/dashboard/dashboard.spec.js
Marius Mutu 6b13ffa183 Initial commit: ROA2WEB - FastAPI + Vue.js + Telegram Bot
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
2025-10-25 14:55:08 +03:00

228 lines
7.3 KiB
JavaScript

import { test, expect } from '@playwright/test';
import { LoginPage } from '../../page-objects/LoginPage.js';
import { DashboardPage } from '../../page-objects/DashboardPage.js';
import { testCredentials } from '../../fixtures/auth.js';
test.describe('Dashboard View', () => {
let loginPage;
let dashboardPage;
test.beforeEach(async ({ page }) => {
loginPage = new LoginPage(page);
dashboardPage = new DashboardPage(page);
// Mock successful authentication
await page.route('**/api/auth/login', async route => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
access_token: 'mock_access_token',
refresh_token: 'mock_refresh_token',
user: {
id: 1,
username: 'testuser',
full_name: 'Test User'
}
}),
});
});
// Mock companies endpoint
await page.route('**/api/companies', async route => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify([
{ code: 'COMP1', name: 'Compania Test 1' },
{ code: 'COMP2', name: 'Compania Test 2' }
]),
});
});
// Mock invoices summary endpoint
await page.route('**/api/invoices/*/summary', async route => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
total: 150,
paid: 120,
overdue: 30,
amount: 850000.50
}),
});
});
// Mock payments summary endpoint
await page.route('**/api/payments/*/summary', async route => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
total: 125,
amount: 750000.25
}),
});
});
// Login first
await loginPage.navigate();
await loginPage.login(testCredentials.valid.username, testCredentials.valid.password);
await page.waitForURL('/dashboard');
});
test('should display dashboard page correctly', async ({ page: _page }) => {
// Check page elements
expect(await dashboardPage.isOnDashboardPage()).toBe(true);
// Check page title contains "Dashboard"
const title = await dashboardPage.getPageTitle();
expect(title).toContain('Dashboard');
// Check welcome message includes username
const welcomeMessage = await dashboardPage.getWelcomeMessage();
expect(welcomeMessage).toContain('testuser');
});
test('should show company selection when no company selected', async ({ page: _page }) => {
// Wait for dashboard to load
await dashboardPage.waitForDashboardLoad();
// Should show company selection card
expect(await dashboardPage.isCompanySelectionVisible()).toBe(true);
// Dashboard content should not be visible yet
expect(await dashboardPage.isDashboardContentVisible()).toBe(false);
});
test('should display dashboard content after company selection', async ({ page }) => {
// Wait for dashboard to load
await dashboardPage.waitForDashboardLoad();
// Select a company
await dashboardPage.selectCompany('Compania Test 1');
// Wait for dashboard content to appear
await page.waitForSelector(dashboardPage.dashboardContent, { timeout: 10000 });
// Dashboard content should now be visible
expect(await dashboardPage.isDashboardContentVisible()).toBe(true);
// Stats cards should be visible
expect(await dashboardPage.areStatsCardsVisible()).toBe(true);
});
test('should display correct statistics after company selection', async ({ page }) => {
// Wait for dashboard to load and select company
await dashboardPage.waitForDashboardLoad();
await dashboardPage.selectCompany('Compania Test 1');
// Wait for stats to load
await page.waitForSelector(dashboardPage.statsGrid, { timeout: 10000 });
// Check statistics values
const stats = await dashboardPage.getStatsData();
expect(stats.invoices).toBe('150');
expect(stats.payments).toBe('125');
expect(stats.company).toContain('Compania Test 1');
});
test('should navigate to invoices view when clicking invoices action', async ({ page }) => {
// Setup dashboard with company selected
await dashboardPage.waitForDashboardLoad();
await dashboardPage.selectCompany('Compania Test 1');
await page.waitForSelector(dashboardPage.dashboardContent);
// Click invoices action button
await dashboardPage.clickInvoicesAction();
// Should navigate to invoices page
await page.waitForURL('/invoices');
expect(page.url()).toContain('/invoices');
});
test('should navigate to payments view when clicking payments action', async ({ page }) => {
// Setup dashboard with company selected
await dashboardPage.waitForDashboardLoad();
await dashboardPage.selectCompany('Compania Test 1');
await page.waitForSelector(dashboardPage.dashboardContent);
// Click payments action button
await dashboardPage.clickPaymentsAction();
// Should navigate to payments page
await page.waitForURL('/payments');
expect(page.url()).toContain('/payments');
});
test('should handle API errors gracefully', async ({ page }) => {
// Mock companies API error
await page.route('**/api/companies', async route => {
await route.fulfill({
status: 500,
contentType: 'application/json',
body: JSON.stringify({
detail: 'Internal server error'
}),
});
});
// Navigate to dashboard
await dashboardPage.navigate();
// Should still show the page but might show error messages
expect(await dashboardPage.isOnDashboardPage()).toBe(true);
// Check for error toast messages
const errorToast = page.locator('.p-toast-message-error');
if (await errorToast.isVisible()) {
const errorText = await errorToast.textContent();
expect(errorText.toLowerCase()).toContain('eroare');
}
});
test('should update stats when switching between companies', async ({ page }) => {
// Mock different stats for second company
await page.route('**/api/invoices/COMP2/summary', async route => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
total: 200,
paid: 180,
overdue: 20,
amount: 1200000.75
}),
});
});
await page.route('**/api/payments/COMP2/summary', async route => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({
total: 175,
amount: 950000.50
}),
});
});
// Select first company
await dashboardPage.waitForDashboardLoad();
await dashboardPage.selectCompany('Compania Test 1');
await page.waitForSelector(dashboardPage.statsGrid);
const stats1 = await dashboardPage.getStatsData();
expect(stats1.invoices).toBe('150');
// Switch to second company
await dashboardPage.selectCompany('Compania Test 2');
await dashboardPage.waitForLoadingToFinish();
const stats2 = await dashboardPage.getStatsData();
expect(stats2.invoices).toBe('200');
expect(stats2.company).toContain('Compania Test 2');
});
});