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
This commit is contained in:
99
reports-app/frontend/tests/page-objects/LoginPage.js
Normal file
99
reports-app/frontend/tests/page-objects/LoginPage.js
Normal file
@@ -0,0 +1,99 @@
|
||||
import { BasePage } from './BasePage.js';
|
||||
|
||||
export class LoginPage extends BasePage {
|
||||
constructor(page) {
|
||||
super(page);
|
||||
|
||||
// Selectors
|
||||
this.usernameInput = '#username';
|
||||
this.passwordInput = '#password input';
|
||||
this.loginButton = 'button[type="submit"]';
|
||||
this.errorMessage = '.error-message';
|
||||
this.loadingSpinner = '.p-button-loading';
|
||||
this.loginTitle = '.login-title';
|
||||
this.loginCard = '.login-card';
|
||||
|
||||
// Form validation selectors
|
||||
this.usernameError = '.field:has(#username) .p-error';
|
||||
this.passwordError = '.field:has(#password) .p-error';
|
||||
this.invalidField = '.p-invalid';
|
||||
}
|
||||
|
||||
async navigate() {
|
||||
await this.page.goto('/');
|
||||
await this.page.waitForSelector(this.loginCard);
|
||||
}
|
||||
|
||||
async fillCredentials(username, password) {
|
||||
await this.page.fill(this.usernameInput, username);
|
||||
await this.page.fill(this.passwordInput, password);
|
||||
}
|
||||
|
||||
async clickLogin() {
|
||||
await this.page.click(this.loginButton);
|
||||
}
|
||||
|
||||
async login(username, password) {
|
||||
await this.fillCredentials(username, password);
|
||||
await this.clickLogin();
|
||||
}
|
||||
|
||||
async waitForLoginResult() {
|
||||
// Wait for either redirect to dashboard or error message
|
||||
try {
|
||||
await Promise.race([
|
||||
this.page.waitForURL('/dashboard', { timeout: 5000 }),
|
||||
this.page.waitForSelector(this.errorMessage, { timeout: 5000 })
|
||||
]);
|
||||
} catch (error) {
|
||||
// Continue - we'll check the state separately
|
||||
}
|
||||
}
|
||||
|
||||
async isOnLoginPage() {
|
||||
return await this.page.locator(this.loginTitle).isVisible();
|
||||
}
|
||||
|
||||
async isLoginButtonDisabled() {
|
||||
return await this.page.locator(this.loginButton).isDisabled();
|
||||
}
|
||||
|
||||
async isLoading() {
|
||||
return await this.page.locator(this.loadingSpinner).isVisible();
|
||||
}
|
||||
|
||||
async getErrorMessage() {
|
||||
const errorElement = this.page.locator(this.errorMessage);
|
||||
if (await errorElement.isVisible()) {
|
||||
return await errorElement.textContent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async getFieldError(field) {
|
||||
const selector = field === 'username' ? this.usernameError : this.passwordError;
|
||||
const errorElement = this.page.locator(selector);
|
||||
if (await errorElement.isVisible()) {
|
||||
return await errorElement.textContent();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async hasInvalidField() {
|
||||
return await this.page.locator(this.invalidField).count() > 0;
|
||||
}
|
||||
|
||||
async clearForm() {
|
||||
await this.page.fill(this.usernameInput, '');
|
||||
await this.page.fill(this.passwordInput, '');
|
||||
}
|
||||
|
||||
async validateFormFields() {
|
||||
// Trigger validation by clicking outside fields
|
||||
await this.page.click(this.loginCard);
|
||||
}
|
||||
|
||||
async getPageTitle() {
|
||||
return await this.page.locator(this.loginTitle).textContent();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user