ค้นหาเว็บไซต์

reactjs - วิธีใช้ฟังก์ชันที่ประกาศใน context provider ในการทดสอบ react?


ฉันกำลังพยายามทดสอบฟังก์ชัน showModal ที่ฉันประกาศใน context provider:

export const ModalProvider = ({ children }: ProviderProps) => {
    const [isOpen, setIsOpen] = useState<boolean>(false);
    const [titleText, setTitleText] = useState<string>('');
    const [contentText, setContentText] = useState<string>('');
    const [hideCloseButton, setHideCloseButton] = useState<boolean>(false);

    const showModal: ShowModalProps = useCallback((title, content, hideCloseButton) => {
        setIsOpen(true);
        setTitleText(title);
        setContentText(content);
        setHideCloseButton(hideCloseButton);
    }, []);

    const closeModal = () => {
        setIsOpen(false);
    };
    return (
        <ModalContext.Provider
            value={{
                isOpen,
                setIsOpen,
                showModal,
                closeModal,
                titleText,
                contentText,
                hideCloseButton
            }}
        >
            {children}
        </ModalContext.Provider>
    );
};

ตอนนี้ฉันต้องการทดสอบฟังก์ชันนี้

describe('Modal testing', () => {
   it(`Should render popup modal`, () => {

    render(
        <ModalProvider>
            <HomePage />
        </ModalProvider>
    );
    showModal('TEST', 'TEST Text', false);
    const errorMessage = screen.getByText('TEST Text');
    expect(errorMessage).toBeDefined();
});

});

ฉันได้รับข้อผิดพลาดว่า showModal ไม่ได้ถูกกำหนด แต่ฉันได้ห่อหน้าด้วย provider แล้ว ดังนั้นฉันไม่แน่ใจว่าจะเข้าถึงฟังก์ชันนี้และเรียกใช้งานในทดสอบได้อย่างไร

คำตอบ #1

เราควรทดสอบพฤติกรรมของคอมโพเนนต์ ModalProvider ในการทดสอบ เราจำเป็นต้องมีคอมโพเนนต์ทดสอบเพื่อใช้ค่าจาก context

ฉันใช้องค์ประกอบกล่องโต้ตอบ HTML เป็นกิริยาช่วย

เราจำเป็นต้องหาปุ่ม "show modal" และเรียกเหตุการณ์คลิกบนมัน ตัวจัดการคลิกจะเรียกฟังก์ชัน showModal จากค่า context หลังจากสถานะเปลี่ยนแปลง ModalProvider และคอมโพเนนต์ children จะทำการเรนเดอร์ใหม่ ตอนนี้เราสามารถตรวจสอบว่า dialog อยู่ในเอกสาร(หน้าจอ) หรือไม่ หากมันอยู่ในเอกสาร เราสามารถตรวจสอบหัวข้อและเนื้อหาของมันได้

เช่น

index.tsx:

import React, { useCallback, useState } from "react";

export interface ModalContextType {
  isOpen: boolean;
  setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
  showModal: (title: string, content: string, hideCloseButton: boolean) => void;
  closeModal: () => void;
  titleText: string;
  contentText: string;
  hideCloseButton: boolean;
}

export const ModalContext = React.createContext<ModalContextType>({} as ModalContextType)

export const ModalProvider = ({ children }) => {
  const [isOpen, setIsOpen] = useState<boolean>(false);
  const [titleText, setTitleText] = useState<string>('');
  const [contentText, setContentText] = useState<string>('');
  const [hideCloseButton, setHideCloseButton] = useState<boolean>(false);

  const showModal = useCallback((title, content, hideCloseButton) => {
    setIsOpen(true);
    setTitleText(title);
    setContentText(content);
    setHideCloseButton(hideCloseButton);
  }, []);

  const closeModal = () => {
    setIsOpen(false);
  };
  return (
    <ModalContext.Provider
      value={{
        isOpen,
        setIsOpen,
        showModal,
        closeModal,
        titleText,
        contentText,
        hideCloseButton
      }}
    >
      {children}
    </ModalContext.Provider>
  );
};

index.test.tsx:

import { render, fireEvent, screen } from "@testing-library/react"
import '@testing-library/jest-dom';
import React from "react"
import { useContext } from "react"
import { ModalContext, ModalProvider } from "."

describe('74101831', () => {
  test('should pass', () => {
    const TestComp = () => {
      const { isOpen, titleText, contentText, hideCloseButton, showModal } = useContext(ModalContext);

      return <div>
        <dialog open={isOpen} title={titleText} >
          <div>{contentText}</div>
          {!hideCloseButton && <button>close</button>}
        </dialog>

        <button onClick={() => showModal('dialog title', 'dialog content', false)}>show modal</button>
      </div>
    }

    render(<ModalProvider><TestComp /></ModalProvider>);

    fireEvent.click(screen.getByRole('button', { name: 'show modal' }));

    expect(screen.getByRole('dialog')).toBeInTheDocument();
    expect(screen.getByRole('dialog')).toHaveAttribute('title', 'dialog title');
    expect(screen.getByRole('dialog')).toHaveAttribute('open');
    expect(screen.getByRole('button', { name: 'close' })).toBeInTheDocument();
    expect(screen.getByText('dialog content')).toBeInTheDocument();
  });
});

ผลการทดสอบ:

 PASS  stackoverflow/74101831/index.test.tsx (11.102 s)
  74101831
    ✓ should pass (142 ms)

-----------|---------|----------|---------|---------|-------------------
File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-----------|---------|----------|---------|---------|-------------------
All files  |   93.75 |      100 |   66.67 |   93.33 |                   
 index.tsx |   93.75 |      100 |   66.67 |   93.33 | 29                
-----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        11.656 s

เวอร์ชันของแพ็กเกจ:

"@testing-library/react": "^11.2.7",
"@testing-library/jest-dom": "^5.11.6",
"jest": "^26.6.3",
"react": "^16.14.0",
"react-dom": "^16.14.0",