reactjs - בעיה בבדיקת שגיאה ברכיב React המשתמש ב-react-query וב-axios. בדיקה עם React Testing Library, Jest, msw
אני בודק קומפוננטת React שצריכה להציג או ספינר, או שגיאה, או רשימה של מתכונים שהתקבלו. הצלחתי לבדוק את הקומפוננטה הזו בזמן טעינה וכאשר היא מקבלת נתונים בהצלחה. יש לי בעיה בבדיקת שגיאה. יצרתי שרת בדיקה עם msw, שיש לו מנהל נתיב שמחזיר שגיאה. אני משתמש ב-axios כדי לבצע בקשות לשרת. אני חושב שהבעיה כאן: axios מבצע 3 בקשות ועד שהתגובה האחרונה מתקבלת useQuery מחזיר isLoading=true, isError=false. רק לאחר מכן הוא מחזיר isLoading=false, isError=true. כך שבבדיקה שלי עבור מסך השגיאה screen.debug() מציג ספינר, ו-errorMessage מחזיר שגיאה כי הוא לא מוצא אלמנט מוצג עם הטקסט 'error', שהקומפוננטה אמורה להציג כאשר מתרחשת שגיאה. מה אני יכול לעשות לגבי זה? נגמרו לי הרעיונות.
עריכה :
- גיליתי שיש הגדרה ב-useQuery, "retry", שהברירת מחדל שלה היא 3 בקשות. אני עדיין לא יודע איך להתמודד עם רכיב שמבצע ניסיון חוזר של בקשות בבדיקה שלי.
אני חדש בבדיקות React ו-Typescript.
מתוך RecipeList.test.tsx:
import { setupServer } from 'msw/node';
import { rest } from 'msw';
import { QueryClient, QueryClientProvider, QueryCache } from 'react-query';
import RecipeList from './RecipeList';
const server = setupServer(
rest.get(`${someUrl}`, (req, res, ctx) =>
res(ctx.status(200), ctx.json(data))
)
);
const queryCache = new QueryCache();
const RecipeListWithQueryClient = () => {
const client = new QueryClient();
return (
<QueryClientProvider client={client}>
<RecipeList />
</QueryClientProvider>
);
};
// Tests setup
beforeAll(() => server.listen());
afterAll(() => server.close());
afterEach(() => server.resetHandlers());
afterEach(() => {
queryCache.clear();
});
describe('RecipeList', () => {
//some tests that pass
describe('while error', () => {
it('display error message', async () => {
server.use(
rest.get(`${someUrl}`, (req, res, ctx) => res(ctx.status(404)))
);
render(<RecipeListWithQueryClient />);
// FOLLOWING CODE RAISE ERROR
const errorMessage = await screen.findByText(/error/i);
await expect(errorMessage).toBeInTheDocument();
});
});
});
קוד רכיב:
מ-RecipeList.tsx:
import { fetchRecipes } from 'api';
const RecipeList: React.FC = () => {
const { data, isLoading, isError } = useQuery<
RecipeDataInterface,
Error
>('recipes', fetchRecipes);;
if (isLoading) {
return (
<Spinner>
<span className="sr-only">Loading...</span>
</Spinner>
);
}
if (isError) {
return (
<Alert >Error occured. Please try again later</Alert>
);
}
return (
<>
{data?.records.map((recipe: RecipeInterface) => (
<RecipeItem key={recipe.id} recipe={recipe.fields} />
))}
</>
);
};
תשובה #1
אני השתמשתי ב-QueryClient כדי להשבית ניסיון חוזר. והגדרתי setupServer כדי לחקות חיבור רשת
import { QueryClient, QueryClientProvider} from 'react-query';
import { setupServer } from 'msw/node'
import { rest } from 'msw'
const server = setupServer(
rest.get('https://reqres.in/api/users', (req, res, ctx) => {
return res(
ctx.status(200),
ctx.json(userSuccessResponseJson()
),
)
}),)
beforeAll(() => server.listen())
afterEach(() => {
server.resetHandlers();
queryClient.clear();
})
afterAll(() => server.close())
const queryClient = new QueryClient({
defaultOptions: {
queries: {
retryDelay: 1,
retry:0,
},
},
})
const Wrapper = ({ children }) => (
<QueryClientProvider client={queryClient}>
{children}
</QueryClientProvider>
);
test('Renders Error text when backend server response with error', async () => {
server.use(
rest.get('https://reqres.in/api/users', (req, res, ctx) => {
return res(ctx.status(403))
})
);
render(<Wrapper><CompanyList />)</Wrapper>);
const linkElement = screen.getByText(/Loading/i);
expect(linkElement).toBeInTheDocument();
await waitFor(() => {
const fetchedText = screen.getByText(/Error:/i);
expect(fetchedText).toBeInTheDocument();
})
});
