Reference

Glossary, HTTP codes, SQL, Postman และ Playwright cheatsheet

ไม่พบคำที่ค้นหา
2xx Success
Code
ชื่อ
ความหมาย / เจอเมื่อไหร่
200
OK
Request สำเร็จ — GET/PUT/PATCH ที่ได้ผลลัพธ์
201
Created
POST สร้างข้อมูลใหม่สำเร็จ — มักมี Location header ชี้ไปที่ resource ใหม่
202
Accepted
Request รับแล้ว แต่ยังไม่ process เสร็จ (async job)
204
No Content
สำเร็จแต่ไม่มี response body — DELETE ที่สำเร็จมักได้ 204
3xx Redirection
Code
ชื่อ
ความหมาย / เจอเมื่อไหร่
301
Moved Permanently
URL เปลี่ยนถาวร browser จะ cache และ redirect ทุกครั้ง
302
Found
Redirect ชั่วคราว ใช้บ่อยหลัง login สำเร็จ
304
Not Modified
Content ไม่เปลี่ยน ให้ใช้ cache — ประหยัด bandwidth
4xx Client Error
Code
ชื่อ
ความหมาย / เจอเมื่อไหร่
400
Bad Request
Request format ผิด เช่น JSON malformed, missing required field
401
Unauthorized
ยังไม่ authenticate หรือ token ไม่ถูกต้อง/หมดอายุ
403
Forbidden
Authenticate แล้วแต่ไม่มีสิทธิ์ทำ action นั้น (role ไม่พอ)
404
Not Found
ไม่พบ resource — URL ผิดหรือ ID ไม่มีในระบบ
405
Method Not Allowed
Endpoint มีอยู่แต่ไม่รองรับ HTTP method ที่ส่งมา
409
Conflict
ข้อมูลซ้ำหรือ conflict เช่น email ซ้ำ, version conflict
410
Gone
Resource เคยมีแต่ถูกลบถาวรแล้ว (ต่างจาก 404 ที่อาจเคยมีหรือไม่มี)
422
Unprocessable
Request format ถูกแต่ข้อมูลไม่ผ่าน validation (email format ผิด, ค่าเกิน range)
429
Too Many Requests
ส่ง request เกิน rate limit — ต้อง retry หลัง delay
5xx Server Error
Code
ชื่อ
ความหมาย / เจอเมื่อไหร่
500
Internal Server Error
Server error ทั่วไป — ดู server log เพื่อหา root cause
501
Not Implemented
Server ยังไม่รองรับ feature ที่ request มา
502
Bad Gateway
Proxy/load balancer ไม่ได้รับ response ที่ถูกต้องจาก upstream
503
Service Unavailable
Server ไม่พร้อมให้บริการ — maintenance หรือ overloaded
504
Gateway Timeout
Proxy รอ upstream นานเกินไป — ตรวจสอบ slow query/process
🔍 SELECT Queries ที่ QA ใช้บ่อย
-- ดูข้อมูล user ทั้งหมด
SELECT * FROM users LIMIT 20;

-- หา user ด้วย email
SELECT id, name, email, created_at
FROM users
WHERE email = 'test@example.com';

-- เช็กว่า record มีอยู่จริง
SELECT COUNT(*) as total FROM orders WHERE user_id = 42;

-- ดู order ล่าสุด
SELECT * FROM orders
ORDER BY created_at DESC
LIMIT 10;

-- JOIN: order พร้อมชื่อ user
SELECT o.id, u.name, u.email, o.total, o.status
FROM orders o
JOIN users u ON o.user_id = u.id
WHERE o.status = 'pending'
ORDER BY o.created_at DESC;

-- หาซ้ำ: email ซ้ำกัน
SELECT email, COUNT(*) as cnt
FROM users
GROUP BY email
HAVING cnt > 1;

-- เช็ก record ที่ deleted ล่าสุด
SELECT * FROM audit_logs
WHERE action = 'DELETE'
AND table_name = 'products'
ORDER BY created_at DESC
LIMIT 5;
📋 SQL Clauses Quick Reference
SELECT col1, col2
เลือก column ที่ต้องการ (* = ทั้งหมด)
FROM table
ระบุตาราง
WHERE condition
กรองแถว: =, !=, >, <, LIKE, IN, BETWEEN, IS NULL
JOIN t2 ON t1.id = t2.fk
เชื่อม 2 ตาราง (INNER=ตรงกัน, LEFT=ซ้ายทั้งหมด)
ORDER BY col DESC
เรียงลำดับ (ASC=น้อยไปมาก, DESC=มากไปน้อย)
LIMIT n
จำกัดจำนวนแถว
GROUP BY col
จัดกลุ่มเพื่อใช้กับ aggregate function
HAVING condition
กรอง group (ใช้แทน WHERE หลัง GROUP BY)
COUNT(*)
นับแถว
SUM / AVG / MAX / MIN
aggregate functions
LIKE '%text%'
ค้นหาข้อความ (% = wildcard)
IS NULL / IS NOT NULL
เช็ก null value
📮 Postman Test Snippets
// ── Status Code ─────────────────────────────
pm.test("Status is 200", () => {
    pm.response.to.have.status(200);
});

// ── Response Time ────────────────────────────
pm.test("ตอบสนองภายใน 1000ms", () => {
    pm.expect(pm.response.responseTime).to.be.below(1000);
});

// ── Response Body ────────────────────────────
pm.test("มี id ใน response", () => {
    const json = pm.response.json();
    pm.expect(json.id).to.exist;
    pm.expect(json.id).to.be.a('number');
});

