问题描述
当用户在输入搜索中输入一些文本时,必须删除 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"));
});
});
解决方法
您可以模拟 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