ทดสอบ React ด้วย react-testing-library ด้วย TypeScript (หรือ JS ก็ได้นะ)

วันหยุดสัปดาห์นี้ระหว่างที่ลองทำ side-project ต้องเขียน React Component ก็เลยอยากจะลองเทสต์ React Component ด้วยอะไรสักอย่างที่ไม่ได้ใช้ประจำ ซึ่งวันนี้ได้ลองใช้งาน react-testing-library ที่มีกลิ่นอายของ selenium นิดๆ รู้สึกว่ากลมกล่อมดี เลยเอามาแชร์ (เสี่ยงใช้ใน Production เอาเองนะครับ :P )

เริ่มต้นใช้งาน
ถ้าไม่ได้ใช้ Create React App ในการสร้าง project อาจจะต้องเริ่มจากเพิ่ม dev dependency เข้าไป

npm install jest babel-jest --save-dev

หลังจากนั้นก็เพิ่ม react-testing-library เข้าไป

npm install @testing-library/react jest-dom jest-extended --save-dev

โดยสิ่งที่เราต้องการจาก jest-extend และ jest-dom ก็คือ extend-expect ที่จะใช้ในการตรวจสอบ react component ในการ test นั้นเอง โดยเราจะเริ่มจากสร้างไฟล์ที่ใช้ในการ setup test แต่ละเทสต์ก่อน โดนเราอาจจะสร้างไฟล์แยกขึ้นมา สมมติชื่อ setupTest.ts ซึ่งเราจะทำการติดตั้ง library ที่เราต้องการในเฟส setupFilesAfterEnv (เดิมเป็นเฟส setupTestFrameworkScriptFile)

“jest”: {
    “setupFilesAfterEnv”: [“<rootDir>/src/setupTests.ts”],
}

โดยในไฟล์ setupTest.ts นั้นเราก็จะทำการ import test utility ขึ้นมาทันทีหลัง jest framework โหลดขึ้นมา

import "jest-extended";
import "jest-dom/extend-expect";
import "@testing-library/react/cleanup-after-each";

โดยใน cleanup-after-each ก็จะทำงานเหมือน afterEach(cleanup) นั่นเอง เท่านี้หลังจากเทสแต่ละเคสเสร็จ jest ก็จะ unmount/release react component ที่ใช้ในแต่ละเทสอัตโนมัติ

ด้วยความที่ react-testing-library นั้นจะใช้ matcher ที่ extend จาก custom matcher (เช่น jest-dom) ในการเทส เราจึงสามารถใช้ custom matcher ที่เพิ่มมาใน jest-dom ได้เลยเช่น toHaveStyle, toHaveTextContent, toBeVisible

const { container } = render(<App />);
expect(container).toHaveStyle('color: red;');

เรายังสามารถใช้ event เพื่อช่วยในการทดสอบ เช่น ใช้ fireEvent ในการ trigger อีเวนต์ หรือจำลอง user interaction หรือใช้ waitForElement เพื่อรอให้ component แสดงขึ้นมา

const toggleButton = getByTestId("toggle-input");
expect(container).toHaveTextContent(/the button is off/i);

fireEvent.click(toggleButton);
expect(toggleButton).toSatisfy(button => button.checked);

การทำ snapshot test นั้นก็สามารถทำได้ง่ายๆ เหมือนเดิมโดยเรียกใช้เมธอด expect(container).toMatchSnapshot() ในการทดสอบกับ snapshot
ซึ่งจะเห็นว่าเทสที่ใช้ jest + react-testing library นี้จะมีความสามารถเหมือนกับ jest แต่มีกลิ่นของ selenium ติดมาพอสมควร สำหรับผมแล้วมันทำให้เราสามารถ test กับ React component ได้ง่ายขึ้น หวังว่าจะเป็นประโยชน์นะครับ

Happy Coding !!

Reference:
https://github.com/testing-library/react-testing-library