tidwright ให้ AI เติม data-testid ตามมาตรฐานเดียวกันทั้งโปรเจกต์ โดยมีเครื่องมือตรวจว่าโค้ดไม่พัง แล้วให้ QA เขียน E2E บน id เหล่านั้นผ่าน getByTestId ไม่ต้องไล่อ่าน source หรือเดา CSS selector
เทียบวิธีทำงานของทีม ตอนยังไม่มีมาตรฐาน กับตอนใช้ tidwright
| เรื่อง | ไม่ใช้ | ใช้ tidwright |
|---|---|---|
| การตั้งชื่อ id | แต่ละคนตั้งเอง (btn1, submitBtn) พอ refactor test ก็พัง | grammar เดียว <area>-<element>-<type> เช่น login-submit-button และ lint บังคับให้ |
| QA หา selector | อ่าน source เอง หรือถอยไปใช้ CSS, XPath, text | อ่านรายการ e2e/TESTIDS.md ที่สร้างให้ แล้วใช้ getByTestId อย่างเดียว |
| เติม id ทั้งฟีเจอร์ | เติมมือทีละ element ไม่เคยจบ | tool เติมชุดที่ปลอดภัยให้ทีเดียว ที่เหลือ AI ตัดสินผ่าน plan ที่ตรวจแล้ว ไม่แก้ไฟล์สดๆ |
| กลัวว่าแก้แล้วพัง | ต้องอ่าน diff ทุกบรรทัดด้วยตา | ตรวจด้วย parser ของโปรเจกต์ + build/typecheck ต้องผ่านทั้งก่อนและหลัง ไม่ผ่านก็คืนไฟล์ทั้งหมด |
| id ซ้ำใน DOM | รู้ตอน test flaky หรือไม่รู้เลย | guard ใน unit test และ E2E ทำให้ test fail พร้อมบอก id กับจำนวนที่ซ้ำ |
| spec ใช้ id ที่ source ลบไปแล้ว | รู้ตอนรันพัง | /tidwright:audit จับก่อนรัน พร้อมจับ sleep, .only, credential ใน spec |
| ใครรับผิดชอบ selector | dev กับ QA เถียงกัน | เขียนเป็นสัญญา: dev เป็นเจ้าของ id, QA เป็นเจ้าของ test, auditor จับ drift |
- <button onClick={save}>Save</button> + <button data-testid="order-form-save-button" onClick={save}>Save</button> - <input name="customerName" /> + <input data-testid="order-form-customer-name-input" name="customerName" />
ผลจริงของ scan --write บนไฟล์ OrderForm.tsx (ปุ่ม Save ที่ชื่อมาจากข้อความอย่างเดียวจะถูกแค่ลิสต์ให้ review เว้นแต่ใส่ --accept-text)
ห้าขั้น และมีสองขั้นที่ต้องมีคนอนุมัติ
${key} ที่คงที่) ผ่าน plan ที่ตรวจแล้ว ก่อนเขียนต้องถามคนก่อนเสมอ--smoke จะเปิดเบราว์เซอร์เช็กว่า id ไม่ซ้ำและมีครบ ถ้าขั้นไหนที่รันแล้วพัง ไฟล์ถูกคืนทั้งหมดe2e/TESTIDS.md ให้ QA ทุกครั้งที่เขียน บอกด้วยว่า id แต่ละตัวนิยามด้วยวิธีไหนgetByTestId และ audit จับ id ที่ spec ใช้แต่ source ไม่มีแล้ว
สิ่งที่ทีมได้เพิ่มจากที่ไม่เคยมีมาก่อน
รายการ type ปิด (button input select row modal toast page…) ห้ามคำเลื่อนลอยอย่าง btn div red และห้ามเลขลอย (ใช้ business id แทน)
recipe modal orders-delete บอกชุด id ที่ modal/table/form/tabs/toast ควรมี ไม่ต้องคิดใหม่ทุกหน้า
modal(page,"orders-delete").confirm และ table(page,"orders").row(id) ตรงกับสูตร
template สำหรับ vitest/jest และ Playwright fixture ที่ fail เมื่อ data-testid เดียวกันอยู่ใน DOM สองที่
จับ sleep, .only, credential literal, selector แบบ CSS/XPath/text และ id ที่ source ไม่มี
template playwright.config.ts ปฏิเสธ host ที่ไม่ใช่ local เว้นแต่อยู่ใน allow list กันเผลอรันกับ production
<area>-<element>-<type> · kebab-case ASCII · ส่วนท้ายเป็น type จากรายการปิด · แต่ละ id นิยามครั้งเดียว (id แบบ dynamic ก็นับ)
| Component | id ที่ควรมี (<n> = ชื่อที่ตั้ง) |
|---|---|
| modal / drawer | <n>-modal · -title-text · -close-button · -confirm-button · -cancel-button · -error-banner |
| form + field | <n>-form · -submit-button · <form>-<field>-input · …-error |
| table | <n>-table · -row-${id} · -cell-${id}-${col} · -sort-button-${col} · -empty · -loading · -error |
| tabs · menu · pagination · toast | <n>-tab-${key} / -panel-${key} · -trigger-button / -item-${key} · -prev-button / -next-button · <action>-success-toast |
scan อ่านอย่างเดียว ต้องมี --write และ AI ต้องโชว์ dry run แล้วถามก่อน ไฟล์ที่มีการแก้ค้างใน git ถูกข้าม
เติมเฉพาะ native element ที่ชื่อเชื่อถือได้ ไม่ซ้ำ ไม่มี spread และ render ออกมาจริง ที่เหลือลิสต์พร้อมเหตุผล
ใช้ parser ของโปรเจกต์เอง (TypeScript, Vue, Svelte, Angular, parse5) string, regex หรือ comment จึงไม่ถูกเข้าใจผิดเป็น element ไม่มี parser = แค่ลิสต์ ไม่เขียน
--write บังคับ --verify ต้องผ่านทั้งก่อนและหลัง ถ้าไม่ได้รัน browser check รายงานจะบอกชัดว่า NOT run
คำสั่ง verify ที่มาจากไฟล์ใน repo อย่างเดียวจะไม่ถูกรันจนกว่าคนอนุมัติ
lint --write-baseline ยอมรับปัญหาที่มีอยู่ แล้ว CI ล้มเฉพาะปัญหาใหม่
รันซ้ำได้ด้วย node tools/corpus-check.mjs บน open-source app 9 ตัวที่ pin commit ไว้ (RealWorld Conduit ใน Vue / SvelteKit / Angular / React, elk, ngx-admin, shadcn-svelte, excalidraw, vercel/commerce)
--verify ในโปรเจกต์จริง)--writeAGENTS.md แต่ยังไม่เคยทดสอบใน Codex หรือ Cursor จริงขั้นตอนติดตั้งทั้ง Claude Code, Codex และ Cursor อยู่ใน README ของ repo (ขอ URL ของ repo จากทีม)
/plugin install tidwright@tidwright-marketplace # Claude Code /tidwright:init # ค้นหา repo → เขียน profile → scaffold (ต้องอนุมัติ) /tidwright:testid src/features/orders # เติม id ให้หนึ่งฟีเจอร์ แล้วสร้าง catalog /tidwright:audit # ตรวจ spec