【问题标题】:How to write test with swr如何使用 swr 编写测试
【发布时间】:2021-08-29 16:22:45
【问题描述】:

当用户在输入搜索中键入一些文本时 data-testid = 'loading' 必须被删除,现在控制台返回 Unable to find an element by: [data-testid="loading"] 有人可以建议我用 swr 编写测试或建议我如何模拟 swr 的响应

这是我的组件文件

import axios from "axios";
import { useEffect, useState } from "react";
import useSWR from "swr";
import "./styles.css";

const useDebounce = (newValue) => {
  const [value, setValue] = useState("");
  useEffect(() => {
    const timeout = setTimeout(() => {
      setValue(newValue);
    }, 500);
    return () => clearTimeout(timeout);
  }, [newValue]);
  return value;
};

export const fetcher = async (url) => {
  const { data } = await axios.get(url);
  return data;
};
export default function App() {
  const [query, setQuery] = useState("react");
  const searchQuery = useDebounce(query);
  const { data: repos } = useSWR(
    `https://api.github.com/search/repositories?q=${searchQuery}&per_page=1&page=1`,
    fetcher
  );
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <input
        testId="search"
        data-testid="search"
        id="search-input"
        placeholder="search"
        onChange={(event) => setQuery(event.target.value)}
      />
      {!repos ? (
        <div data-testid="loader" testId="loader">
          <h2 id="loading">loading</h2>
        </div>
      ) : (
        repos?.items?.map((user) => {
          return (
            <div
              data-testid="repo-item"
              style={{
                margin: "1rem",
                height: "40px",
                background: "lightpink"
              }}
            >
              {user.name}
            </div>
          );
        })
      )}
    </div>
  );
}

这是我的测试文件

import {
  render,
  screen,
  waitForElementToBeRemoved
} from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import App from "./App";
import { act } from "react-dom/test-utils";

describe("test", () => {
  beforeEach(() => {
    jest.resetAllMocks();
    jest.useFakeTimers();
  });
  it("happy render", () => {
    expect(() => render(<App />)).not.toThrow();
  });

  it("renders after search", async () => {
    render(<App />);
    userEvent.type(screen.getByTestId("search"), "vue");
    act(() => {
      jest.runAllTimers();
    });
    await waitForElementToBeRemoved(() => screen.getByTestId("loader"));
  });
});

【问题讨论】:

    标签: reactjs jestjs react-hooks react-testing-library swr


    【解决方案1】:

    您可以模拟 axios.get() 方法及其解析/拒绝值,而不是模拟 useSWR 钩子。然后,测试组件的行为,比如返回数据时渲染了什么,没有数据时渲染了什么。

    例如

    App.tsx:

    import axios from 'axios';
    import React from 'react';
    import { useEffect, useState } from 'react';
    import useSWR from 'swr';
    
    const useDebounce = (newValue) => {
      const [value, setValue] = useState('');
      useEffect(() => {
        const timeout = setTimeout(() => {
          setValue(newValue);
        }, 500);
        return () => clearTimeout(timeout);
      }, [newValue]);
      return value;
    };
    
    export const fetcher = async (url) => {
      const { data } = await axios.get(url);
      return data;
    };
    
    export default function App() {
      const [query, setQuery] = useState('react');
      const searchQuery = useDebounce(query);
      const { data: repos } = useSWR(
        `https://api.github.com/search/repositories?q=${searchQuery}&per_page=1&page=1`,
        fetcher
      );
      return (
        <div className="App">
          <h1>Hello CodeSandbox</h1>
          <h2>Start editing to see some magic happen!</h2>
          <input
            data-testid="search"
            id="search-input"
            placeholder="search"
            onChange={(event) => setQuery(event.target.value)}
          />
          {!repos ? (
            <div data-testid="loader">
              <h2 id="loading">loading</h2>
            </div>
          ) : (
            repos?.items?.map((user) => {
              console.log('user: ', user);
              return (
                <div key={user.id} data-testid="repo-item">
                  {user.name}
                </div>
              );
            })
          )}
        </div>
      );
    }
    

    App.test.tsx:

    import React from 'react';
    import { render, screen, waitForElementToBeRemoved } from '@testing-library/react';
    import userEvent from '@testing-library/user-event';
    import App from './App';
    import { act } from 'react-dom/test-utils';
    import axios from 'axios';
    
    describe('test', () => {
      beforeEach(() => {
        jest.clearAllMocks();
        jest.useFakeTimers();
      });
      it('happy render', () => {
        expect(() => render(<App />)).not.toThrow();
      });
    
      it('renders after search', async () => {
        jest.spyOn(axios, 'get').mockResolvedValueOnce({
          data: {
            items: [
              { id: 1, name: 'react' },
              { id: 2, name: 'jestjs' },
            ],
          },
        });
        render(<App />);
        userEvent.type(screen.getByTestId('search'), 'vue');
        act(() => {
          jest.runAllTimers();
        });
        await waitForElementToBeRemoved(() => screen.getByTestId('loader'));
      });
    });
    

    测试结果:

     PASS  examples/67958776/App.test.tsx (8.166 s)
      test
        ✓ happy render (42 ms)
        ✓ renders after search (58 ms)
    
      console.log
        user:  { id: 1, name: 'react' }
    
          at examples/67958776/App.tsx:45:19
              at Array.map (<anonymous>)
    
      console.log
        user:  { id: 2, name: 'jestjs' }
    
          at examples/67958776/App.tsx:45:19
              at Array.map (<anonymous>)
    
    ----------|---------|----------|---------|---------|-------------------
    File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
    ----------|---------|----------|---------|---------|-------------------
    All files |     100 |       80 |     100 |     100 |                   
     App.tsx  |     100 |       80 |     100 |     100 | 44                
    ----------|---------|----------|---------|---------|-------------------
    Test Suites: 1 passed, 1 total
    Tests:       2 passed, 2 total
    Snapshots:   0 total
    Time:        8.873 s
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-19
      • 2019-09-03
      • 2020-03-28
      • 1970-01-01
      • 1970-01-01
      • 2011-12-31
      相关资源
      最近更新 更多