pm.test("token เป็น string ไม่ว่าง", () => {
    const json = pm.response.json();
    pm.expect(json.token).to.be.a('string').and.not.empty;
});

pm.test("items เป็น array", () => {
    const json = pm.response.json();
    pm.expect(json.items).to.be.an('array');
    pm.expect(json.items.length).to.be.above(0);
});

// ── Header ───────────────────────────────────
pm.test("Content-Type เป็น JSON", () => {
    pm.expect(pm.response.headers.get('Content-Type'))
        .to.include('application/json');
});

// ── Set Environment Variable ─────────────────
const json = pm.response.json();
pm.environment.set("token", json.token);
pm.environment.set("userId", json.id);

// ── Get Environment Variable ─────────────────
const baseUrl = pm.environment.get("base_url");

// ── Request body helper ──────────────────────
// ใช้ {{variable}} ใน Body:
// { "email": "{{email}}", "token": "{{token}}" }
⌨️ Postman Keyboard Shortcuts
Ctrl + Enter
Send request
Ctrl + S
Save request
Ctrl + /
Comment/uncomment ใน script
Ctrl + B
Toggle sidebar
Ctrl + Alt + C
Open console
Ctrl + T
New tab
🔗 Pre-request Script — Login แล้วเอา Token
// วางใน Pre-request Script ของ Collection
// เพื่อ auto-refresh token ก่อนทุก request

const token = pm.environment.get("token");
if (!token) {
    pm.sendRequest({
        url: pm.environment.get("base_url") + "/auth/login",
        method: "POST",
        header: { "Content-Type": "application/json" },
        body: {
            mode: "raw",
            raw: JSON.stringify({
                email: pm.environment.get("email"),
                password: pm.environment.get("password")
            })
        }
    }, (err, res) => {
        if (!err) {
            pm.environment.set("token", res.json().token);
        }
    });
}
🎭 Selectors — วิธีเลือก Element
Role (แนะนำ)
page.get_by_role("button", name="Submit")
ใช้ semantic role + name — ดีที่สุด ไม่พังเมื่อ style เปลี่ยน
Label
page.get_by_label("Email address")
ค้นหา input จาก label ที่ associate — accessible
Placeholder
page.get_by_placeholder("กรอก email")
ค้นหาจาก placeholder attribute
Text
page.get_by_text("ยืนยัน")
ค้นหา element ที่มีข้อความนั้น
Test ID
page.get_by_test_id("submit-btn")
ใช้ data-testid attribute — ดีสำหรับ production code
CSS Selector
page.locator("#email-input")
page.locator(".btn-primary")
ใช้เมื่อ locator อื่นใช้ไม่ได้ — fragile เมื่อ CSS เปลี่ยน
nth / Filter
page.locator("li").nth(0)
page.locator("li").filter(has_text="Active")
เลือก element ตำแหน่งที่ n หรือกรองด้วย text
Within (chaining)
page.locator(".card").get_by_role("button")
หา button ภายใน .card เท่านั้น — scope ลง
✅ Assertions
from playwright.sync_api import expect

# ── Visibility ───────────────────────────────
expect(page.locator(".alert")).to_be_visible()
expect(page.locator(".modal")).to_be_hidden()

# ── Text content ─────────────────────────────
expect(page.locator("h1")).to_have_text("Dashboard")
expect(page.locator(".msg")).to_contain_text("สำเร็จ")

# ── Input value ──────────────────────────────
expect(page.get_by_label("Email")).to_have_value("test@x.com")

# ── URL ──────────────────────────────────────
expect(page).to_have_url("https://example.com/dashboard")
expect(page).to_have_url(re.compile(".*/dashboard"))

# ── Title ────────────────────────────────────
expect(page).to_have_title("Dashboard — MyApp")

# ── Enabled/Disabled ─────────────────────────
expect(page.locator("button[type=submit]")).to_be_enabled()
expect(page.locator("#save-btn")).to_be_disabled()

# ── Checked ──────────────────────────────────
expect(page.get_by_role("checkbox")).to_be_checked()

# ── Count ────────────────────────────────────
expect(page.locator("tr")).to_have_count(10)
⚡ Actions ที่ใช้บ่อย
# ── Navigation ──────────────────────────────
page.goto("https://example.com")
page.go_back()
page.reload()

# ── Input ────────────────────────────────────
page.get_by_label("Email").fill("test@x.com")
page.get_by_label("Email").clear()
page.get_by_label("Message").type("สวัสดี", delay=50)

# ── Click ────────────────────────────────────
page.get_by_role("button", name="Submit").click()
page.locator(".dropdown").click()
page.locator("text=เลือก").dblclick()

# ── Select / Checkbox ────────────────────────
page.get_by_label("Country").select_option("TH")
page.get_by_role("checkbox").check()
page.get_by_role("checkbox").uncheck()

# ── Wait ─────────────────────────────────────
page.wait_for_url("**/success")
page.wait_for_selector(".loading", state="hidden")
page.locator(".result").wait_for()

# ── Screenshot ───────────────────────────────
page.screenshot(path="screenshot.png", full_page=True)
page.locator(".chart").screenshot(path="chart.png")

# ── Network interception ─────────────────────
page.route("**/api/users", lambda route: route.fulfill(
    status=200,
    body='[{"id":1,"name":"Mock User"}]'
))

# ── Keyboard ─────────────────────────────────
page.keyboard.press("Enter")
page.keyboard.press("Control+A")

# ── Hover ────────────────────────────────────
page.locator(".menu-item").hover()