From b3d772249938730cec16d54954905b7993fb7985 Mon Sep 17 00:00:00 2001 From: Leandro Lourenci Date: Wed, 29 Jan 2020 18:03:15 -0300 Subject: [PATCH 1/2] Enhance toHaveStyle to accept JS as css --- src/__tests__/to-have-style.js | 22 ++++++++++++++++++++++ src/to-have-style.js | 13 ++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/__tests__/to-have-style.js b/src/__tests__/to-have-style.js index 0771bd48..fba73a21 100644 --- a/src/__tests__/to-have-style.js +++ b/src/__tests__/to-have-style.js @@ -1,6 +1,7 @@ import {render} from './helpers/test-utils' import document from './helpers/document' +// eslint-disable-next-line max-lines-per-function describe('.toHaveStyle', () => { test('handles positive test cases', () => { const {container} = render(` @@ -144,4 +145,25 @@ describe('.toHaveStyle', () => { 'whatever: anything', ) }) + + test('handles styles as object', () => { + const {container} = render(` +
+ Hello World +
+ `) + + expect(container.querySelector('.label')).toHaveStyle({ + backgroundColor: 'blue', + }) + expect(container.querySelector('.label')).toHaveStyle({ + backgroundColor: 'blue', + height: '100%', + }) + expect(container.querySelector('.label')).not.toHaveStyle({ + backgroundColor: 'red', + height: '100%', + }) + // expect(container.querySelector('.label')).not.toHaveStyle({ whatever: 'anything' }) + }) }) diff --git a/src/to-have-style.js b/src/to-have-style.js index e81303ea..9c5b28b8 100644 --- a/src/to-have-style.js +++ b/src/to-have-style.js @@ -48,8 +48,19 @@ function expectedDiff(expected, computedStyles) { return diffOutput.replace(`${chalk.red('+ Received')}\n`, '') } -export function toHaveStyle(htmlElement, css) { +function getCss(document, css) { + if (typeof css === 'object') { + const sandboxElement = document.createElement('div') + Object.assign(sandboxElement.style, css) + return sandboxElement.style.cssText + } + + return css +} + +export function toHaveStyle(htmlElement, expectedCss) { checkHtmlElement(htmlElement, toHaveStyle, this) + const css = getCss(htmlElement.ownerDocument, expectedCss) const parsedCSS = parseCSS(css, toHaveStyle, this) const {getComputedStyle} = htmlElement.ownerDocument.defaultView From 963646f8dc422f8738bdd1b44951bb9d63819f93 Mon Sep 17 00:00:00 2001 From: Leandro Lourenci Date: Thu, 30 Jan 2020 20:53:58 -0300 Subject: [PATCH 2/2] Do some refactor --- README.md | 22 +++++++++++++----- src/__tests__/to-have-style.js | 4 +++- src/__tests__/utils.js | 41 +++++++++++++++++++++++++++++++++- src/to-have-style.js | 27 ++++++++++------------ src/utils.js | 7 ++++++ 5 files changed, 79 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 3814609c..cc704f15 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,6 @@ clear to read and to maintain. - - [Installation](#installation) - [Usage](#usage) - [Custom matchers](#custom-matchers) @@ -642,7 +641,7 @@ expect(getByTestId('login-form')).toHaveFormValues({ ### `toHaveStyle` ```typescript -toHaveStyle(css: string) +toHaveStyle(css: string | object) ``` This allows you to check if a certain element has some specific css properties @@ -652,7 +651,10 @@ expected properties applied, not just some of them. #### Examples ```html - ``` @@ -661,14 +663,23 @@ expected properties applied, not just some of them. const button = getByTestId('delete-button') expect(button).toHaveStyle('display: none') +expect(button).toHaveStyle({display: 'none'}) expect(button).toHaveStyle(` - color: red; + background-color: red; display: none; `) +expect(button).toHaveStyle({ + backgroundColor: 'red', + display: 'none', +}) expect(button).not.toHaveStyle(` - color: blue; + background-color: blue; display: none; `) +expect(button).not.toHaveStyle({ + backgroundColor: 'blue', + display: 'none', +}) ``` This also works with rules that are applied to the element via a class name for @@ -928,6 +939,7 @@ Thanks goes to these people ([emoji key][emojis]): + This project follows the [all-contributors][all-contributors] specification. diff --git a/src/__tests__/to-have-style.js b/src/__tests__/to-have-style.js index fba73a21..0c313550 100644 --- a/src/__tests__/to-have-style.js +++ b/src/__tests__/to-have-style.js @@ -164,6 +164,8 @@ describe('.toHaveStyle', () => { backgroundColor: 'red', height: '100%', }) - // expect(container.querySelector('.label')).not.toHaveStyle({ whatever: 'anything' }) + expect(container.querySelector('.label')).not.toHaveStyle({ + whatever: 'anything', + }) }) }) diff --git a/src/__tests__/utils.js b/src/__tests__/utils.js index 6410808b..5eae7f20 100644 --- a/src/__tests__/utils.js +++ b/src/__tests__/utils.js @@ -1,4 +1,9 @@ -import {deprecate, checkHtmlElement, HtmlElementTypeError} from '../utils' +import { + deprecate, + checkHtmlElement, + HtmlElementTypeError, + parseJStoCSS, +} from '../utils' import document from './helpers/document' test('deprecate', () => { @@ -77,3 +82,37 @@ describe('checkHtmlElement', () => { }).toThrow(HtmlElementTypeError) }) }) + +describe('parseJStoCSS', () => { + describe('when all the styles are valid', () => { + it('returns the JS parsed as CSS text', () => { + expect( + parseJStoCSS(document, { + backgroundColor: 'blue', + height: '100%', + }), + ).toBe('background-color: blue; height: 100%;') + }) + }) + + describe('when some style is invalid', () => { + it('returns the JS parsed as CSS text without the invalid style', () => { + expect( + parseJStoCSS(document, { + backgroundColor: 'blue', + whatever: 'anything', + }), + ).toBe('background-color: blue;') + }) + }) + + describe('when all the styles are invalid', () => { + it('returns an empty string', () => { + expect( + parseJStoCSS(document, { + whatever: 'anything', + }), + ).toBe('') + }) + }) +}) diff --git a/src/to-have-style.js b/src/to-have-style.js index 9c5b28b8..3e8a155b 100644 --- a/src/to-have-style.js +++ b/src/to-have-style.js @@ -1,7 +1,7 @@ import {matcherHint} from 'jest-matcher-utils' import jestDiff from 'jest-diff' import chalk from 'chalk' -import {checkHtmlElement, parseCSS} from './utils' +import {checkHtmlElement, parseCSS, parseJStoCSS} from './utils' function getStyleDeclaration(document, css) { const styles = {} @@ -17,9 +17,12 @@ function getStyleDeclaration(document, css) { } function isSubset(styles, computedStyle) { - return Object.entries(styles).every( - ([prop, value]) => - computedStyle.getPropertyValue(prop.toLowerCase()) === value, + return ( + !!Object.keys(styles).length && + Object.entries(styles).every( + ([prop, value]) => + computedStyle.getPropertyValue(prop.toLowerCase()) === value, + ) ) } @@ -48,20 +51,14 @@ function expectedDiff(expected, computedStyles) { return diffOutput.replace(`${chalk.red('+ Received')}\n`, '') } -function getCss(document, css) { - if (typeof css === 'object') { - const sandboxElement = document.createElement('div') - Object.assign(sandboxElement.style, css) - return sandboxElement.style.cssText - } - - return css +function getCSStoParse(document, css) { + return typeof css === 'object' ? parseJStoCSS(document, css) : css } -export function toHaveStyle(htmlElement, expectedCss) { +export function toHaveStyle(htmlElement, css) { checkHtmlElement(htmlElement, toHaveStyle, this) - const css = getCss(htmlElement.ownerDocument, expectedCss) - const parsedCSS = parseCSS(css, toHaveStyle, this) + const cssToParse = getCSStoParse(htmlElement.ownerDocument, css) + const parsedCSS = parseCSS(cssToParse, toHaveStyle, this) const {getComputedStyle} = htmlElement.ownerDocument.defaultView const expected = getStyleDeclaration(htmlElement.ownerDocument, parsedCSS) diff --git a/src/utils.js b/src/utils.js index 1647fd29..c07a3037 100644 --- a/src/utils.js +++ b/src/utils.js @@ -192,6 +192,12 @@ function compareArraysAsSet(a, b) { return undefined } +function parseJStoCSS(document, css) { + const sandboxElement = document.createElement('div') + Object.assign(sandboxElement.style, css) + return sandboxElement.style.cssText +} + export { HtmlElementTypeError, checkHtmlElement, @@ -203,4 +209,5 @@ export { getTag, getSingleElementValue, compareArraysAsSet, + parseJStoCSS, }