feat: establish Playwright E2E testing infrastructure with configuration and initial tests
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { LoginPage } from '../pages/login.page';
|
||||
|
||||
/**
|
||||
* Login Smoke Tests
|
||||
*
|
||||
* This test suite validates the core login functionality of the Mifos X Web App.
|
||||
* These tests use a strict Page Object Model with selectors from Playwright codegen.
|
||||
*
|
||||
* Prerequisites:
|
||||
* - Angular dev server running on http://localhost:4200
|
||||
* - Fineract backend accessible (via proxy to https://localhost:8443)
|
||||
*
|
||||
* Test Data:
|
||||
* - Valid credentials: mifos / password
|
||||
*/
|
||||
test.describe('Login Page', () => {
|
||||
let loginPage: LoginPage;
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
loginPage = new LoginPage(page);
|
||||
await loginPage.navigate();
|
||||
});
|
||||
|
||||
test('should display the login form', async () => {
|
||||
// Verify the login form is visible
|
||||
await loginPage.assertOnLoginPage();
|
||||
|
||||
// Verify form elements are present (using codegen selectors)
|
||||
await expect(loginPage.usernameInput).toBeVisible();
|
||||
await expect(loginPage.passwordInput).toBeVisible();
|
||||
await expect(loginPage.loginButton).toBeVisible();
|
||||
});
|
||||
|
||||
test('should disable login button when form is empty', async () => {
|
||||
// Login button should be disabled with empty fields
|
||||
await expect(loginPage.loginButton).toBeDisabled();
|
||||
});
|
||||
|
||||
test('should show validation errors for required fields', async ({ page }) => {
|
||||
// Focus and blur username field to trigger validation
|
||||
await loginPage.usernameInput.focus();
|
||||
await loginPage.passwordInput.focus();
|
||||
await page.keyboard.press('Tab');
|
||||
|
||||
// Check for validation error messages
|
||||
const hasErrors = await loginPage.getErrorCount();
|
||||
expect(hasErrors).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
test('should enable login button when credentials are entered', async () => {
|
||||
// Fill in credentials using the wrapper clicks (as per codegen)
|
||||
await loginPage.usernameDivWrapper.click();
|
||||
await loginPage.usernameInput.fill('mifos');
|
||||
await loginPage.passwordDivWrapper.click();
|
||||
await loginPage.passwordInput.fill('password');
|
||||
|
||||
// Login button should become enabled
|
||||
await expect(loginPage.loginButton).toBeEnabled();
|
||||
});
|
||||
|
||||
// Skip in CI - requires Fineract backend
|
||||
test.skip(!!process.env.CI, 'Requires Fineract backend');
|
||||
test('should successfully login with valid credentials', async () => {
|
||||
// Perform login with valid credentials
|
||||
// This uses the login() method which follows the exact codegen sequence
|
||||
await loginPage.loginAndWaitForDashboard('mifos', 'password');
|
||||
|
||||
// Assert we're no longer on the login page
|
||||
await loginPage.assertLoginSuccess();
|
||||
});
|
||||
|
||||
test('should handle invalid credentials gracefully', async ({ page }) => {
|
||||
// Attempt login with wrong password
|
||||
await loginPage.login('mifos', 'wrongpassword');
|
||||
|
||||
// Wait for the login attempt to process and any error notification to appear
|
||||
// The app shows a snackbar notification for authentication errors
|
||||
await page.waitForTimeout(3000);
|
||||
|
||||
// Should remain on login page after failed attempt (URL still contains /login)
|
||||
await expect(page).toHaveURL(/.*login.*/);
|
||||
|
||||
// Verify we're still on the login page by checking form elements are visible
|
||||
await expect(loginPage.usernameInput).toBeVisible();
|
||||
await expect(loginPage.passwordInput).toBeVisible();
|
||||
});
|
||||
|
||||
/**
|
||||
* Simple test that exactly mirrors the codegen script.
|
||||
* This is the baseline test generated from codegen.
|
||||
*/
|
||||
// Skip in CI - requires Fineract backend
|
||||
test.skip(!!process.env.CI, 'Requires Fineract backend');
|
||||
test('codegen baseline: login with mifos credentials', async () => {
|
||||
// This test uses the exact codegen interaction sequence
|
||||
await loginPage.login('mifos', 'password');
|
||||
|
||||
// Verify successful login
|
||||
await loginPage.assertLoginSuccess();
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Accessibility smoke test
|
||||
*/
|
||||
test.describe('Login Page Accessibility', () => {
|
||||
let loginPage: LoginPage;
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
loginPage = new LoginPage(page);
|
||||
await loginPage.navigate();
|
||||
});
|
||||
|
||||
test('should have proper page title', async ({ page }) => {
|
||||
const title = await page.title();
|
||||
expect(title).toBeTruthy();
|
||||
});
|
||||
|
||||
test('should support keyboard navigation', async ({ page }) => {
|
||||
// Tab through form elements
|
||||
await page.keyboard.press('Tab');
|
||||
await page.keyboard.press('Tab');
|
||||
await page.keyboard.press('Tab');
|
||||
|
||||
// Form should be navigable via keyboard
|
||||
await expect(loginPage.loginButton).toBeVisible();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user