# 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 %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://kidkung.gitbook.io/node-js/library/jest.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
