82 lines
3.3 KiB
TypeScript
82 lines
3.3 KiB
TypeScript
|
|
import { Page } from '@playwright/test';
|
||
|
|
import { getEnvironmentConfig } from './environment';
|
||
|
|
|
||
|
|
const env = getEnvironmentConfig();
|
||
|
|
|
||
|
|
export const TEST_CREDENTIALS = {
|
||
|
|
username: env.username,
|
||
|
|
password: env.password,
|
||
|
|
loginPath: process.env.TEST_LOGIN_PATH || '/neopaas/portal/login',
|
||
|
|
dashboardPath: '/dashboard',
|
||
|
|
};
|
||
|
|
|
||
|
|
export async function loginAs(page: Page, identifier: string, password: string): Promise<void> {
|
||
|
|
console.log('Starting login process...');
|
||
|
|
|
||
|
|
// The initial navigation is the most failure-prone step on a loaded local
|
||
|
|
// machine (headless browser launch/navigation can occasionally stall well
|
||
|
|
// past a single timeout even though the server itself responds in ~1-3s) -
|
||
|
|
// retry it in place rather than letting one slow navigation fail the whole
|
||
|
|
// test and force an expensive full test-level retry.
|
||
|
|
let lastError: unknown;
|
||
|
|
for (let attempt = 1; attempt <= 3; attempt++) {
|
||
|
|
try {
|
||
|
|
await page.goto(TEST_CREDENTIALS.loginPath, { waitUntil: 'domcontentloaded' });
|
||
|
|
lastError = undefined;
|
||
|
|
break;
|
||
|
|
} catch (error) {
|
||
|
|
lastError = error;
|
||
|
|
console.log(`Login page navigation attempt ${attempt} failed, retrying...`);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (lastError) throw lastError;
|
||
|
|
|
||
|
|
await page.waitForTimeout(2000);
|
||
|
|
|
||
|
|
// The button's own text is the language you'd switch TO, not the current
|
||
|
|
// one - so it reads "English" while the page is in Arabic (click to go to
|
||
|
|
// English), and "العربية" once already in English. The language preference
|
||
|
|
// persists across logout/login (e.g. via localStorage), so on a second
|
||
|
|
// login within the same test the page may already be in English - only
|
||
|
|
// click when the button would actually switch TO English.
|
||
|
|
console.log('Checking for language switcher...');
|
||
|
|
|
||
|
|
const languageArticle = page.locator('article.ant-typography.font-poppins-500.css-1kfsfla').first();
|
||
|
|
const isVisible = await languageArticle.isVisible({ timeout: 2000 }).catch(() => false);
|
||
|
|
|
||
|
|
if (isVisible) {
|
||
|
|
const text = (await languageArticle.textContent())?.trim();
|
||
|
|
console.log(`Found language button with text: "${text}"`);
|
||
|
|
if (text === 'English') {
|
||
|
|
console.log('Clicking to switch language to English...');
|
||
|
|
await languageArticle.click();
|
||
|
|
await page.waitForTimeout(2000);
|
||
|
|
console.log('✓ Language switched');
|
||
|
|
} else {
|
||
|
|
console.log('Already in English - no switch needed');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
console.log('Filling username...');
|
||
|
|
await page.fill('input[type="email"], input[type="text"], input[name="email"], input[name="username"], input[placeholder*="email" i], input[placeholder*="username" i]', identifier);
|
||
|
|
|
||
|
|
console.log('Filling password...');
|
||
|
|
await page.fill('input[type="password"], input[name="password"]', password);
|
||
|
|
|
||
|
|
console.log('Clicking login button...');
|
||
|
|
await page.click('button[type="submit"], button:has-text("Login"), button:has-text("Sign in")');
|
||
|
|
|
||
|
|
console.log('Waiting for redirect...');
|
||
|
|
await page.waitForURL(/\/(dashboard|terminals)/, { timeout: 30000 }).catch(() => {
|
||
|
|
console.log('Post-login URL not detected, checking for navigation...');
|
||
|
|
});
|
||
|
|
|
||
|
|
await page.waitForLoadState('domcontentloaded').catch(() => {});
|
||
|
|
await page.waitForTimeout(2000);
|
||
|
|
console.log('Login completed successfully');
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function login(page: Page): Promise<void> {
|
||
|
|
await loginAs(page, TEST_CREDENTIALS.username, TEST_CREDENTIALS.password);
|
||
|
|
}
|