to-have-style.js 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. "use strict";
  2. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  3. Object.defineProperty(exports, "__esModule", {
  4. value: true
  5. });
  6. exports.toHaveStyle = toHaveStyle;
  7. var _chalk = _interopRequireDefault(require("chalk"));
  8. var _utils = require("./utils");
  9. function getStyleDeclaration(document, css) {
  10. const styles = {}; // The next block is necessary to normalize colors
  11. const copy = document.createElement('div');
  12. Object.keys(css).forEach(property => {
  13. copy.style[property] = css[property];
  14. styles[property] = copy.style[property];
  15. });
  16. return styles;
  17. }
  18. function isSubset(styles, computedStyle) {
  19. return !!Object.keys(styles).length && Object.entries(styles).every(([prop, value]) => computedStyle[prop] === value || computedStyle.getPropertyValue(prop.toLowerCase()) === value);
  20. }
  21. function printoutStyles(styles) {
  22. return Object.keys(styles).sort().map(prop => `${prop}: ${styles[prop]};`).join('\n');
  23. } // Highlights only style rules that were expected but were not found in the
  24. // received computed styles
  25. function expectedDiff(diffFn, expected, computedStyles) {
  26. const received = Array.from(computedStyles).filter(prop => expected[prop] !== undefined).reduce((obj, prop) => Object.assign(obj, {
  27. [prop]: computedStyles.getPropertyValue(prop)
  28. }), {});
  29. const diffOutput = diffFn(printoutStyles(expected), printoutStyles(received)); // Remove the "+ Received" annotation because this is a one-way diff
  30. return diffOutput.replace(`${_chalk.default.red('+ Received')}\n`, '');
  31. }
  32. function toHaveStyle(htmlElement, css) {
  33. (0, _utils.checkHtmlElement)(htmlElement, toHaveStyle, this);
  34. const parsedCSS = typeof css === 'object' ? css : (0, _utils.parseCSS)(css, toHaveStyle, this);
  35. const {
  36. getComputedStyle
  37. } = htmlElement.ownerDocument.defaultView;
  38. const expected = getStyleDeclaration(htmlElement.ownerDocument, parsedCSS);
  39. const received = getComputedStyle(htmlElement);
  40. return {
  41. pass: isSubset(expected, received),
  42. message: () => {
  43. const matcher = `${this.isNot ? '.not' : ''}.toHaveStyle`;
  44. return [this.utils.matcherHint(matcher, 'element', ''), expectedDiff(this.utils.diff, expected, received)].join('\n\n');
  45. }
  46. };
  47. }