如何将 Material-UI 样式表注入 jest/react-testing-library 测试?

Jak*_*ake 5 jestjs material-ui react-testing-library

似乎如果您不将 Material-UI 样式表注入 jest/react-testing-library 测试,那么 jsdom 将无法从您的组件中获取正确的样式(例如,运行getComputedStyle(component)将返回不正确的组件样式)。

您如何正确设置 jest/react-testing-library 测试,以便将样式正确地注入到测试中?我已经将组件包装在主题提供程序中,效果很好。

dav*_*lyi 8

作为一种解决方法,在断言之前重新插入整个头部(或注入 JSS 样式的元素)似乎可以正确应用样式并getComputedStyle()响应测试库toHaveStyle()

import React from "react";
import "@testing-library/jest-dom/extend-expect";
import { render } from "@testing-library/react";

test("test my styles", () => {
  const { getByTestId } = render(
    <div data-testid="wrapper">
      <MyButtonStyledWithJSS/>
    </div>
  );
  const button = getByTestId("wrapper").firstChild;
  document.head.innerHTML = document.head.innerHTML;
  expect(button).toHaveStyle(`border-radius: 4px;`);
});

Run Code Online (Sandbox Code Playgroud)

当您使用动态样式时,这仍然会失败,例如:

myButton: {
  padding: props => props.spacing,
  ...
}
Run Code Online (Sandbox Code Playgroud)

这是因为JSS使用CSSStyleSheet.insertRule方法来注入这些样式,并且它不会以style节点的形式出现在head中。此问题的一种解决方案是挂钩浏览器的insertRule方法并将传入规则作为样式标签添加到头部。要将所有这些提取到一个函数中:

function mockStyleInjection() {
  const defaultInsertRule = window.CSSStyleSheet.prototype.insertRule;
  window.CSSStyleSheet.prototype.insertRule = function (rule, index) {
    const styleElement = document.createElement("style");
    const textNode = document.createTextNode(rule);
    styleElement.appendChild(textNode);
    document.head.appendChild(styleElement);
    return defaultInsertRule.bind(this)(rule, index);
  };
  // cleanup function, which reinserts the head and cleans up method overwrite
  return function applyJSSRules() {
    window.CSSStyleSheet.prototype.insertRule = defaultInsertRule;
    document.head.innerHTML = document.head.innerHTML;
  };
}

Run Code Online (Sandbox Code Playgroud)

在我们之前的测试中该函数的使用示例:

import React from "react";
import "@testing-library/jest-dom/extend-expect";
import { render } from "@testing-library/react";

test("test my styles", () => {
  const applyJSSRules = mockStyleInjection();
  const { getByTestId } = render(
    <div data-testid="wrapper">
      <MyButtonStyledWithJSS spacing="8px"/>
    </div>
  );
  const button = getByTestId("wrapper").firstChild;
  applyJSSRules();
  expect(button).toHaveStyle("border-radius: 4px;");
  expect(button).toHaveStyle("padding: 8px;");
});

Run Code Online (Sandbox Code Playgroud)


Mic*_*ook -1

我不能具体谈论 Material-UI 样式表,但您可以将样式表注入到渲染的组件中:

import {render} from '@testing-library/react';
import fs from 'fs';
import path from 'path';

const stylesheetFile = fs.reactFileSync(path.resolve(__dirname, '../path-to-stylesheet'), 'utf-8');

const styleTag = document.createElement('style');
styleTag.type = 'text/css';
styleTag.innerHTML = stylesheetFile;

const rendered = render(<MyComponent>);
rendered.append(style);
Run Code Online (Sandbox Code Playgroud)

您不一定必须从文件中读取,您可以使用您想要的任何文本。