Tại sao getComputingStyle () trong thử nghiệm JEST trả về các kết quả khác nhau cho các kiểu được tính toán trong DevTools của Chrome / Firefox


16

Tôi đã viết một nút tùy chỉnh ( MyStyledButton) dựa trên tài liệu-ui Button .

import React from "react";
import { Button } from "@material-ui/core";
import { makeStyles } from "@material-ui/styles";

const useStyles = makeStyles({
  root: {
    minWidth: 100
  }
});

function MyStyledButton(props) {
  const buttonStyle = useStyles(props);
  const { children, width, ...others } = props;

  return (

      <Button classes={{ root: buttonStyle.root }} {...others}>
        {children}
      </Button>
     );
}

export default MyStyledButton;

Nó được tạo kiểu bằng cách sử dụng một chủ đề và điều này xác định backgroundColorlà màu vàng (Đặc biệt #fbb900)

import { createMuiTheme } from "@material-ui/core/styles";

export const myYellow = "#FBB900";

export const theme = createMuiTheme({
  overrides: {
    MuiButton: {
      containedPrimary: {
        color: "black",
        backgroundColor: myYellow
      }
    }
  }
});

Các thành phần được khởi tạo trong chính của tôi index.jsvà được bọc trong theme.

  <MuiThemeProvider theme={theme}>
     <MyStyledButton variant="contained" color="primary">
       Primary Click Me
     </MyStyledButton>
  </MuiThemeProvider>

Nếu tôi kiểm tra nút trong Chrome DevTools, background-colornó sẽ được "tính toán" như mong đợi. Đây cũng là trường hợp trong Firefox DevTools.

Ảnh chụp màn hình từ Chrome

Tuy nhiên, khi tôi viết một bài kiểm tra JEST để kiểm tra background-colorvà tôi truy vấn kiểu nút DOM òf nút sử dụng getComputedStyles()tôi transparentquay lại và bài kiểm tra thất bại.

const wrapper = mount(
    <MyStyledButton variant="contained" color="primary">
      Primary
    </MyStyledButton>
  );
  const foundButton = wrapper.find("button");
  expect(foundButton).toHaveLength(1);
  //I want to check the background colour of the button here
  //I've tried getComputedStyle() but it returns 'transparent' instead of #FBB900
  expect(
    window
      .getComputedStyle(foundButton.getDOMNode())
      .getPropertyValue("background-color")
  ).toEqual(myYellow);

Tôi đã bao gồm một CodeSandbox với vấn đề chính xác, mã tối thiểu để sao chép và thử nghiệm JEST không thành công.

Chỉnh sửa không đầu-tuyết-nyofd


Màu nền .MuiButtonBase-root-33 trong suốt .MuiButton-chứaPrimary-13 thì không - vì vậy vấn đề là, các lớp trong CSS là quan trọng, vì vậy chỉ tải thứ tự phân biệt chúng -> trong các kiểu kiểm tra được tải sai thứ tự.
Zydnar

1
@Andreas - Cập nhật theo yêu cầu
Simon Long

@Zyndar - Vâng, tôi biết điều đó. Có cách nào để vượt qua bài kiểm tra này không?
Simon Long

Sẽ không themecần phải được sử dụng trong thử nghiệm? Như trong, bọc <MyStyledButton>trong <MuiThemeProvider theme={theme}>? Hoặc sử dụng một số chức năng bao bọc để thêm chủ đề cho tất cả các thành phần?
Brett DeWoody

Không, điều đó không tạo nên sự khác biệt.
Simon Long

Câu trả lời:


1

Tôi đã tiến gần hơn, nhưng chưa hoàn toàn là một giải pháp.

Vấn đề chính là MUIButton tiêm một thẻ vào phần tử để cung cấp năng lượng cho các kiểu. Điều này không xảy ra trong bài kiểm tra đơn vị của bạn. Tôi đã có thể làm cho điều này hoạt động bằng cách sử dụng createMount mà các bài kiểm tra vật liệu sử dụng.

Sau khi sửa lỗi này, phong cách được hiển thị chính xác. Tuy nhiên, kiểu tính toán vẫn không hoạt động. Có vẻ như những người khác đã gặp phải vấn đề với enzyme xử lý việc này một cách chính xác - vì vậy tôi không chắc liệu điều đó có khả thi hay không.

Để đến nơi tôi đang ở, hãy lấy đoạn kiểm tra của bạn, sao chép đoạn mã này lên trên cùng và sau đó thay đổi mã kiểm tra của bạn thành:

const myMount = createMount({ strict: true });
  const wrapper = myMount(
    <MuiThemeProvider theme={theme}>
      <MyStyledButton variant="contained" color="primary">
        Primary
      </MyStyledButton>
    </MuiThemeProvider>
  );
class Mode extends React.Component {
  static propTypes = {
    /**
     * this is essentially children. However we can't use children because then
     * using `wrapper.setProps({ children })` would work differently if this component
     * would be the root.
     */
    __element: PropTypes.element.isRequired,
    __strict: PropTypes.bool.isRequired,
  };

  render() {
    // Excess props will come from e.g. enzyme setProps
    const { __element, __strict, ...other } = this.props;
    const Component = __strict ? React.StrictMode : React.Fragment;

    return <Component>{React.cloneElement(__element, other)}</Component>;
  }
}

// Generate an enhanced mount function.
function createMount(options = {}) {

  const attachTo = document.createElement('div');
  attachTo.className = 'app';
  attachTo.setAttribute('id', 'app');
  document.body.insertBefore(attachTo, document.body.firstChild);

  const mountWithContext = function mountWithContext(node, localOptions = {}) {
    const strict = true;
    const disableUnnmount = false;
    const localEnzymeOptions = {};
    const globalEnzymeOptions = {};

    if (!disableUnnmount) {
      ReactDOM.unmountComponentAtNode(attachTo);
    }

    // some tests require that no other components are in the tree
    // e.g. when doing .instance(), .state() etc.
    return mount(strict == null ? node : <Mode __element={node} __strict={Boolean(strict)} />, {
      attachTo,
      ...globalEnzymeOptions,
      ...localEnzymeOptions,
    });
  };

  mountWithContext.attachTo = attachTo;
  mountWithContext.cleanUp = () => {
    ReactDOM.unmountComponentAtNode(attachTo);
    attachTo.parentElement.removeChild(attachTo);
  };

  return mountWithContext;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.