ทำไม getComputedStyle () ในการทดสอบ JEST ส่งคืนผลลัพธ์ที่แตกต่างไปยังสไตล์ที่คำนวณใน Chrome / Firefox DevTools


16

ผมเคยเขียนปุ่มที่กำหนดเอง ( MyStyledButton) ตามวัสดุ 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;

มันมีสไตล์โดยใช้ชุดรูปแบบและสิ่งนี้ระบุbackgroundColorว่าเป็นสีเหลือง (พิเศษ#fbb900)

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

export const myYellow = "#FBB900";

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

ส่วนประกอบถูกสร้างขึ้นใน main ของฉันindex.jsและถูกหุ้มthemeด้วย

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

หากฉันตรวจสอบปุ่มใน Chrome DevTools background-colorจะ "คำนวณ" ตามที่คาดไว้ นี่เป็นกรณีใน Firefox DevTools

ภาพหน้าจอจาก Chrome

อย่างไรก็ตามเมื่อฉันเขียนการทดสอบ JEST เพื่อตรวจสอบ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);

ฉันได้รวม CodeSandbox กับปัญหาที่แน่นอนรหัสขั้นต่ำในการทำซ้ำและการทดสอบ JEST ที่ล้มเหลว

แก้ไข headless-snow-nyofd


.MuiButtonBase-root-33 background-color โปร่งใสในขณะที่. MuiButton-containPrimary-13 ไม่ได้ - ดังนั้นปัญหาคือคลาสใน CSS นั้นมีความสำคัญเท่ากันดังนั้นลำดับการโหลดเท่านั้นที่แยกความแตกต่าง -> ในรูปแบบการทดสอบโหลดในลำดับที่ไม่ถูกต้อง
Zydnar

1
@Andreas - อัปเดตตามที่ร้องขอ
Simon Long

@Zyndar - ใช่ฉันรู้ว่า มีวิธีใดบ้างที่จะผ่านการทดสอบนี้?
Simon Long

ไม่themeจำเป็นต้องใช้ในการทดสอบใช่ไหม ในขณะที่ห่อ<MyStyledButton>ใน<MuiThemeProvider theme={theme}>? หรือใช้ฟังก์ชั่น wrapper เพื่อเพิ่มธีมให้กับส่วนประกอบทั้งหมด?
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.