React testing-library 基本使用

使用create react app創建專案的時候,你會發現它自動幫你安裝好testing-library的一些套件。

{
  "dependencies": {
    //...
    "@testing-library/jest-dom": "^5.11.4",
    "@testing-library/react": "^11.1.0",
    "@testing-library/user-event": "^12.1.10",
}

因為我有使用craco,所以指令部分他也有幫你寫好script

{
  "scripts": {
    //...
    "test": "craco test"
  }
}

/src資料夾中會看到跟測試有關的兩個檔案:

// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import "@testing-library/jest-dom";
import { render, screen } from '@testing-library/react';
import App from './App';
test('renders learn react link', () => {
  render(<App />);
  const linkElement = screen.getByText(/learn react/i);
  expect(linkElement).toBeInTheDocument();
});

 

首先在create react app創建專案完成的情況下,直接跑:

$ yarn test

 

你可能會遇到一些錯誤,以下是我遇到的幾個:

1. 如果有使用alias,會找不到相關路徑:

Cannot find module '@/XXX/XXX' from 'src/App.js'

要把jestmoduleNameMapper設定加上去。

像我是在craco.config.js中有加入alias,名稱叫做@

const path = require("path");

module.exports = {
  //...
  webpack: {
    alias: {
      "@": path.resolve(__dirname, "src/"),
    },
  },
};

所以在jest設定中也要叫做@

{
  //...
  "jest": {
    "moduleNameMapper": {
      "^@/(.+)": "<rootDir>/src/$1"
    }
  },
}

 

2. 找不到matchMedia

這時候在setupTests.js加入以下這段:

import "@testing-library/jest-dom";
window.matchMedia = query => ({
  matches: false,
  media: query,
  onchange: null,
  addListener: jest.fn(), // deprecated
  removeListener: jest.fn(), // deprecated
  addEventListener: jest.fn(),
  removeEventListener: jest.fn(),
  dispatchEvent: jest.fn(),
});

 

3. App.test.js測試失敗

因為一開始create react app時,App.js的內容是預設的,裡面有react logo、一些預設文字。

App.test.js中的測試項目也是以預設的內容來測,當我們有改動App.js的內容,自然就會測試失敗拉!

import { render, screen } from "@testing-library/react";
import App from "./App";

test("renders learn react link", () => {
  render(<App />);
  const linkElement = screen.getByText(/learn react/i); // <-- 因為我App.js裡面已經沒有 "learn react"文字了,所以失敗。
  expect(linkElement).toBeInTheDocument();
});

可以把他先簡易改成render就好:

import App from "./App";
import ReactDOM from "react-dom";

it("renders without crashing", () => {
  const div = document.createElement("div");
  ReactDOM.render(<App />, div);
});

接下來我們可以試著針對function來進行測試:

我在/utils資料夾中放有許多工具,例如日期formate、價錢format之類的,這邊先選一個來進行測試。

src/
- utils/
-- format.js
-- format.test.js //<--同層下新增測試檔案
export const dateFormat = date => {
  return moment(date).isValid() && typeof date === "string"
    ? moment(date).format("YYYY-MM-DD HH:mm:ss")
    : "is not valid date";
};

 

 

現在正式要來寫測試囉!

import { dateFormat } from "./format";

describe("format functions", () => {
  test("dateFormat", () => {
    expect(dateFormat("2021-07-07T00:00:00+08:00")).toBe(`2021-07-07 00:00:00`);
  });
});

先引入我寫好的function

我預期我收到資料庫傳來的日期格式,我要轉換成一般人習慣閱讀的格式。

再次跑測試

$ yarn test

這時會看到這時會看到Test Suites有2個、Tests有兩個。

  • Test Suites:表示我有兩隻xxx.test.js檔案
  • Tests:表示我有兩個測試(每個檔案裡各一個測試)

因為測試就是要確保各種可能性,所以通常expect不會只寫一種。

import { dateFormat } from "./format";

describe("format functions", () => {
  test("dateFormat", () => {
    expect(dateFormat("2021-07-07T00:00:00+08:00")).toBe(`2021-07-07 00:00:00`);
    expect(dateFormat(null)).toBe(`is not valid date`);
    expect(dateFormat(123)).toBe(`is not valid date`);
  });
});

再來因為format.js中還有很多其他function,也可以寫在一起。

import { priceFormat, dateFormat } from "./format";

describe("format functions", () => {
  test("priceFormat", () => {
    expect(priceFormat({ val: 200, currency: 0 })).toBe(`¥ 2`);
  });
  test("dateFormat", () => {
    expect(dateFormat("2021-07-07T00:00:00+08:00")).toBe(`2021-07-07 00:00:00`);
    expect(dateFormat(null)).toBe(`is not valid date`);
    expect(dateFormat(123)).toBe(`is not valid date`);
  });
});

這樣就是最簡的最基本的測試流程拉!

學習程式原來可以這麼簡單:六角學院線上課程

初學者如何成為vue前端工程師:查看課程內容

---------------------------

| 軟體開發 | 網站建置 | 網頁系統 | 資料庫網站 |

| 客製化網站 (報名系統、投票系統、掛號系統...) |

| 前後端技術合作 |

歡迎與我們聯繫:jessica@penueling.com

加入Line立即聊聊:@539mjyid

0
0 回復

發表評論

Want to join the discussion?
Feel free to contribute!

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。