JEST 테스트에서 getComputedStyle ()이 Chrome / Firefox DevTools의 계산 된 스타일에 다른 결과를 반환하는 이유


16

material-uiMyStyledButton 기반 사용자 정의 버튼 ( )을 작성했습니다 . 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;

테마를 사용하여 스타일이 지정 backgroundColor되며을 노란색 음영으로 지정합니다 (특히 #fbb900)

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

export const myYellow = "#FBB900";

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

구성 요소가 내 메인에서 인스턴스화 index.js되고에 래핑됩니다 theme.

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

Chrome DevTools에서 버튼을 검사하면 background-color예상대로 "계산됩니다". Firefox DevTools에서도 마찬가지입니다.

Chrome 스크린 샷

나는 농담 테스트를 작성할 때 그러나를 확인 background-color하고 내가 사용하는 버튼의 DOM 노드 스타일을 쿼리 getComputedStyles()내가 가져 transparent왔다 테스트가 실패합니다.

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);

정확한 문제, 재현 할 수있는 최소 코드 및 실패한 JEST 테스트가있는 CodeSandbox를 포함 시켰습니다.

헤드리스 스노우 Nyofd 편집


.MuiButtonBase-root-33 배경색은 투명하지만 .MuiButton-containedPrimary-13은 투명하지 않습니다. 문제는 CSS의 클래스가 똑같이 중요하므로로드 순서 만 구별한다는 것입니다.
Zydnar

1
@Andreas-요청에 따라 업데이트
Simon Long

@ Zyndar-예, 알고 있습니다. 이 시험을 통과 할 수있는 방법이 있습니까?
Simon Long

하지 않을까요 theme필요가 시험에 사용되는? 마찬가지로, 포장 <MyStyledButton>의를 <MuiThemeProvider theme={theme}>? 또는 일부 래퍼 기능을 사용하여 테마를 모든 구성 요소에 추가합니까?
Brett DeWoody

아니요, 아무런 차이가 없습니다.
Simon Long

답변:


1

나는 더 가까워졌지만 아직 해결책이 없습니다.

주요 문제는 MUIButton이 요소에 태그를 삽입하여 스타일을 강화한다는 것입니다. 이것은 단위 테스트에서 일어나지 않습니다. 재료 테스트에서 사용 하는 createMount 를 사용하여이 작업을 수행 할 수있었습니다 .

이 수정 후 스타일이 올바르게 표시됩니다. 그러나 계산 된 스타일은 여전히 ​​작동하지 않습니다. 다른 사람들이 효소를 올바르게 처리하는 데 문제가있는 것처럼 보입니다. 그래서 가능한지 확실하지 않습니다.

내가 어디를 얻으려면, 테스트 조각을, 정상에이를 복사 한 다음 테스트 코드를 변경 :

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;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.