Files
roa2web-service-auto/reports-app/frontend/tests/e2e/responsive/breakpoints.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

237 lines
8.7 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('Responsive Design Tests', () => {
let loginPage;
let dashboardPage;
// Common setup for all responsive tests
const setupMockAuth = async (page) => {
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' }
}),
});
});
await page.route('**/api/companies', async route => {
await route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify([
{ code: 'COMP1', name: 'Test Company' }
]),
});
});
};
test.describe('Mobile Layout (320px)', () => {
test.beforeEach(async ({ page }) => {
await page.setViewportSize({ width: 320, height: 568 });
loginPage = new LoginPage(page);
dashboardPage = new DashboardPage(page);
await setupMockAuth(page);
});
test('should display login form correctly on mobile', async ({ page }) => {
await loginPage.navigate();
// Take screenshot for visual verification
await page.screenshot({ path: 'mobile-login.png', fullPage: true });
// Login form should be visible and properly sized
await expect(page.locator(loginPage.loginCard)).toBeVisible();
await expect(page.locator(loginPage.usernameInput)).toBeVisible();
await expect(page.locator(loginPage.passwordInput)).toBeVisible();
// Check that form takes appropriate width
const cardWidth = await page.locator(loginPage.loginCard).boundingBox();
expect(cardWidth.width).toBeLessThan(320); // Should fit in viewport
});
test('should adapt dashboard layout for mobile', async ({ page }) => {
// Login and navigate to dashboard
await loginPage.navigate();
await loginPage.login(testCredentials.valid.username, testCredentials.valid.password);
await page.waitForURL('/dashboard');
// Take screenshot
await page.screenshot({ path: 'mobile-dashboard.png', fullPage: true });
// Dashboard should be responsive
await expect(page.locator(dashboardPage.pageTitle)).toBeVisible();
// Stats grid should stack vertically on mobile
const statsGrid = page.locator(dashboardPage.statsGrid);
if (await statsGrid.isVisible()) {
const gridBox = await statsGrid.boundingBox();
expect(gridBox.width).toBeLessThan(320);
}
});
});
test.describe('Tablet Layout (768px)', () => {
test.beforeEach(async ({ page }) => {
await page.setViewportSize({ width: 768, height: 1024 });
loginPage = new LoginPage(page);
dashboardPage = new DashboardPage(page);
await setupMockAuth(page);
});
test('should display login form appropriately on tablet', async ({ page }) => {
await loginPage.navigate();
await page.screenshot({ path: 'tablet-login.png', fullPage: true });
// Login card should be centered and well-proportioned
const loginCard = page.locator(loginPage.loginCard);
await expect(loginCard).toBeVisible();
const cardBox = await loginCard.boundingBox();
expect(cardBox.width).toBeGreaterThan(300);
expect(cardBox.width).toBeLessThan(500);
});
test('should show proper tablet dashboard layout', async ({ page }) => {
await loginPage.navigate();
await loginPage.login(testCredentials.valid.username, testCredentials.valid.password);
await page.waitForURL('/dashboard');
await page.screenshot({ path: 'tablet-dashboard.png', fullPage: true });
// Dashboard elements should be properly spaced
await expect(page.locator(dashboardPage.pageTitle)).toBeVisible();
// Stats should be arranged in appropriate grid
const statsCards = page.locator('.stat-card');
const cardCount = await statsCards.count();
if (cardCount > 0) {
// Cards should be visible and properly sized
for (let i = 0; i < cardCount; i++) {
await expect(statsCards.nth(i)).toBeVisible();
}
}
});
});
test.describe('Desktop Layout (1024px+)', () => {
test.beforeEach(async ({ page }) => {
await page.setViewportSize({ width: 1024, height: 768 });
loginPage = new LoginPage(page);
dashboardPage = new DashboardPage(page);
await setupMockAuth(page);
});
test('should display full desktop login layout', async ({ page }) => {
await loginPage.navigate();
await page.screenshot({ path: 'desktop-login.png', fullPage: true });
// Login should be centered with appropriate sizing
const loginCard = page.locator(loginPage.loginCard);
await expect(loginCard).toBeVisible();
// Card should not take full width on desktop
const cardBox = await loginCard.boundingBox();
expect(cardBox.width).toBeLessThan(500);
});
test('should show complete desktop dashboard layout', async ({ page }) => {
await loginPage.navigate();
await loginPage.login(testCredentials.valid.username, testCredentials.valid.password);
await page.waitForURL('/dashboard');
await page.screenshot({ path: 'desktop-dashboard.png', fullPage: true });
// All dashboard elements should be visible
await expect(page.locator(dashboardPage.pageTitle)).toBeVisible();
await expect(page.locator(dashboardPage.pageSubtitle)).toBeVisible();
// Stats grid should use horizontal layout
const statsGrid = page.locator(dashboardPage.statsGrid);
if (await statsGrid.isVisible()) {
const gridBox = await statsGrid.boundingBox();
expect(gridBox.width).toBeGreaterThan(600);
}
});
});
test.describe('Wide Screen Layout (1920px)', () => {
test.beforeEach(async ({ page }) => {
await page.setViewportSize({ width: 1920, height: 1080 });
loginPage = new LoginPage(page);
dashboardPage = new DashboardPage(page);
await setupMockAuth(page);
});
test('should handle wide screen layouts appropriately', async ({ page }) => {
await loginPage.navigate();
await loginPage.login(testCredentials.valid.username, testCredentials.valid.password);
await page.waitForURL('/dashboard');
await page.screenshot({ path: 'widescreen-dashboard.png', fullPage: true });
// Content should not stretch too wide
const mainContent = page.locator('.dashboard-content');
if (await mainContent.isVisible()) {
const contentBox = await mainContent.boundingBox();
// Content should have reasonable max-width
expect(contentBox.width).toBeLessThan(1600);
}
});
});
test.describe('Orientation Changes', () => {
test('should handle portrait to landscape orientation', async ({ page }) => {
// Start in mobile portrait
await page.setViewportSize({ width: 375, height: 667 });
loginPage = new LoginPage(page);
await setupMockAuth(page);
await loginPage.navigate();
await page.screenshot({ path: 'mobile-portrait.png' });
// Rotate to landscape
await page.setViewportSize({ width: 667, height: 375 });
await page.waitForTimeout(500); // Allow for reflow
await page.screenshot({ path: 'mobile-landscape.png' });
// Login form should still be usable
await expect(page.locator(loginPage.loginCard)).toBeVisible();
await expect(page.locator(loginPage.usernameInput)).toBeVisible();
});
});
test.describe('Touch Interactions', () => {
test('should handle touch interactions on mobile', async ({ page }) => {
await page.setViewportSize({ width: 375, height: 667 });
loginPage = new LoginPage(page);
await setupMockAuth(page);
await loginPage.navigate();
// Test touch interactions
await page.tap(loginPage.usernameInput);
await page.fill(loginPage.usernameInput, 'testuser');
await page.tap(loginPage.passwordInput);
await page.fill(loginPage.passwordInput, 'testpass');
// Login button should be tappable
const loginButton = page.locator(loginPage.loginButton);
await expect(loginButton).toBeEnabled();
// Button should have appropriate touch target size (minimum 44px)
const buttonBox = await loginButton.boundingBox();
expect(buttonBox.height).toBeGreaterThanOrEqual(44);
});
});
});