# QA 9: Web qanday ishlaydi — Client-Server, HTTP, DNS, Cookie, Cache va Chrome DevTools

> **Holat:** 2026-yil oktabr. Bu dars web'ning "ichki kuxnyasi"ni QA ko'zi bilan ochadi: so'rov brauzerdan serverga qanday yetadi, holat (cookie, storage) qayerda saqlanadi, kesh va CORS qanday bug'larga olib keladi va Chrome DevTools bilan bularning hammasini qanday ko'rish mumkin. Barcha `curl` misollari jonli amaliyot saytlarida (jsonplaceholder, restful-booker, saucedemo) ishga tushirib tekshirilgan.

> **Bu darsdan keyin siz:** web ilovadagi istalgan muammoni "front-end'mi, back-end'mi yoki infratuzilmami?" degan savolga dalil bilan javob bera olasiz.

- URL, DNS, TCP/TLS va HTTP so'rov-javobning tuzilishini tushuntira olasiz;
- cookie, localStorage, sessionStorage farqini va ularga bog'liq bug'larni bilasiz;
- kesh (`Cache-Control`, `ETag`, `304`) va CORS xatolarini taniy olasiz;
- Chrome DevTools'ning Elements, Console, Network, Application, Device Mode, Lighthouse panellarida ishlay olasiz;
- bug report'ga HAR, cURL va `X-Request-ID` kabi kuchli dalillarni qo'sha olasiz.

## Mundarija

