Подобный вопрос здесь - Невозможно проверить, ожидают (вяз) .not.toBeVisible () для компонента семантического интерфейса реакции - однако ответ предполагает, что это должно работать для CSS-in-JS, который что я использую.
Я использую компонент Material-UI <Hidden>
, чтобы отображать только текст на экранах sm
и выше. Вот код (который отлично работает в производстве):
<Hidden implementation="css" xsDown>
<LogoText variant="h5" component="p" />
</Hidden>
Я использую jest-dom
с react-testing-library
и пытаюсь проверить отзывчивость моей панели навигации, которая содержит этот скрытый текст.
У меня есть следующий тест:
const initTest = width => {
Object.defineProperty(window, "innerWidth", {
writable: true,
configurable: true,
value: width
});
window.matchMedia = jest.fn().mockImplementation(
query => {
return {
matches: width >= theme.breakpoints.values.sm ? true : false,
media: query,
onchange: null,
addListener: jest.fn(),
removeListener: jest.fn()
};
}
);
const height = Math.round((width * 9) / 16);
return { width, height };
};
describe("Unit: <Navbar> On xs screens", () => {
it("renders as snapshot at minimum size", async () => {
const { width, height } = initTest(320);
const { asFragment, rerender } = render(
<Container backgroundColor={"#ffffff"}>
<Navbar />
</Container>
);
rerender(
<Container backgroundColor={"#ffffff"}>
<Navbar />
</Container>
);
expect(asFragment()).toMatchSnapshot();
const screenshot = await generateImage({
viewport: { width, height }
});
expect(screenshot).toMatchImageSnapshot();
});
it("renders as snapshot at maximum size", async () => {
const { width, height } = initTest(theme.breakpoints.values.sm - 1);
const { asFragment, rerender } = render(
<Container backgroundColor={"#ffffff"}>
<Navbar />
</Container>
);
rerender(
<Container backgroundColor={"#ffffff"}>
<Navbar />
</Container>
);
expect(asFragment()).toMatchSnapshot();
const screenshot = await generateImage({
viewport: { width, height }
});
expect(screenshot).toMatchImageSnapshot();
});
it("hides logo text", async () => {
initTest(theme.breakpoints.values.sm - 1);
const { rerender, getByText } = render(
<Container backgroundColor={"#ffffff"}>
<Navbar />
</Container>
);
rerender(
<Container backgroundColor={"#ffffff"}>
<Navbar />
</Container>
);
await wait(() => expect(getByText("LOGO TEXT")).not.toBeVisible());
});
});
Первые 2 теста делают снимок экрана, и когда я смотрю на снимок экрана, я вижу, что текст логотипа не виден:
И когда я просматриваю DOM в браузере с размером xs
, я вижу, что родительский компонент действительно скрыт: https://i.imgur.com/TfBpePV.png
Тем не менее, когда я запускаю тест, он не проходит и говорит, что элемент видим:
● Unit: <Navbar> On xs screens › hides logo text
expect(element).not.toBeVisible()
Received element is visible:
<p class="MuiTypography-root MuiTypography-h5 makeStyles-typography-237" />
Если я добавлю console.log(innerWidth)
перед expect()
, он вернет правильную ширину, поэтому проблема не в том, что jsdom выполняет рендеринг с неправильной шириной экрана.
Кроме того, если я изменю реализацию компонента <Hidden>
с CSS на JS, он будет работать нормально (поскольку элемент полностью удален из документа с использованием JS, а не просто скрыт с помощью медиазапросов).
Как это исправить, чтобы заставить его работать?