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
129 lines
3.9 KiB
JavaScript
129 lines
3.9 KiB
JavaScript
import { BasePage } from './BasePage.js';
|
|
|
|
export class DashboardPage extends BasePage {
|
|
constructor(page) {
|
|
super(page);
|
|
|
|
// Header selectors
|
|
this.pageTitle = '.page-title';
|
|
this.pageSubtitle = '.page-subtitle';
|
|
this.userWelcome = '.page-subtitle';
|
|
|
|
// Company selection selectors
|
|
this.companySelectionCard = '.company-selection-card';
|
|
this.companyDropdown = '.company-selection .p-dropdown';
|
|
this.companyDropdownTrigger = '.company-selection .p-dropdown-trigger';
|
|
this.companyOptions = '.p-dropdown-item';
|
|
|
|
// Stats cards selectors
|
|
this.statsGrid = '.stats-grid';
|
|
this.invoicesStatCard = '.stat-card.stat-invoices';
|
|
this.paymentsStatCard = '.stat-card.stat-payments';
|
|
this.companyStatCard = '.stat-card.stat-company';
|
|
|
|
// Stat values
|
|
this.invoicesTotal = '.stat-invoices .stat-value';
|
|
this.paymentsTotal = '.stat-payments .stat-value';
|
|
this.companyName = '.stat-company .stat-value';
|
|
|
|
// Quick actions
|
|
this.quickActionsCard = '.quick-actions-card';
|
|
this.invoicesActionButton = 'button:has-text("Facturi")';
|
|
this.paymentsActionButton = 'button:has-text("Încasări")';
|
|
|
|
// Navigation
|
|
this.dashboardContent = '.dashboard-content';
|
|
}
|
|
|
|
async navigate() {
|
|
await this.page.goto('/dashboard');
|
|
await this.page.waitForSelector(this.pageTitle);
|
|
}
|
|
|
|
async isOnDashboardPage() {
|
|
return await this.page.locator(this.pageTitle).isVisible();
|
|
}
|
|
|
|
async getPageTitle() {
|
|
return await this.page.locator(this.pageTitle).textContent();
|
|
}
|
|
|
|
async getWelcomeMessage() {
|
|
return await this.page.locator(this.userWelcome).textContent();
|
|
}
|
|
|
|
async isCompanySelectionVisible() {
|
|
return await this.page.locator(this.companySelectionCard).isVisible();
|
|
}
|
|
|
|
async isDashboardContentVisible() {
|
|
return await this.page.locator(this.dashboardContent).isVisible();
|
|
}
|
|
|
|
async selectCompany(companyName) {
|
|
// Click dropdown to open options
|
|
await this.page.click(this.companyDropdownTrigger);
|
|
|
|
// Wait for options to appear and select the company
|
|
await this.page.waitForSelector(this.companyOptions);
|
|
await this.page.click(`${this.companyOptions}:has-text("${companyName}")`);
|
|
|
|
// Wait for selection to be processed
|
|
await this.waitForLoadingToFinish();
|
|
}
|
|
|
|
async getSelectedCompanyName() {
|
|
if (await this.page.locator(this.companyName).isVisible()) {
|
|
return await this.page.locator(this.companyName).textContent();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
async getInvoicesCount() {
|
|
if (await this.page.locator(this.invoicesTotal).isVisible()) {
|
|
return await this.page.locator(this.invoicesTotal).textContent();
|
|
}
|
|
return '0';
|
|
}
|
|
|
|
async getPaymentsCount() {
|
|
if (await this.page.locator(this.paymentsTotal).isVisible()) {
|
|
return await this.page.locator(this.paymentsTotal).textContent();
|
|
}
|
|
return '0';
|
|
}
|
|
|
|
async clickInvoicesAction() {
|
|
await this.page.click(this.invoicesActionButton);
|
|
await this.waitForNavigation();
|
|
}
|
|
|
|
async clickPaymentsAction() {
|
|
await this.page.click(this.paymentsActionButton);
|
|
await this.waitForNavigation();
|
|
}
|
|
|
|
async areStatsCardsVisible() {
|
|
const invoicesVisible = await this.page.locator(this.invoicesStatCard).isVisible();
|
|
const paymentsVisible = await this.page.locator(this.paymentsStatCard).isVisible();
|
|
const companyVisible = await this.page.locator(this.companyStatCard).isVisible();
|
|
|
|
return invoicesVisible && paymentsVisible && companyVisible;
|
|
}
|
|
|
|
async getStatsData() {
|
|
return {
|
|
invoices: await this.getInvoicesCount(),
|
|
payments: await this.getPaymentsCount(),
|
|
company: await this.getSelectedCompanyName()
|
|
};
|
|
}
|
|
|
|
async waitForDashboardLoad() {
|
|
// Wait for either company selection or dashboard content to appear
|
|
await Promise.race([
|
|
this.page.waitForSelector(this.companySelectionCard, { timeout: 10000 }),
|
|
this.page.waitForSelector(this.dashboardContent, { timeout: 10000 })
|
|
]);
|
|
}
|
|
} |