> For the complete documentation index, see [llms.txt](https://kidkung.gitbook.io/node-js/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kidkung.gitbook.io/node-js/library/jest.md).

# Jest

### install

```batch
npm install --save-dev jest @types/jest 
```

```json
#package.json
script: {
    "test": "jest --coverage",
    "test:watch": "jest --watch",
}
#jest.config.js
module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  setupFiles: ['dotenv/config'],
};
```

{% hint style="info" %}
**Report**\
ปกติเวลารันด้วย jest --coverage ก็จะมี folder ที่ชื่อ coverage ออกมาอยู่แล้วซึ่งเราจะสามารถคลิกเปิดขึ้นมาเพื่อดูเทส report ของเราได้ว่า ผ่าน/ไม่ผ่าน ไฟล์ไหนบ้าง มีโค๊ดตรงไหนไม่ได้ไช้บ้าง

จะมี plugin อีกตัวที่จะติดตั้งเพิ่มหรือไม่ติดก็ได้คือ jest-html-reporters ซึ่ง UI จะสวยกว่า แต่รายละเอียดบางอย่างก็จะไม่มี

**Install**

```batch
npm i --dev-save jest-html-reporters
#jest.config.js
...
"reporters": [
    "default",
    "jest-html-reporters"
  ],
 ...
```

{% endhint %}

โฟลเดอร์เทสเรา จะไว้ในชื่อ `__tests__` ก็ได้ หรือไว้ข้างนอกก็ได้เช่นกัน ขอแค่มีชื่อ `.spec` หรือ `.test` ต่อท้าย โดยเราสามารถตั้งชื่อได้โดยใช้ชื่อไฟล์ต่อท้าย เช่น `app.test.js` หรือ `app.spec.js`

```typescript
#app.test.js
const { getScore } = require('./app')
describe('Score', () => {
  it('should get A', () => {
    const result = getScore()
    // Assertion
    expect(result).toEqual('A')
  })
});
```

### เริ่มเขียน Test <a href="#id-3d22" id="id-3d22"></a>

#### Jest API Block Scope

> * **describe**: ใช้ระบุ test group หรือจะเรียกว่า test suite ก็ได้ครับ โดยเราอาจจะแบ่งตาม API Endpoints ก็ได้
> * **it หรือ test**: ใช้ระบุ scope ของ test ของเรานั่นเอง
> * beforeAll: ใช้ระบุ test suite setup ต่างๆ ที่จะทำก่อน 1 ครั้งเริ่ม test ทุกข้อ
> * **beforeEach**: ใช้ระบุ test case setup ที่จะทำก่อนเริ่มเทสทุกข้อ
> * **afterEach**: ใช้ระบุ test case teardown ที่จะทำหลังเทสทุกข้อ
> * **afterAll**: ใช้ระบุ test suite teardown ที่จะทำหลังจากรันเทสครบทุกข้อแล้ว 1 ครั้ง
>
> ยังมี API อื่นๆ ที่สามารถใช้งานได้ สามารถอ่านรายละเอียดเต็มๆ ได้ที่ <https://jestjs.io/docs/api> เลย

#### Mock Function

```typescript
it('should works with jest.fn() and mockResolvedValue', async () => {
  let myMock = fetchSomeData
  myMock = jest.fn()
  myMock.mockResolvedValue('success from mock data')
  await expect(myMock()).resolves.toEqual('success from mock data')
})
```

> ```typescript
> const app = {
>     fetchSomeData : ()=>{
>         return 'success'
>     }
> }
> it('spyOn and custom response', async () => { 
>     const spy = jest.spyOn(app, 'fetchSomeData').mockResolvedValue('fail')
>     const isLoggedIn = await app.login() expect(isLoggedIn).toBe(false)
>     expect(spy).toHaveBeenCalled()
>     app.fetchSomeData.mockRestore() 
> })
> ```
>
> เราทำการ mock function ขึ้นมา เพื่ออะไร เพื่อเอาไว้เทส function โดยที่เราอยากเปลี่ยนแปลงค่าของ function ที่เราต้องการ เช่น fetchSomeData() function จริงๆ มัน return success เราอยากจะเปลี่ยนเป็น error เป็น hello world หรืออื่นๆ เพื่อเทส เราก็ใช้ mock ได้ โดยไม่จำเป็นต้องแก้ไขโค๊ดเรา
>
> * jest.fn() : mock function
>   * สั่งให้ mock function return กลับมาเป็น "hello world"
>
>     jest.fn().mockReturnValue('hello world')
>   * สั่งให้ mock function return กลับมาเป็น Promise("hello world")
>
>     jest.fn().mockResolvedValue('hello world')
> * jest.spyOn(\[object], \["function mane"]) : คล้ายๆกับ mock function ด้วย jest.fn() แต่สามารถ tracking object ได้ รวมถึง restore mock หรือกลับไปใช้ function จริงที่ไม่ได้ mock ได้&#x20;
>
>   * spy function 'fetchSomeData' และ return 'fail'
>     * jest.spyOn(app, 'fetchSomeData').mockResolvedValue('fail')
>   * .toHaveBennCalled()&#x20;
>     * เช็คว่า spy function ของเราถูกเรียกรึป่าว
>       * const spy = jest.spyOn(app, 'fetchSomeData').mockResolvedValue('fail')
>
>         expect(spy).toHaveBeenCalled()
>
>   อ่านเพิ่มเติมได้ที่ <https://jestjs.io/docs/mock-functions>

{% embed url="<https://www.devahoy.com/blog/2019/08/getting-started-with-testing-and-jest>" %}
อ่านเพิ่มเติม
{% endembed %}

{% embed url="<https://nottyo.medium.com/%E0%B8%A1%E0%B8%B2%E0%B8%97%E0%B8%B3-api-testing-%E0%B8%94%E0%B9%89%E0%B8%A7%E0%B8%A2-jest-supertest-%E0%B8%A3%E0%B8%B1%E0%B8%99%E0%B9%80%E0%B8%A3%E0%B9%87%E0%B8%A7%E0%B9%81%E0%B8%A3%E0%B8%87%E0%B9%81%E0%B8%9A%E0%B8%9A-fast-furious-%E0%B8%81%E0%B8%B1%E0%B8%99-b4336b76aeba>" %}
อ่านเพิ่มเติม
{% endembed %}
