QA 25: Accessibility, Localization va Visual testing — WCAG 2.2, axe-core va o'zbek tili nozikliklari
🧪 QA Engineer — Zero to Hero
QA 25: Accessibility, Localization va Visual testing — WCAG 2.2, axe-core va o'zbek tili nozikliklari
Holat: 2026-yil oktabr. Dars WCAG 2.2 (W3C Recommendation, 2023-yil 5-oktabr; joriy tahrir 2024-yil 12-dekabr),
@axe-core/playwright4.13.0 + Playwright 1.64 va Node.js 24 (ICU 78.2, CLDR 48) asosida yozilgan. Barcha axe,Intlva screenshot natijalari haqiqiy ishga tushirishdan olingan.
Bu darsdan keyin siz: mahsulotni "hamma uchun, har tilda va har relizda bir xil ko'rinishda" ishlashini tekshira olasiz:
- WCAG 2.2 ning POUR printsiplari va AA darajasini amalda (klaviatura, kontrast, label, screen reader) tekshirasiz;
- axe-core'ni Playwright testlariga qo'shib, natijani o'qiysiz va avtomatlashtirish chegarasini bilasiz;
- o'zbek tili (lotin/kirill,
oʻ/gʻ, apostroflar), rus plural shakllari, sana/son/valyuta formatlarini sinaysiz; toHaveScreenshotbilan visual regression testlar yozasiz;- Nielsen evristikalari bilan tezkor usability tahlil qilasiz.
Mundarija
- Nega accessibility muhim
- WCAG 2.2: POUR, darajalar va yangi mezonlar
- Qo'lda a11y tekshiruvi: klaviatura, kontrast, screen reader
- Avtomatik a11y: axe-core + Playwright
- Mobil accessibility
- i18n va l10n: asosiy tushunchalar
- O'zbek tili nozikliklari: oʻ/gʻ, lotin/kirill, alifbo islohoti
- Sana, son, valyuta va plural: Intl bilan tekshirish
- Visual testing: toHaveScreenshot va vositalar
- Usability asoslari: Nielsen'ning 10 evristikasi
- Amaliy mashqlar
- O'zingizni tekshiring
- Xulosa
- Manbalar
1. Nega accessibility muhim {#nega-a11y}
Accessibility (a11y) — mahsulotdan imkoniyati cheklangan odamlar ham to'liq foydalana olishi: ko'zi ojiz yoki zaif ko'radiganlar (screen reader, kattalashtirish), rang ajratishda qiynaladiganlar, qo'l harakati cheklanganlar (faqat klaviatura yoki switch qurilma), eshitishi zaiflar (subtitr), kognitiv qiyinchiligi borlar.
Bundan tashqari vaziyatli cheklovlar ham bor: quyosh ostida ekran yomon ko'rinadi, bir qo'lda bola ko'tarib telefon ishlatiladi, shovqinli metroda video ovozsiz ko'riladi. A11y uchun qilingan har bir yaxshilanish hammaga foyda beradi.
Qonuniy kontekst. Yevropa Ittifoqining European Accessibility Act (Direktiva 2019/882) 2025-yil 28-iyundan keyin bozorga chiqarilgan mahsulotlar va iste'molchilarga ko'rsatiladigan xizmatlarga qo'llanadi — ro'yxatda e-commerce, bank xizmatlari, elektron kitoblar, smartfon va kompyuterlar bor. DemoBozor Yevropa mijozlariga sotsa yoki ilova xalqaro bozorga chiqsa, bu to'g'ridan-to'g'ri talabga aylanadi.
QA'ning roli — a11y'ni reliz oxirida "bir marta audit" qilish emas, har feature'ning Definition of Done'iga qo'shish: klaviatura bilan o'tib chiqish, avtomatik skaner, kerak bo'lsa screen reader bilan tekshiruv.
🎯 Intervyuda: Accessibility testlashni qanday tashkil qilasiz? — Uch qatlam: (1) har PR'da avtomatik skaner (axe) — tez topiladigan xatolar uchun; (2) har feature'da qo'lda tekshiruv — klaviatura, fokus, kontrast, label'lar, 200% zoom; (3) muhim ssenariylarni screen reader (VoiceOver, NVDA, TalkBack) bilan tekshirish. Mezon — WCAG 2.2 AA.
2. WCAG 2.2: POUR, darajalar va yangi mezonlar {#wcag}
WCAG (Web Content Accessibility Guidelines) — W3C'ning WAI guruhi chiqargan xalqaro standart. WCAG 2.2 2023-yil 5-oktabrda W3C Recommendation bo'ldi (joriy tahrir — 2024-yil 12-dekabr). Muhim jihati: WCAG 2.2 ga mos kontent WCAG 2.1 va 2.0 ga ham mos keladi.
WCAG 2.2 ning to'rt printsipi: Perceivable, Operable, Understandable, Robust va muvofiqlik darajalari
Tuzilma: printsip → guideline → success criterion
- 4 printsip (POUR): Perceivable, Operable, Understandable, Robust.
- Har printsip ostida guideline'lar, ular ostida tekshiriladigan success criterion (SC)'lar bor — masalan,
1.4.3 Contrast (Minimum). - Har SC'ning darajasi: A, AA yoki AAA. Amalda maqsad odatda AA (A + AA mezonlari). W3C'ning o'zi butun sayt uchun AAA'ni umumiy talab qilib qo'yishni tavsiya etmaydi — ba'zi kontent uchun barcha AAA mezonlarini bajarib bo'lmaydi.
QA eng ko'p tekshiradigan mezonlar
| SC | Nomi | Daraja | Qisqacha |
|---|---|---|---|
| 1.1.1 | Non-text Content | A | Rasm/ikonkada mazmunli muqobil matn |
| 1.3.1 | Info and Relationships | A | Sarlavhalar, ro'yxatlar, jadvallar, label'lar kodda ham to'g'ri |
| 1.4.3 | Contrast (Minimum) | AA | Matn ≥ 4.5:1; katta matn (≥ 18pt yoki ≥ 14pt bold) ≥ 3:1 |
| 1.4.10 | Reflow | AA | 320 CSS px kenglikda ikki yo'nalishli scroll'siz ishlaydi |
| 1.4.11 | Non-text Contrast | AA | UI komponentlar va muhim grafika ≥ 3:1 |
| 2.1.1 | Keyboard | A | Hamma funksiya klaviaturadan |
| 2.1.2 | No Keyboard Trap | A | Fokus biror joyda "qamalib" qolmaydi |
| 2.4.3 | Focus Order | A | Fokus tartibi mantiqiy |
| 2.4.7 | Focus Visible | AA | Fokus ko'rinib turadi |
| 3.1.1 | Language of Page | A | <html lang="uz"> |
| 3.3.1 | Error Identification | A | Xato aniqlanib, matn bilan tushuntiriladi |
| 3.3.2 | Labels or Instructions | A | Maydonlarda label yoki ko'rsatma |
| 4.1.2 | Name, Role, Value | A | Har boshqaruv elementining nomi, roli, holati bor |
WCAG 2.2 da qo'shilgan 9 ta mezon
| SC | Nomi | Daraja | QA nimani tekshiradi |
|---|---|---|---|
| 2.4.11 | Focus Not Obscured (Minimum) | AA | Fokusdagi element sticky header/banner ostida to'liq yashirinib qolmaydi |
| 2.4.12 | Focus Not Obscured (Enhanced) | AAA | Fokusdagi element umuman yopilmaydi |
| 2.4.13 | Focus Appearance | AAA | Fokus indikatori yetarlicha katta va kontrastli |
| 2.5.7 | Dragging Movements | AA | Sudrash (drag) bilan qilinadigan amalning bir bosishli muqobili bor |
| 2.5.8 | Target Size (Minimum) | AA | Bosiladigan nishon kamida 24×24 CSS px (istisnolar bor) |
| 3.2.6 | Consistent Help | A | Yordam havolasi har sahifada bir xil joyda |
| 3.3.7 | Redundant Entry | A | Bir jarayonda kiritilgan ma'lumot qayta so'ralmaydi |
| 3.3.8 | Accessible Authentication (Minimum) | AA | Login uchun "eslab qolish yoki hisoblash" testi majburiy emas (parol menejeri, nusxa ko'chirish ishlaydi) |
| 3.3.9 | Accessible Authentication (Enhanced) | AAA | Yuqoridagining qat'iyroq varianti |
4.1.1 Parsing esa eskirgan deb WCAG 2.2 dan olib tashlangan.
🇺🇿 Mahalliy kontekst: DemoBozor'da SMS kod maydoni: 3.3.8 nuqtai nazaridan foydalanuvchi kodni nusxalab qo'ya olishi va telefon SMS kodini avtomatik taklif qilishi (autofill) ishlashi kerak. 6 ta alohida katakchali OTP maydonlari ko'pincha aynan shu joyda buziladi.
WCAG 3.0 haqida
WCAG 3.0 hozircha Working Draft (oxirgi qoralama — 2026-yil 10-sentabr). Hujjatning o'zida u WCAG 2 ni almashtirmasligi va ishlar hali bir necha yil davom etishi aytilgan. Amaliy testlash uchun mezon — WCAG 2.2 AA.
ARIA'ning birinchi qoidasi
W3C'ning "Using ARIA" hujjati: kerakli semantika va xatti-harakat allaqachon mavjud bo'lgan native HTML element yoki atribut bo'lsa — ARIA qo'shish o'rniga o'sha native elementni ishlating. Ya'ni <div role="button" tabindex="0"> emas, <button>. QA uchun signal: kodda role="button" ko'p bo'lsa, klaviatura (Enter/Space), fokus va screen reader'ni ayniqsa sinchiklab tekshiring.
3. Qo'lda a11y tekshiruvi: klaviatura, kontrast, screen reader {#manual-a11y}
5 daqiqalik klaviatura testi
Sichqonchani chetga qo'ying va DemoBozor checkout sahifasini faqat klaviatura bilan bajaring:
| Qadam | Tekshiruv | Kutilgan natija |
|---|---|---|
Tab / Shift+Tab | Hamma interaktiv elementga yetib borasizmi? | Ha, mantiqiy tartibda (2.4.3) |
| Fokus | Hozir qayerda turganingiz ko'rinadimi? | Aniq ko'rinadigan fokus halqasi (2.4.7) |
| Sticky header | Fokusdagi element header ostida qolib ketmaydimi? | Ko'rinadi (2.4.11) |
Enter / Space | Tugma va havolalar ishlaydimi? | Ha |
| Modal oyna | Fokus modal ichida qoladimi, Esc yopadimi, yopilgach fokus qaytadimi? | Ha |
| Chiqish | Biror joyda fokus "qamalib" qolmaydimi? | Yo'q (2.1.2) |
| "Kontentga o'tish" havolasi | Sahifa boshida bormi? | Uzun menyuli sahifalarda tavsiya etiladi |
Kontrast
- Normal matn: kamida 4.5:1; katta matn (≥ 18pt yoki ≥ 14pt bold): 3:1; UI komponent chegaralari va ikonkalar: 3:1.
- Tekshirish: WebAIM Contrast Checker yoki Chrome DevTools'dagi rang tanlagich (u kontrast nisbatini ko'rsatadi).
- Faqat rang bilan ma'no berilmasin (1.4.1): "Qizil maydonlar — xato" emas, xato matni ham bo'lsin.
Zoom va reflow
- Brauzerni 200% ga kattalashtiring: matn kesilmaydi, tugmalar ustma-ust tushmaydi.
- Oynani 320 CSS px kenglikka toraytiring (taxminan 400% zoom): faqat vertikal scroll bo'lishi kerak (1.4.10).
Formalar
- Har maydonning ko'rinadigan label'i bor. W3C WAI forms qo'llanmasi: placeholder — foydali ko'rsatma, lekin label o'rnini bosmaydi; yozishni boshlaganingizda u yo'qoladi.
- Xato maydon bilan bog'langan va matnli: "Telefon raqam +998 dan keyin 9 ta raqamdan iborat bo'lishi kerak".
- Majburiy maydonlar faqat rang yoki
*bilan emas, matn yoki atribut bilan ham belgilangan.
Screen reader bilan tekshiruv
| Platforma | Screen reader | Yoqish |
|---|---|---|
| macOS | VoiceOver | Cmd + F5 |
| iOS / iPadOS | VoiceOver | Settings → Accessibility → VoiceOver |
| Windows | NVDA (bepul) | O'rnatib, ishga tushirish |
| Android | TalkBack | Settings → Accessibility → TalkBack |
Nimalarni eshitishingiz kerak: sahifa sarlavhasi; sarlavhalar bo'yicha navigatsiya; har maydonning nomi ("Telefon raqam, matn maydoni"); tugma nomlari ("Savatchaga qo'shish, tugma" — "tugma, tugma" emas); rasmlarning mazmuni; xato va "Savatchaga qo'shildi" kabi status xabarlari (4.1.3).
4. Avtomatik a11y: axe-core + Playwright {#axe}
axe-core (Deque) — ochiq kodli a11y qoidalar dvigateli. Chrome Lighthouse'ning accessibility bahosi ham axe'ning foydalanuvchiga ta'sir baholariga asoslangan og'irliklardan foydalanadi. Playwright bilan integratsiya — @axe-core/playwright.
npm i -D @playwright/test @axe-core/playwright
npx playwright install chromium
// playwright.config.ts
import { defineConfig, devices } from "@playwright/test";
export default defineConfig({
testDir: "./tests",
reporter: "list",
use: {
baseURL: "https://www.saucedemo.com",
testIdAttribute: "data-test",
},
projects: [{ name: "chromium", use: { ...devices["Desktop Chrome"] } }],
});
// tests/a11y.spec.ts
import { test, expect } from "@playwright/test";
import AxeBuilder from "@axe-core/playwright";
const WCAG_TAGS = ["wcag2a", "wcag2aa", "wcag21a", "wcag21aa", "wcag22aa"];
test("login sahifasida WCAG A/AA buzilishlari yo'q", async ({
page,
}, testInfo) => {
await page.goto("/");
const results = await new AxeBuilder({ page }).withTags(WCAG_TAGS).analyze();
// to'liq natija HTML hisobotga ilova bo'ladi
await testInfo.attach("axe-violations", {
body: JSON.stringify(results.violations, null, 2),
contentType: "application/json",
});
expect(results.violations).toEqual([]);
});
test("DemoBozor mini sahifa: axe xatolarni topadi", async ({ page }) => {
await page.setContent(`
<html lang="uz"><body>
<h1>DemoBozor</h1>
<img src="choynak.png">
<span>Telefon raqam</span> <input type="tel" id="phone">
<input type="text" placeholder="Promo-kod">
<button><svg width="16" height="16"></svg></button>
<p style="color:#aaaaaa;background:#ffffff">Yetkazib berish bepul</p>
</body></html>`);
const results = await new AxeBuilder({ page }).withTags(WCAG_TAGS).analyze();
const ids = results.violations.map((v) => v.id).sort();
expect(ids).toEqual([
"button-name",
"color-contrast",
"document-title",
"image-alt",
"label",
]);
});
test("faqat login formasi, bitta qoida o'chirilgan holda", async ({ page }) => {
await page.goto("/");
const results = await new AxeBuilder({ page })
.include("#login_button_container")
.disableRules(["color-contrast"])
.analyze();
expect(results.violations).toEqual([]);
});
Uchala test ham o'tadi (2026-yil oktabr). Ikkinchi testdan muhim saboqlar:
| Element | axe qoidasi | Muammo |
|---|---|---|
<img src="choynak.png"> | image-alt | alt yo'q |
<input type="tel"> (yonida oddiy <span>) | label | Matn ko'rinadi, lekin maydonga bog'lanmagan |
<button><svg></button> | button-name | Tugma nomsiz — screen reader faqat "tugma" deydi |
#aaaaaa matn oq fonda | color-contrast | 2.32:1 < 4.5:1 |
<title> yo'q | document-title | Sahifa sarlavhasi yo'q |
⚠️ Diqqat: Faqat placeholder'i bor "Promo-kod" maydoni uchun axe xato bermadi: placeholder accessible name hisoblashda zaxira manba bo'lishi mumkin. Saucedemo login'i ham axe'dan 0 xato bilan o'tadi — uning maydonlarida
aria-labelva placeholder bor, lekin ko'rinadigan label yo'q. Avtomatik skaner "o'tdi" degani — hali "foydalanuvchi uchun qulay" degani emas; buni qo'lda tekshirish (3-bo'lim) topadi.
Haqiqiy topilmalar: TodoMVC
test("TodoMVC: jiddiy buzilishlar", async ({ page }) => {
await page.goto("https://demo.playwright.dev/todomvc/");
await page
.getByPlaceholder("What needs to be done?")
.fill("Choynak sotib olish");
await page.getByPlaceholder("What needs to be done?").press("Enter");
const { violations } = await new AxeBuilder({ page })
.withTags(WCAG_TAGS)
.analyze();
const serious = violations.filter(
(v) => v.impact === "serious" || v.impact === "critical",
);
for (const v of serious) {
for (const node of v.nodes) {
console.log(
`${v.impact} | ${v.id} | ${node.target.join(" ")} | ${node.any[0]?.message}`,
);
}
}
expect(serious, "jiddiy a11y buzilishlari bo'lmasligi kerak").toEqual([]);
});
2026-yil oktabrdagi ishga tushirishda bu test yiqildi va konsolga quyidagilar chiqdi (qisqartirilgan; sayt o'zgarsa, natija ham o'zgaradi):
serious | color-contrast | h1 | ... contrast of 1.26 (foreground color: #ebd7d7, background color: #f5f5f5, font size: 75.0pt (100px) ...). Expected contrast ratio of 3:1
serious | color-contrast | .selected | ... contrast of 4.47 (foreground color: #777777, background color: #ffffff, font size: 10.5pt (14px) ...). Expected contrast ratio of 4.5:1
serious | color-contrast | p:nth-child(1) | ... contrast of 1.68 (foreground color: #bfbfbf, background color: #f5f5f5, font size: 7.5pt (10px) ...). Expected contrast ratio of 4.5:1
E'tibor bering: .selected filtrining kontrasti 4.47 — chegaraga juda yaqin, lekin baribir fail. Katta (100px) sarlavha uchun talab 3:1, kichik matn uchun 4.5:1 — axe shriftga qarab to'g'ri chegarani o'zi tanlaydi.
axe natijasini o'qish
violations— buzilishlar:id(qoida),impact(minor/moderate/serious/critical),help,helpUrl,nodes(har biritargetselector vafailureSummarybilan).passes— o'tgan tekshiruvlar;incomplete— axe aniq hal qila olmagan, qo'lda ko'rish kerak bo'lganlar;inapplicable— sahifaga taalluqli bo'lmagan qoidalar.
Avtomatlashtirish chegarasi
Ko'p mezonlar inson baholashini talab qiladi: alt matni mazmunlimi, fokus tartibi mantiqiymi, xato xabari tushunarlimi. Deque'ning 2021-yildagi tadqiqoti (vendor tadqiqoti, mustaqil emas) avtomatik testlar topilgan muammolar hajmining taxminan 57% ini aniqlaganini ko'rsatgan — qolgan qismi baribir qo'lda topiladi. Lighthouse'da 100 ball ham "to'liq accessible" degani emas.
💡 Maslahat: CI'da axe'ni muhim sahifalarda ishlating va
serious/criticalbuzilishlarda pipeline'ni yiqiting. Eski (ma'lum) muammolar ko'p bo'lsa — ularni alohida ticket'larga ajratib, yangi buzilish qo'shilishiga yo'l qo'ymaslik siyosatini qo'llang.
5. Mobil accessibility {#mobil-a11y}
| Tekshiruv | iOS | Android |
|---|---|---|
| Screen reader | VoiceOver: har element nomi, roli, holati o'qiladimi | TalkBack: xuddi shunday |
| Shrift kattaligi | Dynamic Type'ning eng katta (accessibility) o'lchamlari | Font size / Display size maksimal |
| Bosish nishoni | Apple HIG: tugma bosish maydoni kamida 44×44 pt (visionOS'da 60×60 pt) | Google: kamida 48×48 dp, oralig'i ≥ 8 dp |
| Harakat | Reduce Motion yoqilganda animatsiyalar kamayadi | Animatsiya sozlamalari |
| Kontrast | Increase Contrast, Bold Text | High contrast text |
| Avtomatik audit | Xcode Accessibility Inspector | Accessibility Scanner ilovasi |
DemoBozor uchun tipik mobil a11y bug'lari:
- savatcha ikonkasidagi badge VoiceOver'da "3" deb o'qiladi — "Savatcha, 3 ta mahsulot" bo'lishi kerak;
- Dynamic Type maksimal o'lchamda "Buyurtma berish" tugmasi ekrandan chiqib ketadi;
- mahsulot rasmi karuseli faqat swipe bilan ishlaydi — VoiceOver foydalanuvchisi uchun muqobil yo'q;
- OTP katakchalari har biri alohida o'qiladi va SMS kod autofill ishlamaydi.
🧠 Esda tuting:
accessibilityIdentifier(iOS) /testTag(Compose) — avtomatik testlar uchun, foydalanuvchiga o'qilmaydi. VoiceOver o'qiydigan matn —accessibilityLabel/contentDescription. Ikkalasi ham kerak, lekin vazifasi har xil (QA 22). Mobil testlash checklisti: QA 14.
6. i18n va l10n: asosiy tushunchalar {#i18n}
- Internationalization (i18n) — mahsulotni turli tillarga moslashtirish mumkin qilib qurish: matnlar koddan tashqarida (resurs fayllar), Unicode, locale'ga qarab formatlash, egiluvchan layout.
- Localization (l10n) — aniq bir locale uchun moslashtirish: tarjima, sana/son/valyuta formatlari, madaniy jihatlar, huquqiy matnlar.
DemoBozor 4 locale bilan ishlaydi: uz-Latn, uz-Cyrl, ru, en.
Tipik l10n bug'lari
| Bug | Misol | Sabab |
|---|---|---|
| Tarjima qilinmagan matn | Rus tilida "Out of stock" | Hardcoded string yoki backend xatosi |
| Gap bo'laklardan yig'ilgan | "Savatchada " + n + " ta mahsulot" | Tillarda so'z tartibi va qo'shimchalar boshqacha |
| Noto'g'ri plural | "5 товара" (to'g'risi "5 товаров") | Plural qoidalari hisobga olinmagan |
| Kesilgan matn | "Buyurtma be..." | Tarjima uzunroq, tugma kengligi qat'iy |
| Rasm ichidagi matn | Banner faqat o'zbekcha | Matn rasmga "yopishtirilgan" |
| Noaniq sana | 09/10/2026 — 9-oktabrmi yoki 10-sentabrmi? | Format talabda belgilanmagan |
| Shriftda belgi yo'q | ʻ o'rnida bo'sh kvadrat | Shriftda U+02BB glif yo'q |
| Backend xabari tarjimasiz | API inglizcha xato qaytaradi | Xato kodlari o'rniga matn |
Matn kengayishi
W3C'ning "Text size in translation" maqolasida keltirilgan IBM yo'riqnomasiga ko'ra, ingliz tilidan Yevropa tillariga tarjimada qisqa matnlar eng ko'p uzayadi: 10 belgigacha bo'lgan matnlar 200–300% gacha, 70 belgidan uzunlari esa taxminan 130% gacha. Tugma, tab va menyu nomlari — eng xavfli joylar.
Pseudo-localization
Haqiqiy tarjimani kutmasdan, matnlarni sun'iy ravishda "chet tilga o'xshatish" usuli: harflarni diakritikali variantlarga almashtirish va uzaytirish, masalan Savatcha → [Šàvàtçhà ~~~~]. Natijada hardcoded matnlar (o'zgarmay qolganlari) va kesilish joylari darhol ko'rinadi.
RTL tillar
Arab yoki fors tilini qo'shish rejasi bo'lsa: dir="rtl", layout ko'zgu kabi aylanadi, CSS'da margin-left o'rniga mantiqiy margin-inline-start. Node 24'da tekshirish: new Intl.Locale('ar').getTextInfo() → { direction: 'rtl' }.
7. O'zbek tili nozikliklari: oʻ/gʻ, lotin/kirill, alifbo islohoti {#ozbek-tili}
Apostroflarning besh xil ko'rinishi
O'zbek lotin alifbosidagi Oʻ va Gʻ harflari uchun to'g'ri belgi — **ʻ (U+02BB, MODIFIER LETTER TURNED COMMA)**; tutuq belgisi uchun — ʼ (U+02BC). Amalda esa klaviaturada qulay bo'lgani uchun boshqa belgilar ishlatiladi:
| Yozilishi | Belgi | Unicode |
|---|---|---|
o'zbek | ASCII apostrof | U+0027 |
oʻzbek | Modifier letter turned comma | U+02BB |
o‘zbek | Left single quotation mark | U+2018 |
o’zbek | Right single quotation mark | U+2019 |
ozbek` | Backtick | U+0060 |
Inson uchun beshalasi "bir xil so'z", kompyuter uchun esa — besh xil satr. Natijada qidiruv, takrorlarni topish, saralash va login (masalan, foydalanuvchi nomi) buziladi.
Qidiruvni tekshirish va tuzatish
// Qidiruv kaliti: barcha apostrof variantlarini bitta belgiga (U+02BB) keltiramiz
const APOSTROPHES = /['`‘’ʼ]/g;
export function searchKey(text) {
return text
.normalize("NFC")
.replace(APOSTROPHES, "ʻ")
.toLocaleLowerCase("uz");
}
const products = [
"Oʻzbek atlasi",
"O'zbek do'ppisi",
"O‘zbekcha choynak",
"Gʻijduvon kosasi",
];
const query = "o'zbek";
const naive = products.filter((p) => p.toLowerCase().includes(query));
const smart = products.filter((p) => searchKey(p).includes(searchKey(query)));
console.log("oddiy qidiruv:", naive);
console.log("normallashtirilgan:", smart);
Node 24 natijasi:
oddiy qidiruv: [ "O'zbek do'ppisi" ]
normallashtirilgan: [ 'Oʻzbek atlasi', "O'zbek do'ppisi", 'O‘zbekcha choynak' ]
Oddiy qidiruv 3 ta mos mahsulotdan faqat bittasini topdi. searchKey — faqat qidiruv indeksi uchun kalit: ekranda matn foydalanuvchi yozgandek qoladi.
QA test g'oyalari: har bir apostrof varianti bilan qidirish; nomida ʻ bo'lgan mahsulotni ' bilan qidirish va aksincha; ro'yxatdan o'tishda bir xil ism turli apostrof bilan "boshqa odam" bo'lib qolmaydimi; shriftlarda ʻ glifi bormi.
Saralash (collation)
O'zbek alifbosida Oʻ, Gʻ, Sh, Ch harflari Z dan keyin keladi. Oddiy sort() esa kod nuqtalari bo'yicha saralaydi:
const words = [
"shakar",
"sabzi",
"olma",
"oʻrik",
"gʻisht",
"gilos",
"chinni",
"tuz",
];
console.log("sort(): ", [...words].sort().join(", "));
console.log(
"Collator('uz'): ",
[...words].sort(new Intl.Collator("uz").compare).join(", "),
);
sort(): chinni, gilos, gʻisht, olma, oʻrik, sabzi, shakar, tuz
Collator('uz'): gilos, olma, sabzi, tuz, oʻrik, gʻisht, shakar, chinni
Shahar, toifa yoki brend ro'yxatlari alifbo tartibida chiqsa — locale'ga mos saralash talabda belgilanganmi, tekshiring.
Lotin va kirill
Ikkala yozuv ham faol ishlatiladi. Tekshiruvlar: ilova tanlangan yozuvda izchil ko'rsatiladimi (bir ekranda aralash emas); foydalanuvchi ism yoki manzilni kirillda kiritsa, saqlanadi va to'g'ri ko'rinadimi; qidiruv qaysi yozuvlarda ishlashi talabda yozilganmi.
🇺🇿 Mahalliy kontekst: Alifbo islohoti. O'zbek lotin alifbosini takomillashtirish haqidagi qonun loyihasini Senat 2026-yil 10-sentabrda ma'qulladi va Prezidentga yubordi. Xabarlarga ko'ra yangi alifboda 28 harf va bitta apostrof bo'ladi:
Oʻ → Ö,Gʻ → Ğ,Sh → Ş,Ch → Ç. Rasmiy xabarda raqamli texnologiyalar bo'yicha yagona texnik standart ishlab chiqilayotgani va qidiruv mexanizmlari yangi harflarga moslashtirilayotgani aytilgan. Qonun kuchga kirsa, o'tish davrida ilovalar ikkala imloni ham to'g'ri qidirishi va saqlashi kerak bo'ladi (oʻrikvaörik). Holatni rasmiy manbalardan kuzatib boring.
8. Sana, son, valyuta va plural: Intl bilan tekshirish {#intl}
JavaScript'ning Intl API'si CLDR ma'lumotlari asosida formatlaydi. Quyidagi natijalar Node.js 24 (ICU 78.2, CLDR 48) da olingan; brauzer va OS versiyasiga qarab biroz farq qilishi mumkin.
| Kod | Natija |
|---|---|
new Intl.NumberFormat('uz-UZ').format(1250000) | 1 250 000 |
... ('uz-UZ', { style: 'currency', currency: 'UZS' }) | 1 250 000,00 soʻm |
... + maximumFractionDigits: 0 | 1 250 000 soʻm |
... ('uz-Cyrl-UZ', ...) | 1 250 000 сўм |
... ('ru-RU', ...) | 1 250 000 UZS |
... ('en-US', ...) | UZS 1,250,000 |
new Intl.DateTimeFormat('uz-UZ', { timeZone: 'Asia/Tashkent' }) | 09/10/2026 |
... ('uz-UZ', { dateStyle: 'long', timeStyle: 'short', ... }) | 9-oktabr, 2026, 14:30 |
... ('ru-RU', ...) | 9 октября 2026 г. в 14:30 |
... ('en-US', ...) | October 9, 2026 at 2:30 PM |
(Sana: 2026-10-09T09:30:00Z — Toshkentda 14:30.)
Bu jadvaldan uchta muhim QA xulosasi:
- Format — mahsulot qarori.
uz-UZning standart qisqa formati09/10/2026, O'zbekistonda esa hujjatlarda ko'pincha09.10.2026yoziladi. Talabda qaysi format ekanini aniq yozdiring va hamma ekranda izchilligini tekshiring. - **CLDR
soʻmda U+02BB ishlatadi**, ko'p dizayn maketlarida esaso'm(U+0027) yozilgan. Matnni aynan taqqoslaydigan testlar shu yerda yiqiladi. - Bo'shliqlar oddiy probel emas. Raqam guruhlari va valyuta oldidagi bo'shliq — NBSP (U+00A0):
const price = new Intl.NumberFormat("uz-UZ", {
style: "currency",
currency: "UZS",
maximumFractionDigits: 0,
}).format(1250000);
console.log(price); // 1 250 000 soʻm
console.log(price === "1 250 000 soʻm"); // false — bo'shliqlar NBSP (U+00A0)
console.log(price.replace(/[ ]/g, " ") === "1 250 000 soʻm"); // true
Playwright'ning web-first assertion'i toHaveText satr bilan solishtirganda bo'shliqlarni normallashtiradi, shuning uchun await expect(locator).toHaveText('1 250 000 soʻm') o'tadi; lekin textContent() ni toBe bilan solishtirsangiz — yiqiladi. Bu "flaky emas, lekin tushunarsiz" testlarning klassik sababi.
Plural qoidalari
CLDR bo'yicha o'zbek tilida plural kategoriyalari ikkita: one, other. Rus tilida to'rtta: one, few, many, other.
const messages = {
uz: { one: "{n} ta mahsulot", other: "{n} ta mahsulot" },
ru: {
one: "{n} товар",
few: "{n} товара",
many: "{n} товаров",
other: "{n} товара",
},
};
function cartLabel(locale, n) {
const category = new Intl.PluralRules(locale).select(n); // 'one' | 'few' | 'many' | 'other'
return messages[locale][category].replace("{n}", String(n));
}
for (const n of [1, 2, 5, 11, 21, 22, 25]) {
console.log(`${n}: ${cartLabel("ru", n)} | ${cartLabel("uz", n)}`);
}
1: 1 товар | 1 ta mahsulot
2: 2 товара | 2 ta mahsulot
5: 5 товаров | 5 ta mahsulot
11: 11 товаров | 11 ta mahsulot
21: 21 товар | 21 ta mahsulot
22: 22 товара | 22 ta mahsulot
25: 25 товаров | 25 ta mahsulot
Rus tili uchun test qiymatlari: 0, 1, 2, 5, 11, 12, 21, 22, 25, 101, 111 — ayniqsa 11–14 (har doim many) va 21, 22 (yana one, few) chegaralari. Bu — QA 5 dagi equivalence partitioning'ning tilga xos qo'llanilishi.
Vaqt zonasi
Asia/Tashkent — UTC+5, yozgi vaqtga o'tish yo'q: Node 24'da yanvar va iyul uchun ham GMT+5 chiqadi. Tekshiruvlar: server UTC'da saqlab, ekranda Toshkent vaqtida ko'rsatadimi; promo-kod "bugun 23:59 gacha" Toshkent vaqti bo'yicha tugaydimi; chet eldagi foydalanuvchi uchun buyurtma vaqti qanday ko'rinadi.
9. Visual testing: toHaveScreenshot va vositalar {#visual}
Visual regression testing — sahifa yoki komponentning skrinshotini oldindan tasdiqlangan baseline bilan solishtirish. Funksional assertion'lar "tugma bor va bosiladi" deydi, visual test esa "tugma o'z joyida, to'g'ri rangda, matn kesilmagan" ekanini ushlaydi.
| Yondashuv | Qanday ishlaydi | Misollar |
|---|---|---|
| Pixel diff | Piksellarni solishtiradi | Playwright toHaveScreenshot |
| Bulutli vizual xizmatlar | Baseline'larni saqlaydi, review UI beradi | Percy (BrowserStack), Chromatic (Storybook komponentlari uchun) |
| AI asosidagi taqqoslash | Inson ko'ziga sezilmaydigan farqlarni filtrlashga urinadi | Applitools Eyes |
Playwright bilan
// tests/visual.spec.ts
import { test, expect } from "@playwright/test";
const PRICE_COLOR = process.env.PRICE_COLOR ?? "#0F766E";
const productCard = (updatedAt: string) => `
<html lang="uz"><head><title>DemoBozor</title><style>
body { font-family: Arial, sans-serif; margin: 24px; }
.card { width: 280px; padding: 16px; border: 1px solid #ddd; border-radius: 12px; }
.price { color: ${PRICE_COLOR}; font-size: 22px; font-weight: bold; }
.spinner { width: 16px; height: 16px; border: 3px solid #ccc; border-top-color: #333;
border-radius: 50%; animation: spin 1s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }
</style></head><body>
<div class="card" data-test="product-card">
<h2>Elektr choynak</h2>
<p class="price">349 000 so'm</p>
<p data-test="updated-at">Yangilandi: ${updatedAt}</p>
<div class="spinner"></div>
<button>Savatchaga qo'shish</button>
</div>
</body></html>`;
test("mahsulot kartasi vizual ko'rinishi", async ({ page }) => {
await page.setViewportSize({ width: 400, height: 360 });
await page.setContent(productCard(new Date().toISOString()));
await expect(page.getByTestId("product-card")).toHaveScreenshot(
"product-card.png",
{
mask: [page.getByTestId("updated-at")], // har safar o'zgaradigan vaqt
animations: "disabled", // spinner to'xtatiladi
maxDiffPixels: 50, // kichik farqlarga ruxsat
},
);
});
Haqiqiy ish oqimi (Playwright 1.64, macOS):
# 1) Birinchi ishga tushirish — baseline yo'q, test yiqiladi:
npx playwright test tests/visual.spec.ts
# Error: A snapshot doesn't exist at .../visual.spec.ts-snapshots/product-card-chromium-darwin.png, writing actual.
# 2) Baseline yaratish (natijani ko'z bilan tekshirib, commit qiling):
npx playwright test tests/visual.spec.ts --update-snapshots
# 3) Keyingi ishga tushirishlar baseline bilan solishtiradi — o'tadi.
# 4) Narx rangi o'zgarsa (PRICE_COLOR='#DC2626'):
# Error: expect(locator).toHaveScreenshot(expected) failed
# 669 pixels (ratio 0.01 of all image pixels) are different.
# test-results/ papkasida: product-card-expected.png, -actual.png, -diff.png
Muhim jihatlar:
- Baseline nomida brauzer va platforma bor (
-chromium-darwin.png). Playwright hujjati: render OS, versiya, sozlamalar, apparat va headless rejimga qarab farq qiladi — baseline'lar qayerda yaratilgan bo'lsa, testlar ham o'sha muhitda ishlashi kerak. Amalda baseline'larni CI bilan bir xil muhitda (masalan, Linux konteynerida) yarating (QA 21). mask— vaqt, tasodifiy reklama, avatar kabi o'zgaruvchan joylarni yopadi;animations: 'disabled'— CSS animatsiyalarini to'xtatadi;maxDiffPixels/threshold— sezgirlik;stylePath— skrinshot paytida maxsus CSS (masalan, iframe'larni yashirish).- Komponent darajasidagi kichik skrinshotlar butun sahifadan barqarorroq.
- Responsive tekshiruv: bir xil test 375 / 768 / 1280 px kengliklarda.
- Diff'ni PR'da ko'rib tasdiqlash jarayoni bo'lsin:
--update-snapshotsni o'ylamasdan ishga tushirish — bug'ni baseline'ga "muhrlab qo'yish" demakdir.
Batafsil Playwright amaliyoti: QA 19.
10. Usability asoslari: Nielsen'ning 10 evristikasi {#usability}
Jakob Nielsen'ning 10 ta usability evristikasi (1994) — interfeysni tez baholash uchun tekshiruv ro'yxati:
| # | Evristika | DemoBozor'dagi buzilish misoli |
|---|---|---|
| 1 | Visibility of System Status | "To'lash" bosilgach hech narsa o'zgarmaydi — yuklanish ko'rsatkichi yo'q |
| 2 | Match Between the System and the Real World | "SKU qoldig'i: 0" — xaridor uchun "Sotuvda yo'q" bo'lishi kerak |
| 3 | User Control and Freedom | Savatchadan o'chirilgan mahsulotni qaytarib bo'lmaydi |
| 4 | Consistency and Standards | Bir ekranda "Savatcha", boshqasida "Korzina" |
| 5 | Error Prevention | Muddatli to'lov formasida yosh chegarasi oldindan ko'rsatilmaydi |
| 6 | Recognition Rather than Recall | Checkout'da avvalgi manzillar taklif qilinmaydi |
| 7 | Flexibility and Efficiency of Use | Doimiy mijoz uchun "qayta buyurtma" tugmasi yo'q |
| 8 | Aesthetic and Minimalist Design | Mahsulot sahifasida 5 ta bir-biriga o'xshash banner |
| 9 | Help Users Recognize, Diagnose, and Recover from Errors | "Xato 4012" — nima qilish kerakligi yozilmagan |
| 10 | Help and Documentation | Qaytarish qoidalari faqat ofertaning 20-sahifasida |
"5 ta foydalanuvchi" qoidasi
Nielsen'ning 2000-yildagi maqolasiga ko'ra, bir xil turdagi 5 ta foydalanuvchi bilan test taxminan 85% usability muammolarini topadi (bitta foydalanuvchi o'rtacha ~31% ni topadi degan modelga asoslangan). Muallifning o'zi qo'shgan shartlar: bitta katta test o'rniga bir nechta kichik testlar (har redizayndan keyin), foydalanuvchilar guruhlari juda farq qilsa — har guruhdan alohida, miqdoriy (metrikali) tadqiqotlar uchun esa ko'proq ishtirokchi kerak. Bu — qat'iy qonun emas, amaliy "rule of thumb".
11. Amaliy mashqlar {#mashqlar}
Mashq 1: Kontrastni tuzating
axe TodoMVC'da .selected filtri uchun quyidagini chiqardi: contrast of 4.47 (foreground color: #777777, background color: #ffffff, font size: 10.5pt (14px)...). Expected contrast ratio of 4.5:1. (a) Bu qaysi SC? (b) Nega 4.47 yetmaydi? (c) Eng kam o'zgarish bilan qaysi rangni taklif qilasiz?
<details> <summary>💡 Javobni ko'rish</summary>
- (a) 1.4.3 Contrast (Minimum), AA.
- (b) 14px oddiy matn "katta matn" emas (≥ 18pt yoki ≥ 14pt bold emas), shuning uchun talab 4.5:1. 4.47 < 4.5 — chegaraga yaqin bo'lsa ham fail.
- (c) Bir pog'ona to'qroq kulrang:
#767676oq fonda ≈ 4.54:1 — talabdan o'tadi (hisob WCAG formulasi bo'yicha). Kattaroq zaxira kerak bo'lsa#6B6B6B(≈ 5.33:1). Dizayner bilan kelishib, design token'ni o'zgartirish kerak — bitta ekranni emas.
</details>
Mashq 2: Modal oyna klaviatura testi
DemoBozor'da "Manzil qo'shish" modal oynasi bor (maydonlar: shahar, ko'cha, uy, izoh; tugmalar: "Saqlash", "Bekor qilish", yopish ✕). Klaviatura bo'yicha test case'larni yozing.
<details> <summary>💡 Javobni ko'rish</summary>
| # | Qadam | Kutilgan natija |
|---|---|---|
| 1 | Modalni klaviatura bilan ochish (Enter) | Modal ochiladi, fokus birinchi maydonga (yoki sarlavhaga) o'tadi |
| 2 | Tab bilan aylanish | Fokus faqat modal ichida aylanadi, orqadagi sahifaga chiqmaydi |
| 3 | Har elementda | Fokus aniq ko'rinadi (2.4.7) |
| 4 | Yopish ✕ tugmasi | Screen reader uni "Yopish, tugma" deb o'qiydi (nomli) |
| 5 | Esc | Modal yopiladi |
| 6 | Yopilgandan keyin | Fokus modalni ochgan tugmaga qaytadi |
| 7 | Bo'sh maydon bilan "Saqlash" | Xato matni maydon yonida, screen reader o'qiydi |
| 8 | 200% zoom | Modal kontenti kesilmaydi, scroll qilinadi |
</details>
Mashq 3: Rus plural test qiymatlari
Savatcha sarlavhasi: "В корзине N товар/товара/товаров". Equivalence partitioning bilan minimal, lekin to'liq qamrovli test qiymatlarini tanlang va kutilgan shaklni yozing.
<details> <summary>💡 Javobni ko'rish</summary>
| N | Kategoriya (Intl.PluralRules('ru')) | Kutilgan |
|---|---|---|
| 1 | one | 1 товар |
| 2 | few | 2 товара |
| 5 | many | 5 товаров |
| 11 | many | 11 товаров (11–14 — istisno!) |
| 12 | many | 12 товаров |
| 21 | one | 21 товар |
| 22 | few | 22 товара |
| 25 | many | 25 товаров |
| 101 | one | 101 товар |
| 111 | many | 111 товаров |
0 qiymati uchun alohida xabar ("Корзина пуста") talabda bormi — tekshiring. Kodda shakllarni qo'lda if bilan emas, Intl.PluralRules (yoki i18n kutubxonasi) bilan tanlash kerak.
</details>
Mashq 4: Qidiruv uchun test to'plami
DemoBozor katalogida "Gʻijduvon kosasi" (U+02BB bilan) bor. Apostrof muammosini ushlaydigan qidiruv test'larini yozing va searchKey funksiyasi bilan kutilgan natijani ayting.
<details> <summary>💡 Javobni ko'rish</summary>
| Qidiruv so'rovi | Ishlatilgan belgi | Kutilgan |
|---|---|---|
gʻijduvon | U+02BB | Topiladi |
g'ijduvon | U+0027 | Topiladi |
g‘ijduvon | U+2018 | Topiladi |
g’ijduvon | U+2019 | Topiladi |
gijduvon` | U+0060 | Topiladi |
GʻIJDUVON | Katta harflar | Topiladi |
гиждувон | Kirill | Talabga qarab (yozuvlararo qidiruv bormi?) |
searchKey barcha apostrof variantlarini U+02BB ga keltirib, kichik harfga o'tkazgani uchun dastlabki 6 holatda ham kalitlar teng bo'ladi. Kirill → lotin moslashtirish alohida talab va alohida algoritm (transliteratsiya) talab qiladi.
</details>
Mashq 5: L10n bug'larini toping
Rus tilidagi buyurtma ekrani tavsifi: sarlavha "Ваш заказ", tugma "Buyurtma berish", matn "В корзине 5 товара", narx "1250000 so'm", sana "10/09/2026", yetkazib berish izohi kesilgan: "Бесплатная доставка от 300 000 сў...", xato xabari "Promo code expired". Bug'larni sanang.
<details> <summary>💡 Javobni ko'rish</summary>
- "Buyurtma berish" — tugma tarjima qilinmagan (hardcoded yoki kalit yo'q).
- "5 товара" — noto'g'ri plural, to'g'risi "5 товаров".
- "1250000 so'm" — guruhlash yo'q va valyuta locale'ga mos emas (rus interfeysida
IntlUZSberadi yoki mahsulot talabidagi rus yozuvi kerak). - "10/09/2026" — noaniq format; rus locale'da odatda
10.09.2026, umuman olganda talab bo'yicha bitta izchil format. - "сў..." — rus matni ichida o'zbek kirill valyuta nomi va matn kesilgan (kenglik/uzunlik muammosi).
- "Promo code expired" — backend xabari tarjima qilinmagan; API xato kodini qaytarishi, matnni esa mijoz locale bo'yicha ko'rsatishi kerak.
</details>
Mashq 6: Beqaror visual test
toHaveScreenshot testi lokal kompyuterda o'tadi, CI'da esa doim yiqiladi; ba'zan lokalda ham har 5 ishga tushirishda bir marta yiqiladi. Kamida 4 ta ehtimoliy sababni va yechimini yozing.
<details> <summary>💡 Javobni ko'rish</summary>
| Sabab | Yechim |
|---|---|
Baseline macOS'da yaratilgan, CI — Linux (-darwin vs -linux) | Baseline'larni CI bilan bir xil muhitda (konteynerda) yaratish |
| Sahifada vaqt, tasodifiy banner, avatar | mask yoki test data'ni qotirish |
| Animatsiya/karusel | animations: 'disabled', karuselni to'xtatish |
| Shrift kech yuklanadi | Shriftlarni lokal ulash, yuklanishini kutish |
| Ma'lumot o'zgaradi (narx, reyting) | Mock/route bilan barqaror ma'lumot (QA 19) |
| Juda katta (butun sahifa) skrinshot | Komponent darajasidagi kichik skrinshotlar |
</details>
Mashq 7: Evristik tahlil
Quyidagi DemoBozor kuzatuvlarini Nielsen evristikalariga bog'lang: (a) to'lov 8 soniya davom etadi, ekran o'zgarmaydi; (b) xato: "ERR_PAYMENT_DECLINED_51"; (c) savatchadan mahsulot tasdiqsiz va qaytarib bo'lmaydigan tarzda o'chadi; (d) iOS'da "Orqaga" yuqori chapda, Android versiyasida esa pastki o'ngda.
<details> <summary>💡 Javobni ko'rish</summary>
- (a) #1 Visibility of System Status — yuklanish holati ko'rsatilishi kerak.
- (b) #9 Help Users Recognize, Diagnose, and Recover from Errors (va #2) — oddiy tilda: "Karta to'lovni rad etdi. Boshqa karta bilan urinib ko'ring yoki bank bilan bog'laning."
- (c) #3 User Control and Freedom (va #5 Error Prevention) — "Bekor qilish" imkoniyati yoki tasdiq.
- (d) #4 Consistency and Standards — lekin ehtiyot bo'ling: har platformaning o'z standarti bor; platforma konventsiyasiga mos kelishi muhimroq.
</details>
12. O'zingizni tekshiring {#checklist}
- [ ] POUR printsiplarini va AA darajasini misollar bilan tushuntira olaman
- [ ] WCAG 2.2 da qo'shilgan mezonlardan kamida 5 tasini aytib bera olaman
- [ ] Sahifani faqat klaviatura bilan tekshirib, fokus muammolarini topa olaman
- [ ]
@axe-core/playwrighttestini yozib,violationsni o'qiy olaman - [ ] Avtomatik a11y skanerining chegarasini tushuntira olaman
- [ ] O'zbek apostroflari, saralash va plural bo'yicha test g'oyalarini bera olaman
- [ ]
Intlnatijasidagi NBSP muammosini bilaman - [ ]
toHaveScreenshotbilan baseline yaratib, diff'ni tahlil qila olaman
Xulosa {#xulosa}
- Accessibility — WCAG 2.2 AA: POUR printsiplari; QA har feature'da klaviatura, fokus, kontrast, label va screen reader'ni tekshiradi.
- WCAG 2.2 9 ta yangi mezon qo'shdi (fokus yashirinmasligi, 24×24 px nishon, sudrash muqobili, accessible authentication va boshqalar) va 4.1.1 Parsing'ni olib tashladi.
- axe-core tez topiladigan xatolarni ushlaydi, lekin "0 violations" — "accessible" degani emas: placeholder-label, mazmunsiz
altkabi muammolarni inson topadi. - L10n bug'larining ko'pi oldindan bashorat qilinadi: hardcoded matn, plural, kesilish, sana/valyuta formati, backend xabarlari.
- O'zbek tilida: apostrofning 5 xil ko'rinishi qidiruvni buzadi,
Oʻ/GʻalifbodaZdan keyin keladi, lotin va kirill parallel; alifbo islohoti holatini kuzatib boring. Intlnatijasida NBSP va U+02BB bor — testlarda buni hisobga oling.- Visual testlar: barqaror ma'lumot,
mask,animations: 'disabled', CI bilan bir xil muhitdagi baseline va PR'da diff review. - Keyingi dars: QA 26: AI va QA (2026) — LLM bilan test dizayn, Playwright Agents, MCP va AI tizimlarini testlash
Manbalar {#manbalar}
- W3C — WCAG 2.2
- W3C WAI — What's New in WCAG 2.2
- W3C WAI — Understanding SC 2.5.8 Target Size (Minimum)
- W3C WAI — WCAG 2.2 Quick Reference
- W3C WAI — Accessibility Principles
- W3C — WCAG 3.0 Working Draft
- W3C — Using ARIA
- W3C WAI — ARIA Authoring Practices Guide
- W3C WAI — Forms tutorial: Instructions (placeholder)
- European Commission — European Accessibility Act
- EUR-Lex — Directive (EU) 2019/882
- Playwright — Accessibility testing
- Playwright — Visual comparisons
- dequelabs/axe-core — GitHub
- Deque — Automated testing study (57%)
- Chrome — Lighthouse accessibility scoring
- WebAIM — Contrast Checker
- WAVE — WebAIM
- NV Access — NVDA
- Apple HIG — Buttons
- Apple HIG — Accessibility
- Apple — Accessibility Inspector
- Google — Accessibility Scanner va touch target tavsiyasi
- W3C Internationalization — Text size in translation
- Unicode CLDR — Language Plural Rules
- Wikipedia — Uzbek alphabet
- UzA — Senate approves changes to Uzbek alphabet (2026-09-10)
- The Times of Central Asia — Uzbekistan Latin alphabet changes
- Kun.uz — Lower house passes bill to revise Uzbek alphabet (2026-07-07)
- Percy — BrowserStack
- Applitools
- Chromatic
- NN/g — 10 Usability Heuristics
- NN/g — Why You Only Need to Test with 5 Users