All checks were successful
Build and Push Docker Image / build (push) Successful in 25s
#8 Mobile/Responsive (14 PASS, 2 minor WARN): - 8 pages × 2 viewports (iPhone 375px + iPad 768px) = 16 checks - All dashboard/list/analytics pages: no overflow, content renders ✅ - Public complaint/observation forms: minor 13px horizontal overflow at 375px (cosmetic) #9 i18n/Arabic (6 PASS): - Language switch to Arabic: dir=rtl, lang=ar, Arabic text present on all 5 pages ✅ - No horizontal overflow in RTL layout ✅ - English restoration works (dir back to ltr) ✅
99 lines
4.0 KiB
TypeScript
99 lines
4.0 KiB
TypeScript
/* eslint-disable */
|
|
/**
|
|
* I18N / ARABIC TEST — RTL layout + Arabic text rendering.
|
|
* Switches language to Arabic, verifies dir="rtl", Arabic text, layout.
|
|
*
|
|
* Run headed:
|
|
* E2E_MAXIMATED=1 npx playwright test --headed --project chromium i18n-arabic-test --workers=1
|
|
*/
|
|
import { test } from '@playwright/test';
|
|
import { attachObservers, observe, loginAndScope, OBS, BASE_URL } from '../../helpers/audit';
|
|
import { RoleName } from '../../helpers/helpers';
|
|
|
|
const M = 'I18N';
|
|
const ADMIN: RoleName = 'hospital_admin';
|
|
|
|
type Page = import('@playwright/test').Page;
|
|
|
|
async function login(page: Page) { await page.context().clearCookies(); await loginAndScope(page, ADMIN, M); }
|
|
|
|
test.describe('i18n / Arabic', () => {
|
|
test.describe.configure({ mode: 'serial' });
|
|
|
|
test('Switch to Arabic + verify RTL + Arabic text on key pages', async ({ page }) => {
|
|
attachObservers(page, M, ADMIN);
|
|
await login(page);
|
|
|
|
// 1. Switch language to Arabic via the set-language endpoint
|
|
const csrf = await page.context().cookies().then((c) => c.find((x) => x.name === 'csrftoken')?.value || '');
|
|
await page.context().request.post(`${BASE_URL}/i18n/setlang/`, {
|
|
headers: { 'X-CSRFToken': csrf },
|
|
form: { csrfmiddlewaretoken: csrf, language: 'ar' },
|
|
maxRedirects: 0,
|
|
}).catch(() => {});
|
|
|
|
// 2. Visit key pages and check RTL + Arabic
|
|
const pages = [
|
|
{ url: '/', label: 'dashboard' },
|
|
{ url: '/complaints/', label: 'complaint-list' },
|
|
{ url: '/complaints/public/submit/', label: 'public-form' },
|
|
{ url: '/observations/new/', label: 'obs-form' },
|
|
{ url: '/core/public/submit/', label: 'public-landing' },
|
|
];
|
|
|
|
for (const { url, label } of pages) {
|
|
try {
|
|
await page.goto(`${BASE_URL}${url}`);
|
|
await page.waitForLoadState('domcontentloaded');
|
|
await page.waitForTimeout(1000);
|
|
|
|
// Check dir attribute
|
|
const htmlDir = await page.evaluate(() => document.documentElement.dir);
|
|
const htmlLang = await page.evaluate(() => document.documentElement.lang);
|
|
|
|
// Check for Arabic text (basic Unicode range check)
|
|
const body = (await page.textContent('body')) || '';
|
|
const hasArabic = /[\u0600-\u06FF]/.test(body);
|
|
|
|
// Check for layout issues (horizontal scrollbar)
|
|
const scrollWidth = await page.evaluate(() => document.documentElement.scrollWidth);
|
|
const clientWidth = await page.evaluate(() => document.documentElement.clientWidth);
|
|
const hasOverflow = scrollWidth > clientWidth + 10;
|
|
|
|
const rtlOk = htmlDir === 'rtl';
|
|
const langOk = htmlLang === 'ar' || htmlLang.includes('ar');
|
|
const arabicOk = hasArabic;
|
|
const layoutOk = !hasOverflow;
|
|
|
|
const allOk = rtlOk && arabicOk && layoutOk;
|
|
observe(M, `${label}-arabic`, allOk ? 'PASS' : 'WARN',
|
|
`dir=${htmlDir} lang=${htmlLang} arabic=${hasArabic} overflow=${hasOverflow} body=${body.length}`,
|
|
{ url: page.url() });
|
|
} catch (e) {
|
|
observe(M, `${label}-arabic`, 'FAIL', `exception: ${(e as Error).message.slice(0, 100)}`, {});
|
|
}
|
|
}
|
|
|
|
// 3. Switch back to English
|
|
await page.context().request.post(`${BASE_URL}/i18n/setlang/`, {
|
|
headers: { 'X-CSRFToken': csrf },
|
|
form: { csrfmiddlewaretoken: csrf, language: 'en' },
|
|
maxRedirects: 0,
|
|
}).catch(() => {});
|
|
|
|
// Verify English restored
|
|
await page.goto(`${BASE_URL}/`);
|
|
await page.waitForLoadState('domcontentloaded');
|
|
const htmlDirEn = await page.evaluate(() => document.documentElement.dir);
|
|
observe(M, 'restore-english', htmlDirEn !== 'rtl' ? 'PASS' : 'WARN',
|
|
`after switching back to EN: dir=${htmlDirEn}`, {});
|
|
});
|
|
});
|
|
|
|
test.afterAll(async () => {
|
|
const counts = OBS.reduce<Record<string, number>>((a, o) => ((a[o.status] = (a[o.status] || 0) + 1), a), {});
|
|
console.log('\n=========== I18N / ARABIC SUMMARY ===========');
|
|
console.log('Total observations:', OBS.length, JSON.stringify(counts));
|
|
console.log('==============================================\n');
|
|
});
|