เวลาที่เราใช้ NextJS บ่อยครั้งที่จะต้องมีการใช้ useRouter ที่เป็นของ next/navigation
เพื่อทำอะไรบ้างอย่าง
ทีนี้เมื่อเราต้องการเขียน component testing เพื่อที่ทดสอบ component ที่มี useRouter ประกอบอยู่ข้างในนั้นด้วยแล้ว cypress มันจะแสดงผล error ออกมาแบบนี้
ก่อนอื่นต้องทำความเข้าใจก่อนว่า library บางตัวที่เราใช้งานอยู่นั้นมันอยู่ในรูปแบบของ context ซึ่งมันจะมีองค์ประกอบ 2 ส่วนใหญ่ๆ คือ Provider กับ Consumer
useRouter ของ next/navigation ก็เป็นเช่นเดียวกัน ซึ่งปกติแล้ว nextjs มันจะ build in provider มาให้ตั้งแต่ต้นแล้ว เราจึงสามารถเรียกใช้งาน useRouter ที่เป็นตัว consumer ได้เลยทันที (หาอ่านเรื่องของ react context เพิ่มเติมได้)
ทีนี้ เมื่อเราต้องการที่จะทดสอบแค่ component ย่อยๆ มันก็เลยมีแค่การเรียกใช้ useRouter ที่เป็นตัว consumer เลยโดยที่จะยังไม่ได้ mount ตัว provider ของ next/navigation มันเลย เตือน Error นี้ขึ้นมา
การ Mock Router ขึ้นมา
โดยทั่วไปแล้ว วิธีการแก้ไข้ที่ง่ายที่สุด คือ การสร้างตัว Mock Router ของ next/navigation ขึ้นมา เพื่อให้ component ที่ต้องการทดสอบสามารถเรียกใช้งานได้
ตัวอย่าง
สมมติว่าเรามี component ที่มีการ เรียกใช้งาน useRouter เพื่อเปลี่ยนไปยังหน้า about จะได้ code ประมาณนี้ (โค๊ดตัวอย่าง ใช้ Next.js เวอร์ชั่น 14.1.0)
Component
สร้าง mock useRouter
เริ่มต้นจากไปสร้างไฟล์ router.js
ในโฟลเดอร์ cypress/utils/router.js
ซึ่งผมเลือกใช้ JavaScript แทน TypeScript จะได้ไม่ต้อง วุ่นวายกับ Type
วิธีใช้งาน
เมื่อเรามีไฟล์ mock router แล้ว เราสามารถเรียกมันมาใช้งานได้ง่าย โดยเอา MockRouter การครอบ component ที่เราต้องการทดสอบไว้
ถ้าหากเราต้องการตรวจสอบว่ามีการเรียก router.push(link)
จริงไหม สามารถทำได้โดยการใช้ @Alias
ที่กำหนดไว้ push: cy.spy().as('push')
ใน cypress/utils/router.js
เท่านี้เราก็สามารถทดสอบ component นี้ได้แล้ว