1. [Client–server modeli](#client-server)
2. [URL anatomiyasi](#url)
3. [DNS, TCP va TLS — so'rov serverga qanday yetadi](#dns-tls)
4. [HTTP so'rov va javob](#http)
5. [Holat: cookie, session va brauzer xotirasi](#state)
6. [Kesh (caching) va kesh bug'lari](#cache)
7. [CORS — QA nimani ko'radi](#cors)
8. [Front-end'mi, back-end'mi? Bug'ni lokalizatsiya qilish](#localize)
9. [Chrome DevTools — QA'ning asosiy quroli](#devtools)
10. [Cross-browser va responsive testlash](#cross-browser)
11. [Web testlash checklisti](#web-checklist)
12. [Amaliy mashqlar](#mashqlar)
13. [Xulosa](#xulosa)
14. [Manbalar](#manbalar)

---

## 1. Client–server modeli {#client-server}

Web ilova kamida ikki tomondan iborat:

- **Client (mijoz)** — foydalanuvchi qurilmasidagi dastur: brauzer, iOS yoki Android ilova. U so'rov yuboradi va javobni chiroyli qilib ko'rsatadi.
- **Server** — internetdagi kompyuter(lar). So'rovni qabul qiladi, biznes mantiqni bajaradi, ma'lumotlar bazasidan o'qiydi yoki yozadi va javob qaytaradi.

Oddiy o'xshatish — choyxona. Mijoz (brauzer) menyudan tanlaydi, ofitsiant (HTTP) buyurtmani oshxonaga (server) olib boradi, oshpaz omborxonadan (ma'lumotlar bazasi) masalliq oladi, tayyor taom (javob) yana ofitsiant orqali qaytadi. Taom sovuq kelsa, kim aybdor: ofitsiantmi, oshpazmi yoki ombormi? QA'ning ishi — aynan shuni dalil bilan aniqlash.

![So'rovning hayot yo'li: brauzer, DNS, server va ma'lumotlar bazasi o'rtasidagi qadamlar va curl bilan o'lchangan vaqtlar](/lessons/images/qa/qa_09_http_flow.svg)

Zamonaviy web ilovalar (DemoBozor ham) odatda **SPA** (Single Page Application) bo'ladi: sahifa bir marta yuklanadi, keyin JavaScript orqasida `fetch` bilan API'ga so'rovlar yuboradi va faqat kerakli qismni yangilaydi. Shu sababli QA uchun "sahifa" emas, **sahifa ortidagi so'rovlar** muhimroq.

| Qatlam             | DemoBozor'da nima             | Bug qayerda ko'rinadi                          | Qanday tekshiramiz                  |
| ------------------ | ----------------------------- | ---------------------------------------------- | ----------------------------------- |
| Front-end (client) | React web, iOS, Android ilova | Noto'g'ri ko'rinish, tugma ishlamaydi, JS xato | DevTools: Elements, Console         |
| Tarmoq             | DNS, HTTPS, CDN, proxy        | Sayt ochilmaydi, sekin, sertifikat xatosi      | DevTools: Network, `curl -v`, `dig` |
| Back-end (API)     | Node.js REST API              | Noto'g'ri ma'lumot, 4xx/5xx, sekin javob       | Network, Postman, loglar            |
| Ma'lumotlar bazasi | PostgreSQL                    | Ma'lumot saqlanmagan, dublikat, eski qiymat    | SQL ([QA 12](/ios-lessons/qa-sql))  |

> **🎯 Intervyuda:** "Brauzerga manzil yozib Enter bosganda nima sodir bo'ladi?" — DNS orqali IP topiladi, TCP ulanish va TLS handshake o'rnatiladi, HTTP so'rov yuboriladi, server (va DB) ishlab javob qaytaradi, brauzer HTML/CSS/JS'ni yuklab sahifani chizadi (render). Har bosqichni bir gap bilan aytsangiz — kuchli javob.

---

## 2. URL anatomiyasi {#url}

URL — resursning manzili. Bitta xayoliy DemoBozor manzilini qismlarga ajratamiz:

```text
https://www.demobozor.example:443/api/v1/products?query=choynak&page=2#reviews
└─┬─┘   └──────┬───────┘ └┬┘└──────┬───────┘└─────────┬─────────┘└──┬───┘
scheme       host       port     path               query       fragment
```

| Qism     | Misol                   | Ma'nosi                                       | QA uchun eslatma                                  |
| -------- | ----------------------- | --------------------------------------------- | ------------------------------------------------- |
| Scheme   | `https`                 | Protokol                                      | `http://` ga o'tganda HTTPS'ga yo'naltiriladimi?  |
| Host     | `www.demobozor.example`      | Server nomi (subdomain + domain + TLD)        | `demobozor.example` va `www.` ikkalasi ishlaydimi?     |
| Port     | `443`                   | HTTPS uchun standart port (HTTP — 80)         | Odatda yozilmaydi                                 |
| Path     | `/api/v1/products`      | Server ichidagi resurs yo'li                  | Katta-kichik harf, oxiridagi `/`                  |
| Query    | `?query=choynak&page=2` | `kalit=qiymat` juftlari, `&` bilan ajratiladi | Filtr, sahifalash — eng ko'p bug shu yerda        |
| Fragment | `#reviews`              | Sahifa ichidagi joy                           | **Serverga yuborilmaydi**, faqat brauzerda qoladi |

### URL encoding

URL'da probel, `&`, `?`, `#` va lotin bo'lmagan harflar maxsus kodlanadi: probel → `%20`, `&` → `%26`. Masalan "choynak 2 litr" qidiruvi `query=choynak%202%20litr` bo'ladi. O'zbekcha `oʻ` harfi ham baytlarga kodlanadi.

QA uchun test g'oyalari:

- qidiruvga `&`, `#`, `%`, `+`, probel, emoji, `oʻ`/`o'` yozib ko'ring — natija bir xilmi?
- URL'ni qo'lda o'zgartiring: `page=0`, `page=-1`, `page=999`, `page=abc`;
- juda uzun query (masalan, 5000 belgi) yuboring — server nima qaytaradi?
- sahifa URL'ini nusxalab, boshqa brauzerda (yoki tizimdan chiqib) oching — xuddi shu holat ochiladimi?

> **💡 Maslahat:** URL'dagi parametrlar bilan "o'ynash" — eng arzon test usuli. Real topilma: Toolshop API'da `GET /products?page=-1` va `page=abc` xato qaytarmaydi, jimgina 1-sahifani beradi (2026-yil oktabrda tekshirildi). Bu xatomi yoki qulaylikmi — talabga qarab hal qilinadi, lekin QA buni albatta qayd etadi.

---

## 3. DNS, TCP va TLS — so'rov serverga qanday yetadi {#dns-tls}

### DNS — internetning "telefon kitobi"

Kompyuterlar bir-birini nom bilan emas, **IP manzil** bilan topadi. DNS (Domain Name System) `jsonplaceholder.typicode.com` kabi nomni IP'ga aylantiradi. Brauzer avval o'z keshiga, keyin operatsion tizimga, so'ng DNS serverga murojaat qiladi.

```bash
dig +short jsonplaceholder.typicode.com
# 188.114.96.1
# 188.114.97.1

nslookup jsonplaceholder.typicode.com
# Name:    jsonplaceholder.typicode.com
# Address: 188.114.97.1
```

Ikkita IP qaytgani — sayt CDN (bu holatda Cloudflare) ortida turganini bildiradi. Sizda IP'lar boshqacha chiqishi mumkin, bu normal.

QA hayotidagi DNS holatlari:

- **"Staging ochilmayapti"** — ko'pincha DNS yozuvi hali tarqalmagan yoki noto'g'ri. Brauzer xatosi: `ERR_NAME_NOT_RESOLVED`.
- **`/etc/hosts` fayli** — ba'zan jamoa test serverga nom bilan kirish uchun shu faylga qator qo'shishni so'raydi.
- **DNS keshi** — server ko'chirilgandan keyin ba'zi foydalanuvchilar hali eski IP'ga borishi mumkin (TTL tugaguncha).

> **⚠️ Diqqat:** `/etc/hosts` faylini o'zgartirish administrator huquqini talab qiladi va butun tizimga ta'sir qiladi. Faqat jamoa ko'rsatmasi bilan o'zgartiring va testdan keyin qatorni qaytarib o'chiring — aks holda keyin "production ochilmayapti" deb vaqt yo'qotasiz.

### TCP va TLS (HTTPS)

IP topilgach, brauzer server bilan **TCP ulanish** o'rnatadi (SYN → SYN-ACK → ACK "qo'l berib ko'rishish"). HTTPS bo'lsa, ustidan **TLS handshake** bo'ladi: server sertifikat ko'rsatadi, brauzer uni tekshiradi va shifrlash kalitlari kelishiladi. HTTPS = HTTP + TLS.

`curl -v` bu jarayonni ko'rsatadi (qisqartirilgan, haqiqiy natija):

```bash
curl -sv -o /dev/null https://jsonplaceholder.typicode.com/posts/1
# * Connected to jsonplaceholder.typicode.com (188.114.96.1) port 443
# * ALPN: curl offers h2,http/1.1
# * SSL connection using TLSv1.3 / AEAD-CHACHA20-POLY1305-SHA256
# * ALPN: server accepted h2
# > GET /posts/1 HTTP/2
# > Host: jsonplaceholder.typicode.com
# < HTTP/2 200
```

QA uchun TLS bilan bog'liq tekshiruvlar: sertifikat muddati o'tmaganmi, `http://` dan `https://` ga yo'naltirish bormi, HTTPS sahifada `http://` rasm yoki skript yuklanmayaptimi (_mixed content_ — Console'da ogohlantirish chiqadi).

### Vaqt qayerga ketdi? `curl -w` bilan o'lchash

"Sayt sekin" degan shikoyatni dalilga aylantirish uchun so'rov vaqtini bosqichlarga bo'lib o'lchang:

```bash
curl -s -o /dev/null -w "dns: %{time_namelookup}s\ntcp: %{time_connect}s\ntls: %{time_appconnect}s\nttfb: %{time_starttransfer}s\njami: %{time_total}s\nhttp: %{http_version}\n" \
  https://jsonplaceholder.typicode.com/posts/1
# dns: 0.087438s
# tcp: 0.251127s
# tls: 0.423945s
# ttfb: 0.594272s
# jami: 0.594820s
# http: 2
```

Bu qiymatlar **yig'ma** (har biri boshidan hisoblanadi). Ayirmalar: DNS ≈ 87 ms, TCP ≈ 164 ms, TLS ≈ 173 ms, server javobini kutish ≈ 170 ms. Agar "ttfb" uzun bo'lsa — backend sekin; "dns" uzun bo'lsa — DNS muammosi; "tcp/tls" uzun bo'lsa — tarmoq yoki masofa. DevTools'ning **Timing** tab'i ham xuddi shu bosqichlarni ko'rsatadi ([9-bo'lim](#devtools)).

---

## 4. HTTP so'rov va javob {#http}

HTTP — client va server gaplashadigan til. U **matnli va tushunarli**: so'rov ham, javob ham "boshlang'ich qator + header'lar + bo'sh qator + body" tuzilishiga ega.

### Xom (raw) so'rov

```http
GET /posts/1 HTTP/1.1
Host: jsonplaceholder.typicode.com
User-Agent: curl/8.7.1
Accept: */*
```

Body bilan so'rov (xayoliy DemoBozor API):

```http
POST /api/v1/cart/items HTTP/1.1
Host: api.demobozor.example
Content-Type: application/json
Authorization: Bearer eyJhbGciOi...
Accept-Language: uz

{"productId": 1042, "quantity": 2}
```

### Xom javob

Haqiqiy javob (`curl -i https://jsonplaceholder.typicode.com/posts/1`, qisqartirilgan):

```http
HTTP/2 200
content-type: application/json; charset=utf-8
cache-control: max-age=43200
etag: W/"124-yiKdLzqO5gfBrJFrcdJ8Yq0LGnU"
x-ratelimit-limit: 3600000
cf-cache-status: HIT
server: cloudflare

{
  "userId": 1,
  "id": 1,
  "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
  "body": "quia et suscipit..."
}
```

### Method'lar — qisqacha

| Method   | Nima qiladi          | DemoBozor misoli                          |
| -------- | -------------------- | ----------------------------------------- |
| `GET`    | O'qiydi              | `GET /api/v1/products?query=choynak`      |
| `POST`   | Yangi narsa yaratadi | `POST /api/v1/orders`                     |
| `PUT`    | To'liq almashtiradi  | `PUT /api/v1/profile`                     |
| `PATCH`  | Qisman o'zgartiradi  | `PATCH /api/v1/cart/items/7` (`quantity`) |
| `DELETE` | O'chiradi            | `DELETE /api/v1/cart/items/7`             |

Method'larning xususiyatlari (safe, idempotent) va CRUD bilan bog'liqligi keyingi darsda batafsil: [QA 10](/ios-lessons/qa-api-postman).

### Status kod sinflari

| Sinf  | Ma'nosi             | Ko'pincha kimga qarash kerak                            | Misollar                                  |
| ----- | ------------------- | ------------------------------------------------------- | ----------------------------------------- |
| `1xx` | Ma'lumot berish     | —                                                       | `101 Switching Protocols` (WebSocket)     |
| `2xx` | Muvaffaqiyat        | —                                                       | `200 OK`, `201 Created`, `204 No Content` |
| `3xx` | Yo'naltirish / kesh | Konfiguratsiya                                          | `301`, `302`, `304 Not Modified`          |
| `4xx` | Mijoz xatosi        | So'rov (front-end yoki foydalanuvchi kiritgan ma'lumot) | `400`, `401`, `403`, `404`, `422`, `429`  |
| `5xx` | Server xatosi       | Back-end yoki infratuzilma                              | `500`, `502`, `503`, `504`                |

> **🧠 Esda tuting:** `4xx` "mijoz aybdor" degani har doim ham emas. Server mavjud mahsulot uchun `404` qaytarsa — bu back-end bug'i. Status kod — yo'nalish ko'rsatkichi, hukm emas.

### QA uchun eng muhim header'lar

| Header                                            | Yo'nalish      | Nima uchun QA'ga kerak                                                             |
| ------------------------------------------------- | -------------- | ---------------------------------------------------------------------------------- |
| `Host`                                            | So'rov         | Qaysi serverga (muhitga) ketayotganini tasdiqlash                                  |
| `User-Agent`                                      | So'rov         | Qaysi brauzer/ilova versiyasi — bug report uchun                                   |
| `Accept-Language`                                 | So'rov         | Lokalizatsiya: `uz`, `ru`, `en` bo'yicha javob o'zgaradimi                         |
| `Content-Type`                                    | Ikkalasi       | Body formati (`application/json`) — noto'g'ri bo'lsa, server body'ni o'qiy olmaydi |
| `Authorization`                                   | So'rov         | Token yuborilganmi                                                                 |
| `Cookie` / `Set-Cookie`                           | So'rov / javob | Sessiya va holat ([5-bo'lim](#state))                                              |
| `Cache-Control`, `ETag`                           | Javob          | Kesh xatti-harakati ([6-bo'lim](#cache))                                           |
| `Location`                                        | Javob          | `201` yoki `3xx` da yangi resurs/yo'naltirish manzili                              |
| `Access-Control-Allow-Origin`                     | Javob          | CORS ([7-bo'lim](#cors))                                                           |
| `X-Request-ID` (nomi jamoada farq qilishi mumkin) | Javob          | So'rovning noyob ID'si — back-end logidan aynan shu so'rovni topish uchun          |

> **💡 Maslahat:** Agar loyihangizda javoblarda `X-Request-ID` (yoki `X-Correlation-ID`, `traceparent`) bo'lsa, uni har bir back-end bug report'iga qo'shing. Dasturchi logdan sizning so'rovingizni bir zumda topadi. Loglar haqida: [QA 13](/ios-lessons/qa-terminal-git-logs).

### HTTP/1.1, HTTP/2, HTTP/3

| Versiya  | Transport         | Asosiy g'oya                                                       | DevTools `Protocol` ustunida |
| -------- | ----------------- | ------------------------------------------------------------------ | ---------------------------- |
| HTTP/1.1 | TCP               | Bir ulanishda so'rovlar navbat bilan                               | `http/1.1`                   |
| HTTP/2   | TCP + TLS         | Binary format, bitta ulanishda ko'p so'rov parallel (multiplexing) | `h2`                         |
| HTTP/3   | QUIC (UDP ustida) | Ulanish tezroq o'rnatiladi, paket yo'qolishiga chidamliroq         | `h3`                         |

QA uchun amaliy xulosa: versiya odatda biznes mantiqqa ta'sir qilmaydi, lekin "bir brauzerda ishlaydi, boshqasida yo'q" yoki proxy/korporativ tarmoqda g'alati xatolar chiqsa, protokol versiyasini ham bug report'ga yozing.

---

## 5. Holat: cookie, session va brauzer xotirasi {#state}

HTTP **stateless** — server har bir so'rovni alohida, oldingisini eslamasdan qabul qiladi. "Siz tizimga kirgansiz", "savatchada 2 ta choynak bor" kabi holatni saqlash uchun cookie va brauzer xotirasi ishlatiladi.

### Cookie va uning atributlari

Server javobda `Set-Cookie` header'ini yuboradi, brauzer uni saqlaydi va keyingi so'rovlarda `Cookie` header'ida qaytarib yuboradi. GitHub bosh sahifasidan haqiqiy misol (qiymatlar qisqartirilgan):

```http
set-cookie: _gh_sess=…; path=/; HttpOnly; secure; SameSite=Lax
set-cookie: logged_in=no; expires=Sat, 09 Oct 2027 16:48:14 GMT; domain=.github.com; path=/; HttpOnly; secure; SameSite=Lax
```

| Atribut               | Ma'nosi                                                                                                  | QA nimani tekshiradi                                                    |
| --------------------- | -------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- |
| `Expires` / `Max-Age` | Qachon o'chadi. Ikkalasi bo'lsa — `Max-Age` ustun                                                        | Muddat to'g'rimi; "Meni eslab qol" ishlaydimi                           |
| _(ikkalasi ham yo'q)_ | **Session cookie** — brauzer yopilganda o'chadi (sessiyani tiklash funksiyasi buni o'zgartirishi mumkin) | Brauzerni yopib-ochganda holat                                          |
| `Domain`, `Path`      | Cookie qaysi domen/yo'lga yuboriladi                                                                     | Subdomain'lar orasida login saqlanadimi                                 |
| `HttpOnly`            | JavaScript (`document.cookie`) o'qiy olmaydi                                                             | Sessiya cookie'sida **albatta** bo'lishi kerak (XSS'dan himoya)         |
| `Secure`              | Faqat HTTPS orqali yuboriladi (localhost bundan mustasno)                                                | Auth cookie'larda bo'lishi shart                                        |
| `SameSite=Strict`     | Faqat shu saytning o'zidan kelgan so'rovlarda yuboriladi                                                 | Boshqa saytdan link bosib kelganda login "yo'qoladi" — kutilganmi?      |
| `SameSite=Lax`        | + boshqa saytdan **top-level** GET navigatsiyada ham yuboriladi                                          | Ko'p brauzerlarda (masalan, Chrome'da) atribut yozilmasa shu qo'llanadi |
| `SameSite=None`       | Barcha cross-site so'rovlarda yuboriladi; **`Secure` majburiy**                                          | `Secure`siz `None` — brauzer cookie'ni qabul qilmaydi                   |

> **🧠 Esda tuting:** Sessiya/auth cookie'si uchun oltin uchlik: `HttpOnly; Secure; SameSite=Lax` (yoki `Strict`). Bittasi yo'qligi — xavfsizlik bo'yicha savol. Batafsil: [QA 24](/ios-lessons/qa-security).

### localStorage, sessionStorage, IndexedDB

|                                 | Cookie                           | `localStorage`                      | `sessionStorage`                    | IndexedDB                   |
| ------------------------------- | -------------------------------- | ----------------------------------- | ----------------------------------- | --------------------------- |
| Serverga avtomatik yuboriladimi | Ha, har mos so'rovda             | Yo'q                                | Yo'q                                | Yo'q                        |
| Qancha yashaydi                 | `Expires`/`Max-Age` yoki sessiya | O'chirilmaguncha                    | Tab yopilguncha (har tab — alohida) | O'chirilmaguncha            |
| JS o'qiy oladimi                | `HttpOnly` bo'lmasa — ha         | Ha                                  | Ha                                  | Ha                          |
| Odatiy ishlatilishi             | Sessiya, auth                    | Sozlamalar, savatcha, tanlangan til | Vaqtinchalik forma holati           | Katta yoki offline ma'lumot |

### Real misol: saucedemo holatni qayerda saqlaydi?

Saucedemo'ga `standard_user` bilan kirib, bitta mahsulot qo'shib, DevTools → **Application** panelini ochsangiz (2026-yil oktabrda tekshirildi):

- **Cookies:** `session-username = standard_user` — `HttpOnly` yo'q, `Secure` yo'q, `SameSite=Lax`, muddati kirgandan taxminan 10 daqiqa keyin tugaydi;
- **Local Storage:** `cart-contents = [4]` — savatcha butunlay brauzerda saqlanadi (4 — mahsulot ID'si).

Bu kuzatuvlardan chiqadigan QA savollari:

1. Cookie `HttpOnly` emas — `document.cookie` uni o'qiy oladi. Demo ilova uchun mayli, real ilovada sessiya cookie'si uchun bu xavfsizlik topilmasi bo'lardi.
2. Savatcha localStorage'da — boshqa brauzer yoki qurilmadan kirsangiz, savatcha bo'sh bo'ladi. Talab "savatcha qurilmalar orasida sinxron" desa — bu bug.
3. `cart-contents` ni qo'lda `[4, 999]` ga o'zgartirsangiz nima bo'ladi? Mavjud bo'lmagan mahsulot ID'sini ilova qanday ko'taradi?

### Holat bilan bog'liq test g'oyalari

- Logout'dan keyin "Orqaga" tugmasi bilan himoyalangan sahifaga qaytib bo'ladimi?
- Ikki tab: birida logout, ikkinchisida "Sotib olish" bossangiz nima bo'ladi?
- Sessiya muddati checkout'ning o'rtasida tugasa, kiritilgan manzil yo'qolib ketadimi?
- Inkognito oynada, yoki **Application → Clear site data** dan keyin ilova to'g'ri "toza" holatdan boshlanadimi?

---

## 6. Kesh (caching) va kesh bug'lari {#cache}

Kesh — avval yuklangan narsani qayta yuklamaslik uchun nusxa saqlash. U uch joyda bo'lishi mumkin: **brauzer keshi**, **CDN keshi** (masalan, Cloudflare) va **server keshi**.

| Header                              | Ma'nosi                                                             |
| ----------------------------------- | ------------------------------------------------------------------- |
| `Cache-Control: max-age=43200`      | 43 200 soniya (12 soat) davomida qayta so'ramasdan ishlatish mumkin |
| `Cache-Control: no-cache`           | Saqlash mumkin, lekin har safar server bilan tekshirib olish kerak  |
| `Cache-Control: no-store`           | Umuman saqlamang (shaxsiy/maxfiy ma'lumot uchun)                    |
| `Cache-Control: private` / `public` | Faqat foydalanuvchi brauzeri / CDN ham saqlashi mumkin              |
| `ETag`                              | Resurs versiyasining "barmoq izi"                                   |
| `If-None-Match`                     | Client: "menda shu ETag bor, o'zgarganmi?"                          |
| `304 Not Modified`                  | Server: "o'zgarmagan, keshdagini ishlating" (body yuborilmaydi)     |
| `Age`, `cf-cache-status: HIT`       | Javob CDN keshidan kelgan va qancha vaqtdan beri u yerda turibdi    |

### Jonli tajriba: ETag va 304

```bash
# 1) ETag'ni olamiz
curl -sI https://jsonplaceholder.typicode.com/posts/1 | grep -i etag
# etag: W/"124-yiKdLzqO5gfBrJFrcdJ8Yq0LGnU"

# 2) Shu ETag bilan shartli so'rov yuboramiz
curl -s -o /dev/null -w "%{http_code}\n" https://jsonplaceholder.typicode.com/posts/1 \
  -H 'If-None-Match: W/"124-yiKdLzqO5gfBrJFrcdJ8Yq0LGnU"'
# 304
```

ETag qiymati vaqt o'tib o'zgarishi mumkin — 1-buyruqdagi qiymatni 2-buyruqqa o'zingiz qo'ying.

### Tipik kesh bug'lari

| Bug                             | Belgisi                                                 | Qanday tekshiramiz                                       |
| ------------------------------- | ------------------------------------------------------- | -------------------------------------------------------- |
| Deploy'dan keyin eski JS/CSS    | Yangi tugma ko'rinmaydi, inkognitoda ko'rinadi          | Hard reload; fayl nomlarida hash bormi (`app.3f9a1c.js`) |
| CDN eski narxni ko'rsatadi      | Admin narxni o'zgartirdi, saytda eskisi                 | `Age`, `cf-cache-status` header'lari                     |
| Shaxsiy ma'lumot umumiy keshda  | A foydalanuvchi B'ning profilini ko'radi (juda jiddiy!) | Shaxsiy javoblarda `private`/`no-store` bormi            |
| PATCH'dan keyin GET eski qiymat | Saqladingiz, ro'yxatda eski                             | Network'da GET `(disk cache)` dan kelyaptimi             |

Keshni chetlab o'tish usullari:

- **Hard reload:** macOS'da `Cmd+Shift+R`, Windows/Linux'da `Ctrl+Shift+R`;
- DevTools → Network → **Disable cache** (faqat DevTools ochiq turganda ishlaydi);
- inkognito oyna yoki **Application → Clear site data**.

> **⚠️ Diqqat:** Bug'ni "kesh tufayli" deb yopishdan oldin, uni keshsiz holatda qayta tekshiring. Lekin foydalanuvchilar hard reload qilmaydi — deploy'dan keyin eski fayl ko'rsatilishining o'zi ham bug (cache-busting yo'q).

---

## 7. CORS — QA nimani ko'radi {#cors}

**Same-origin policy** — brauzerning xavfsizlik qoidasi: bir **origin**dan (scheme + host + port) yuklangan sahifadagi JavaScript boshqa origin'ga so'rov yuborib, javobni o'qishi cheklangan. `https://demobozor.example` sahifasi `https://api.demobozor.example` ga murojaat qilsa — bu boshqa origin.

Ruxsat berish uchun server **CORS** header'larini qaytaradi. "Murakkab" so'rovlardan (masalan, `Content-Type: application/json` bilan `POST`) oldin brauzer avtomatik **preflight** — `OPTIONS` so'rov yuboradi. Jonli misol:

```bash
curl -s -i -X OPTIONS https://jsonplaceholder.typicode.com/posts \
  -H "Origin: https://demobozor.example" \
  -H "Access-Control-Request-Method: POST" \
  -H "Access-Control-Request-Headers: content-type"
# HTTP/2 204
# access-control-allow-credentials: true
# access-control-allow-headers: content-type
# access-control-allow-methods: GET,HEAD,PUT,PATCH,POST,DELETE
# access-control-allow-origin: https://demobozor.example
```

QA'ga kerakli faktlar:

1. CORS xatosi **Console**'da ko'rinadi: `... has been blocked by CORS policy ...`. Network'da so'rov qizil bo'lishi yoki javob bo'sh ko'rinishi mumkin.
2. CORS — **faqat brauzer** qoidasi. `curl`, Postman yoki mobil ilova uni tekshirmaydi. Shuning uchun klassik holat: "Postman'da ishlayapti, saytda ishlamayapti" → katta ehtimol bilan CORS.
3. Ko'pincha tuzatish back-end/infra konfiguratsiyasida bo'ladi (ruxsat etilgan origin'lar ro'yxati), ba'zan esa front-end noto'g'ri API manzilga murojaat qilayotgan bo'ladi.

> **⚠️ Diqqat:** jsonplaceholder har qanday origin'ni qaytarib "aks ettiradi" va `allow-credentials: true` beradi. Bu ochiq demo API uchun mayli. Cookie bilan ishlaydigan real ilovada esa bunday sozlama xavfsizlik muammosi bo'ladi — QA buni [QA 24](/ios-lessons/qa-security) dagi checklist bo'yicha tekshiradi.

---

## 8. Front-end'mi, back-end'mi? Bug'ni lokalizatsiya qilish {#localize}

Yaxshi QA bug'ni shunchaki "ishlamayapti" deb emas, **qaysi qatlamda** ekanini ko'rsatib yozadi. Algoritm — avval Network:

```text
Muammo UI'da ko'rindi
│
├─ 1. Network'da tegishli so'rov ketdimi?
│     ├─ Yo'q → FRONT-END (tugma handler'i, validatsiya, JS xato → Console'ni oching)
│     └─ Ha ↓
├─ 2. So'rov to'g'rimi? (URL, method, header'lar, Payload)
│     ├─ Yo'q → FRONT-END (noto'g'ri ma'lumot yuborilgan)
│     └─ Ha ↓
├─ 3. Status kod qanday?
│     ├─ 5xx → BACK-END / infra (X-Request-ID bilan server logini so'rang)
│     ├─ 4xx → so'rov noto'g'rimi yoki back-end qoidasi xatomi — talab bilan solishtiring
│     └─ 2xx ↓
├─ 4. Javobdagi ma'lumot to'g'rimi? (Preview / Response)
│     ├─ Yo'q → BACK-END (noto'g'ri hisob, eski kesh, noto'g'ri filtr)
│     └─ Ha ↓
└─ 5. UI javobni to'g'ri ko'rsatyaptimi?
      └─ Yo'q → FRONT-END (render, format, holat boshqaruvi)
```

DemoBozor misoli: savatchada "Yetkazib berish: 20 000 so'm" ko'rinyapti, mahsulotlar summasi esa 300 000 so'm (qoida bo'yicha bepul bo'lishi kerak).

- Network → `GET /api/v1/cart` javobida `"deliveryFee": 0` → API to'g'ri, **front-end** narxni o'zi noto'g'ri hisoblayapti.
- Javobda `"deliveryFee": 20000` → **back-end** qoidani `>` bilan yozgan (`>=` o'rniga) — chegaraviy qiymat bug'i.

| Belgi                                                  | Ehtimoliy qatlam                                                                                            |
| ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------- |
| Console'da qizil `TypeError`, so'rov yo'q              | Front-end                                                                                                   |
| `net::ERR_NAME_NOT_RESOLVED`, `ERR_CONNECTION_REFUSED` | Infra / DNS / server o'chiq                                                                                 |
| `502 Bad Gateway`, `504 Gateway Timeout`               | Infra yoki back-end (proxy orqasidagi xizmat javob bermadi)                                                 |
| `500` va javobda stack trace                           | Back-end (+ xavfsizlik topilmasi: ichki xato tafsiloti oshkor bo'lmoqda)                                    |
| `200`, ma'lumot to'g'ri, ekranda noto'g'ri             | Front-end                                                                                                   |
| Faqat bitta brauzerda                                  | Front-end (moslik)                                                                                          |
| Faqat mobil ilovada, web'da yo'q                       | Mobil client yoki u chaqiradigan boshqa endpoint ([QA 15](/ios-lessons/qa-proxyman) bilan trafikni ko'ring) |

Bug report'ga nima qo'shish kerakligi haqida: [QA 8](/ios-lessons/qa-bug-reports).

---

## 9. Chrome DevTools — QA'ning asosiy quroli {#devtools}

DevTools'ni ochish: `F12`, yoki macOS'da `Cmd+Option+I`, Windows/Linux'da `Ctrl+Shift+I`. Har qanday element ustida o'ng tugma → **Inspect**.

### Elements

- DOM daraxti va CSS'ni ko'rish. Matnni ikki marta bosib **o'zgartirish** mumkin — juda uzun nom (50 belgilik ism) dizaynni buzadimi, kod yozmasdan tekshirasiz.
- **Force state** (`:hover`, `:focus`, `:active`) — sichqoncha ustida turgandagi holatni "muzlatib" ko'rish.
- Yashirin elementlar, `disabled` atributi, `data-test` kabi test atributlarini topish (avtomatlashtirishda kerak bo'ladi — [QA 18](/ios-lessons/qa-playwright-basics)).

### Console

- Qizil xatolar va sariq ogohlantirishlar. **Har bir test sessiyasida Console ochiq tursin** — UI'da hech narsa ko'rinmasa ham, ichkarida xato bo'lishi mumkin.
- **Preserve log** — sahifa yangilanganda ham loglar o'chmaydi (redirect'li jarayonlar uchun).
- JavaScript ishga tushirish: `document.cookie`, `localStorage.getItem('cart-contents')`, `$0` (Elements'da tanlangan element).

### Network — eng muhim panel

| Imkoniyat          | Qayerda                                                                   | Nima uchun                                           |
| ------------------ | ------------------------------------------------------------------------- | ---------------------------------------------------- |
| Tur bo'yicha filtr | `Fetch/XHR`, `Doc`, `JS`, `CSS`, `Img`, `WS`… tugmalari                   | Faqat API so'rovlarini ko'rish                       |
| Xususiyat filtri   | Filter maydoniga `status-code:500`, `mime-type:…`, `larger-than:1K`       | Masalan, faqat 500'larni topish                      |
| **Preserve log**   | Yuqori panel                                                              | Redirect va sahifa almashganda so'rovlar yo'qolmaydi |
| **Disable cache**  | Yuqori panel                                                              | Birinchi tashrifni simulyatsiya qilish               |
| Throttling         | `No throttling` ro'yxati: `Fast 4G`, `Slow 4G`, `3G`, `Offline`, `Custom` | Sekin internetda loading/timeout holatlari           |
| So'rov tafsiloti   | `Headers`, `Payload`, `Preview`, `Response`, `Timing` tab'lari            | Nima ketdi, nima keldi, vaqt qayerga ketdi           |
| `Protocol` ustuni  | Jadval sarlavhasiga o'ng tugma                                            | `h2`, `h3` ni ko'rish                                |
| **Copy as cURL**   | So'rovga o'ng tugma → Copy                                                | So'rovni terminalda/Postman'da aynan takrorlash      |
| **Replay XHR**     | So'rovga o'ng tugma (yoki `R`)                                            | So'rovni sahifani yangilamasdan qayta yuborish       |
| **Export HAR**     | Yuqori paneldagi eksport tugmasi                                          | Butun seansni dasturchiga yuborish                   |

Throttling nomlari Chrome versiyasiga qarab biroz farq qilishi mumkin — ro'yxatda nima bo'lsa, shuni ishlating.

**Timing** tab'idagi bosqichlar: `Queueing`, `Stalled`, `DNS Lookup`, `Initial connection` (TCP va SSL/TLS shu ichida), `Request sent`, `Waiting (TTFB)`, `Content Download`. `Waiting (TTFB)` uzun bo'lsa — server sekin ishlayapti, back-end'ga yozing.

> **⚠️ Diqqat:** HAR faylida so'rov va javoblarning **hammasi** bo'ladi. Chrome standart holatda **sanitized** HAR eksport qiladi — `Cookie`, `Set-Cookie` va `Authorization` header'larini olib tashlaydi. To'liq variant (_with sensitive data_) faqat Settings → Preferences → Network'dagi maxsus sozlama yoqilganda chiqadi. Token yoki shaxsiy ma'lumotli HAR'ni ochiq chatga tashlamang.

**Request blocking:** DevTools drawer'idagi **Network request blocking** paneli (yangi versiyalarda — _Request conditions_) orqali biror URL'ni bloklab, masalan, rasm CDN'i yoki analitika ishlamay qolganda sahifa qanday ko'rinishini tekshirasiz.

**Local overrides:** so'rovga o'ng tugma → **Override content** (yoki **Override headers**). Birinchi marta DevTools fayllarni saqlash uchun papka tanlashni va ruxsat berishni so'raydi; o'zgartirilgan fayllar **Sources → Overrides** da turadi. Shu yo'l bilan back-end'ga tegmasdan API javobini almashtirib, "savatchada 99 ta mahsulot" yoki "narx `null`" kabi chekka holatlarda UI'ni tekshirasiz. Overrides yoqilganda kesh o'chadi. Mobil ilova uchun xuddi shu ishni Proxyman'ning Map Local funksiyasi qiladi: [QA 15](/ios-lessons/qa-proxyman).

### Application

- **Cookies** — ko'rish, tahrirlash, o'chirish (sessiya tugashini simulyatsiya qilish uchun sessiya cookie'sini o'chiring).
- **Local Storage / Session Storage / IndexedDB** — saqlangan ma'lumotlar.
- **Storage → Clear site data** — saytni "birinchi kirish" holatiga qaytarish.

### Device Mode (responsive)

"Toggle device toolbar" tugmasi orqali yoqiladi. `Responsive` rejimida kenglikni qo'lda berasiz yoki **Dimensions** ro'yxatidan qurilma tanlaysiz; DPR, qurilma turi (touch/no touch), aylantirish (rotate) va **Sensors** panelidan geolokatsiya ham sozlanadi.

> **🧠 Esda tuting:** Google'ning o'zi Device Mode'ni mobil qurilmaning "birinchi yaqinlashuvi" deb ataydi — u Chrome dvigatelida ishlaydi va mobil protsessorni simulyatsiya qila olmaydi. iPhone Safari'dagi bug'lar uchun haqiqiy qurilma yoki simulyator kerak ([QA 14](/ios-lessons/qa-mobile-testing)).

### Lighthouse va Recorder

- **Lighthouse** — sahifani Performance, Accessibility, Best Practices, SEO bo'yicha avtomatik tekshiradi va hisobot beradi. Chuqurroq: [QA 23](/ios-lessons/qa-performance-k6) va [QA 25](/ios-lessons/qa-a11y-l10n-visual).
- **Recorder** — foydalanuvchi oqimini yozib oladi, qayta ijro etadi va performance'ni o'lchaydi. Yozuvni JSON yoki Puppeteer skript sifatida eksport qilish mumkin. Bug report'dagi qadamlarni takrorlanadigan qilish uchun qulay.

---

## 10. Cross-browser va responsive testlash {#cross-browser}

Brauzerlar sahifani turli **dvigatellar** bilan chizadi:

| Brauzer                    | Dvigatel         |
| -------------------------- | ---------------- |
| Chrome, Edge, Opera, Brave | Blink (Chromium) |
| Safari (macOS, iOS)        | WebKit           |
| Firefox                    | Gecko            |

iOS'da web ko'radigan ilovalar odatda WebKit'dan foydalanishi shart (App Store Review Guideline 2.5.6); muqobil dvigatellarga faqat maxsus ruxsat bilan, EU va Yaponiyada yo'l ochilgan. Ya'ni iPhone'dagi "Chrome" ko'p hollarda ichida Safari dvigateli bilan ishlaydi — Safari bug'i iPhone Chrome'da ham chiqishi mumkin.

Brauzerlar orasida ko'p farq qiladigan joylar:

- sana/vaqt input'lari (`<input type="date">` ko'rinishi va formati);
- yangi CSS xususiyatlari va shriftlar;
- cookie siyosati (ayniqsa uchinchi tomon cookie'lari) va video autoplay;
- klaviatura, scroll va fokus xatti-harakati.

**Responsive** testda bitta sahifani bir necha kenglikda tekshiring, masalan 360, 390, 768, 1024, 1280 va 1440 px (aniq ro'yxatni loyihangiz analitikasi va dizayn breakpoint'lari belgilaydi). Har kenglikda: matn kesilmayaptimi, tugmalar ustma-ust tushmayaptimi, gorizontal scroll paydo bo'lmayaptimi, menyu ochilib-yopilyaptimi.

Ko'p brauzerda avtomatik tekshirish — Playwright'ning `projects` imkoniyati ([QA 19](/ios-lessons/qa-playwright-advanced)); real qurilmalar — device cloud'lar ([QA 14](/ios-lessons/qa-mobile-testing)).

---

## 11. Web testlash checklisti {#web-checklist}

| Soha                 | Tekshiruvlar                                                                                                                                          |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| Formalar             | Majburiy maydonlar, min/max uzunlik, noto'g'ri format, copy-paste, probel bilan boshlanish, `Enter` bilan yuborish, xato xabari aniq va maydon yonida |
| Ikki marta bosish    | "Buyurtma berish"ni tez-tez 2 marta bosish — 2 ta buyurtma yaratilmaydimi                                                                             |
| Navigatsiya          | Orqaga/Oldinga tugmalari, sahifani yangilash (ayniqsa forma yuborilayotganda), chuqur havolani yangi tabda ochish                                     |
| Havolalar            | 404'ga olib boradigan havola yo'qmi, tashqi havolalar to'g'ri ochiladimi                                                                              |
| Holat                | Sessiya tugashi, ikki tab, logout'dan keyin "Orqaga", inkognito                                                                                       |
| Tarmoq               | `Offline` va `3G` da loading holati, timeout xabari, qayta urinish                                                                                    |
| Console              | Asosiy oqimlarda qizil xato yo'q                                                                                                                      |
| Kesh                 | Deploy'dan keyin yangi versiya ko'rinadi; shaxsiy sahifalar keshlanmaydi                                                                              |
| Responsive           | Asosiy breakpoint'larda sahifa buzilmaydi                                                                                                             |
| Cross-browser        | Chrome, Safari, Firefox (+ loyihada kerak bo'lsa Edge)                                                                                                |
| Lokalizatsiya        | `uz`/`ru`/`en` matnlari sig'adi, sana `dd.mm.yyyy`, narx `1 000 000 so'm`                                                                             |
| Xavfsizlik asoslari  | HTTPS'ga yo'naltirish, cookie atributlari, xatoda stack trace chiqmaydi                                                                               |
| Performance asoslari | Lighthouse'da sezilarli muammo yo'q, katta rasmlar optimallashtirilgan                                                                                |

---

## 12. Amaliy mashqlar {#mashqlar}

### Mashq 1: URL'ni qismlarga ajrating

Quyidagi xayoliy manzilning scheme, host, path, query parametrlari va fragment'ini yozing. Qaysi qismi serverga **yuborilmaydi**?

`https://demobozor.example/catalog/choynaklar?sort=price_asc&min=150000&page=3#filters`

<details>
<summary>💡 Javobni ko'rish</summary>

| Qism     | Qiymat                                   |
| -------- | ---------------------------------------- |
| Scheme   | `https`                                  |
| Host     | `demobozor.example`                           |
| Port     | yozilmagan → HTTPS uchun `443`           |
| Path     | `/catalog/choynaklar`                    |
| Query    | `sort=price_asc`, `min=150000`, `page=3` |
| Fragment | `filters`                                |

Serverga **fragment** (`#filters`) yuborilmaydi — u faqat brauzerda qoladi. Test g'oyalari: `sort` ga noma'lum qiymat, `min` ga manfiy son yoki harf, `page=0` berib, server va UI xatti-harakatini kuzating.

</details>

### Mashq 2: Kesh header'larini o'qing

`curl` bilan `https://jsonplaceholder.typicode.com/posts/3` ning header'larini oling. `Cache-Control` va `ETag` qiymatlarini toping, so'ng shu ETag bilan shartli so'rov yuborib `304` oling.

<details>
<summary>💡 Javobni ko'rish</summary>

```bash
curl -sI https://jsonplaceholder.typicode.com/posts/3 | grep -iE "cache-control|etag"
# cache-control: max-age=43200
# etag: W/"…"   ← sizdagi qiymat

curl -s -o /dev/null -w "%{http_code}\n" https://jsonplaceholder.typicode.com/posts/3 \
  -H 'If-None-Match: W/"…"'   # ← 1-buyruqdan olingan aniq qiymatni qo'ying
# 304
```

`max-age=43200` — 12 soat. `304` javobida body yo'q: brauzer keshdagi nusxani ishlatadi. Agar `200` qaytsa — ETag'ni noto'g'ri nusxalagansiz (qo'shtirnoqlar va `W/` prefiksi ham qiymatning bir qismi).

</details>

### Mashq 3: Kimning bug'i?

Har bir holat uchun ehtimoliy qatlamni (front-end, back-end, infra) va asosiy dalilni yozing:

1. "To'lash" bosilganda Network'da hech qanday so'rov yo'q, Console'da `TypeError: Cannot read properties of undefined (reading 'id')`.
2. `GET /api/v1/products?query=choynak` → `200`, javobda 12 ta mahsulot, ekranda "Hech narsa topilmadi".
3. `GET /api/v1/cart` → `200`, javobda `"subtotal": 300000, "deliveryFee": 20000`.
4. Sayt ochilmaydi, Console/Network'da `net::ERR_NAME_NOT_RESOLVED`.
5. `POST /api/v1/orders` → `502 Bad Gateway`.

<details>
<summary>💡 Javobni ko'rish</summary>

| #   | Qatlam              | Dalil va izoh                                                                                                                          |
| --- | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| 1   | Front-end           | So'rov umuman ketmagan, JS xatosi — Console screenshot'i va stack trace                                                                |
| 2   | Front-end           | API to'g'ri ma'lumot berdi, UI ko'rsatmadi — Network Response + ekran screenshot'i                                                     |
| 3   | Back-end            | 300 000 ≥ 300 000 → bepul bo'lishi kerak. Qoida `>` bilan yozilgan bo'lishi mumkin (chegaraviy qiymat) — so'rov/javob + `X-Request-ID` |
| 4   | Infra / DNS         | Domen IP'ga aylanmayapti — `dig`/`nslookup` natijasi                                                                                   |
| 5   | Infra yoki back-end | Gateway (proxy) orqadagi xizmatdan to'g'ri javob ololmadi — vaqt, `X-Request-ID`, takrorlanish chastotasi                              |

</details>

### Mashq 4: Cookie viktorinasi

1. `Set-Cookie: sid=abc; Path=/; HttpOnly; Secure; SameSite=Strict` — JavaScript `document.cookie` orqali o'qiy oladimi? `http://` orqali yuboriladimi? Boshqa saytdagi havolani bosib kelganda yuboriladimi?
2. `Set-Cookie: theme=dark; Max-Age=31536000` — qancha yashaydi? JS o'qiy oladimi?
3. `Set-Cookie: cart=7; SameSite=None` — nima bo'ladi?
4. `Set-Cookie: lang=uz` — bu qanday cookie?

<details>
<summary>💡 Javobni ko'rish</summary>

1. JS o'qiy olmaydi (`HttpOnly`); `http://` orqali yuborilmaydi (`Secure`); `Strict` bo'lgani uchun boshqa saytdan kelgan navigatsiyada ham yuborilmaydi — foydalanuvchi "tizimdan chiqib qolgandek" ko'rinishi mumkin.
2. 31 536 000 soniya = 365 kun. `HttpOnly` yo'q — JS o'qiy oladi (mavzu sozlamasi uchun bu normal).
3. `SameSite=None` uchun `Secure` majburiy — brauzer bunday cookie'ni qabul qilmaydi. Bu — bug.
4. `Expires` ham, `Max-Age` ham yo'q → **session cookie**, brauzer yopilganda o'chadi (sessiyani tiklash funksiyasi buni o'zgartirishi mumkin).

</details>

### Mashq 5: Network jadvalini o'qing

Checkout sahifasida "Buyurtma berish" bosilgandan keyingi so'rovlar:

| #   | Method | URL                        | Status | Vaqt         |
| --- | ------ | -------------------------- | ------ | ------------ |
| 1   | GET    | `/checkout`                | 200    | 180 ms       |
| 2   | GET    | `/static/app.3f9a1c.js`    | 200    | (disk cache) |
| 3   | GET    | `/api/v1/cart`             | 200    | 240 ms       |
| 4   | POST   | `/api/v1/orders`           | 500    | 3 100 ms     |
| 5   | GET    | `/api/v1/orders/undefined` | 404    | 90 ms        |

Nechta bug bor, ular qaysi qatlamda?

<details>
<summary>💡 Javobni ko'rish</summary>

Ikkita alohida bug:

1. **Back-end:** `POST /api/v1/orders` → `500` va 3,1 soniya. Bug report'ga Payload, Response, `X-Request-ID` va vaqtni qo'shing.
2. **Front-end:** xatodan keyin ilova to'xtamagan va `undefined` ID bilan buyurtmani so'ragan (`/orders/undefined`). Front-end xato javobni ushlamayapti — foydalanuvchiga tushunarli xabar ko'rsatish o'rniga mavjud bo'lmagan buyurtmani ochmoqchi bo'lgan.

`app.3f9a1c.js` ning `disk cache` dan kelgani — normal (nomida hash bor, deploy'da nom o'zgaradi).

</details>

### Mashq 6: DevTools bilan saucedemo holatini tekshiring

`https://www.saucedemo.com` ga `standard_user` / `secret_sauce` bilan kiring, 2 ta mahsulot qo'shing. DevTools → Application'da cookie va localStorage kalitlarini toping. So'ng `cart-contents` kalitini o'chirib, sahifani yangilang. Nima kuzatdingiz? Kuzatuvni qisqa "topilma" sifatida yozing.

<details>
<summary>💡 Javobni ko'rish</summary>

- Cookie: `session-username = standard_user` (`HttpOnly` va `Secure` yo'q, `SameSite=Lax`, taxminan 10 daqiqa yashaydi).
- Local Storage: `cart-contents` (masalan, `[4,0]`) — savatcha brauzerda saqlanadi.
- `cart-contents` o'chirilib, sahifa yangilangach savatcha belgisi yo'qoladi — server tomonda savatcha yo'q.

Topilma namunasi: _"Savatcha faqat localStorage'da saqlanadi: boshqa brauzer yoki qurilmada savatcha bo'sh. Agar talabda savatcha sinxronizatsiyasi bo'lsa — bug, bo'lmasa — product owner bilan muhokama qilinadigan risk. Qo'shimcha: sessiya cookie'si `HttpOnly` emas (demo ilova, real loyihada xavfsizlik topilmasi bo'lardi)."_

</details>

---

## Xulosa {#xulosa}

- So'rov yo'li: DNS → TCP → TLS → HTTP so'rov → server (+DB) → javob → render. Har bosqich o'z bug'iga ega va `curl -w` yoki DevTools Timing bilan o'lchanadi.
- URL qismlari (ayniqsa query) — eng arzon va samarali test maydoni; fragment serverga yuborilmaydi.
- HTTP stateless; holat cookie va brauzer xotirasida yashaydi. Auth cookie'si uchun `HttpOnly; Secure; SameSite` uchligini tekshiring.
- Kesh tezlik beradi, lekin eski fayl, eski narx va eng xavflisi — begona shaxsiy ma'lumot kabi bug'larga olib keladi.
- CORS — faqat brauzer qoidasi: "Postman'da ishlaydi, saytda yo'q" ko'pincha shu.
- Bug'ni lokalizatsiya qilishda avval Network: so'rov ketdimi → to'g'rimi → status → javob → UI.
- DevTools'dagi Copy as cURL, HAR (sanitized), Local overrides va throttling — har kungi QA asboblari.

**Keyingi dars:** [QA 10: API testing (1) — REST, JSON, status kodlar va Postman amaliyoti](/ios-lessons/qa-api-postman)

## Manbalar {#manbalar}

1. [MDN — An overview of HTTP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Overview)
2. [MDN — What is a URL?](https://developer.mozilla.org/en-US/docs/Learn_web_development/Howto/Web_mechanics/What_is_a_URL)
3. [MDN — HTTP response status codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status)
4. [MDN — HTTP request methods](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Methods)
5. [MDN — Evolution of HTTP](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Evolution_of_HTTP)
6. [MDN — Using HTTP cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Cookies)
7. [MDN — Set-Cookie header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Set-Cookie)
8. [MDN — Web Storage API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API)
9. [MDN — Window: sessionStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage)
10. [MDN — IndexedDB API](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API)
11. [MDN — HTTP caching](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Caching)
12. [MDN — Cache-Control](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Cache-Control)
13. [MDN — ETag](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/ETag)
14. [MDN — 304 Not Modified](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/304)
15. [MDN — Same-origin policy](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy)
16. [MDN — Cross-Origin Resource Sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS)
17. [MDN — Preflight request](https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request)
18. [MDN — Rendering engine](https://developer.mozilla.org/en-US/docs/Glossary/Engine/Rendering)
19. [RFC 9110 — HTTP Semantics](https://www.rfc-editor.org/rfc/rfc9110.html)
20. [RFC 9111 — HTTP Caching](https://www.rfc-editor.org/rfc/rfc9111.html)
21. [RFC 9112 — HTTP/1.1](https://www.rfc-editor.org/rfc/rfc9112.html)
22. [RFC 9113 — HTTP/2](https://www.rfc-editor.org/rfc/rfc9113.html)
23. [RFC 9114 — HTTP/3](https://www.rfc-editor.org/rfc/rfc9114.html)
24. [RFC 6265 — HTTP State Management Mechanism (cookies)](https://www.rfc-editor.org/rfc/rfc6265.html)
25. [Chrome DevTools — Inspect network activity](https://developer.chrome.com/docs/devtools/network)
26. [Chrome DevTools — Network features reference](https://developer.chrome.com/docs/devtools/network/reference)
27. [Chrome DevTools — Override web content and HTTP response headers locally](https://developer.chrome.com/docs/devtools/overrides)
28. [Chrome DevTools — Application panel](https://developer.chrome.com/docs/devtools/application)
29. [Chrome DevTools — Console](https://developer.chrome.com/docs/devtools/console)
30. [Chrome DevTools — Elements](https://developer.chrome.com/docs/devtools/elements)
31. [Chrome DevTools — Device mode](https://developer.chrome.com/docs/devtools/device-mode)
32. [Chrome DevTools — Recorder](https://developer.chrome.com/docs/devtools/recorder)
33. [Chrome DevTools — Recorder features reference](https://developer.chrome.com/docs/devtools/recorder/reference)
34. [Lighthouse overview](https://developer.chrome.com/docs/lighthouse/overview)
35. [Apple — App Store Review Guidelines (2.5.6)](https://developer.apple.com/app-store/review/guidelines/)
36. [Apple — Using alternative browser engines](https://developer.apple.com/support/alternative-browser-engines/)
37. [JSONPlaceholder — Guide](https://jsonplaceholder.typicode.com/guide/)
