Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(toHaveStyle): strictly match empty values #276

Merged
merged 1 commit into from Jul 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
63 changes: 46 additions & 17 deletions src/__tests__/to-have-style.js
Expand Up @@ -146,26 +146,55 @@ describe('.toHaveStyle', () => {
)
})

test('handles styles as object', () => {
const {container} = render(`
<div class="label" style="background-color: blue; height: 100%">
Hello World
</div>
`)
describe('object syntax', () => {
test('handles styles as object', () => {
const {container} = render(`
<div class="label" style="background-color: blue; height: 100%">
Hello World
</div>
`)

expect(container.querySelector('.label')).toHaveStyle({
backgroundColor: 'blue',
})
expect(container.querySelector('.label')).toHaveStyle({
backgroundColor: 'blue',
height: '100%',
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',
})
})
expect(container.querySelector('.label')).not.toHaveStyle({
backgroundColor: 'red',
height: '100%',

test('supports dash-cased property names', () => {
const {container} = render(`
<div class="label" style="background-color: blue; height: 100%">
Hello World
</div>
`)
expect(container.querySelector('.label')).toHaveStyle({
'background-color': 'blue',
})
})
expect(container.querySelector('.label')).not.toHaveStyle({
whatever: 'anything',

test('requires strict empty properties matching', () => {
const {container} = render(`
<div class="label" style="width: 100%;height: 100%">
Hello World
</div>
`)
expect(container.querySelector('.label')).not.toHaveStyle({
width: '100%',
height: '',
})
expect(container.querySelector('.label')).not.toHaveStyle({
width: '',
height: '',
})
})
})
})
35 changes: 0 additions & 35 deletions src/__tests__/utils.js
Expand Up @@ -2,7 +2,6 @@ import {
deprecate,
checkHtmlElement,
HtmlElementTypeError,
parseJStoCSS,
toSentence,
} from '../utils'
import document from './helpers/document'
Expand Down Expand Up @@ -84,40 +83,6 @@ describe('checkHtmlElement', () => {
})
})

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('')
})
})
})

describe('toSentence', () => {
it('turns array into string of comma separated list with default last word connector', () => {
expect(toSentence(['one', 'two', 'three'])).toBe('one, two and three')
Expand Down
15 changes: 6 additions & 9 deletions 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, parseJStoCSS} from './utils'
import {checkHtmlElement, parseCSS} from './utils'

function getStyleDeclaration(document, css) {
const styles = {}
Expand All @@ -21,7 +21,8 @@ function isSubset(styles, computedStyle) {
!!Object.keys(styles).length &&
Object.entries(styles).every(
([prop, value]) =>
computedStyle.getPropertyValue(prop.toLowerCase()) === value,
computedStyle[prop] === value ||
computedStyle[prop.toLowerCase()] === value,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

computedStyle.getPropertyValue supports only dash-cased notation. Property getters work for both dash and camelCase

)
)
}
Expand All @@ -37,7 +38,7 @@ function printoutStyles(styles) {
// received computed styles
function expectedDiff(expected, computedStyles) {
const received = Array.from(computedStyles)
.filter(prop => expected[prop])
.filter(prop => expected[prop] !== undefined)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is needed to get a proper diff for expect(something).toHaveStyle({width: ''}) (expect width to be empty). Without this change it prints "the diff has no visual difference"

.reduce(
(obj, prop) =>
Object.assign(obj, {[prop]: computedStyles.getPropertyValue(prop)}),
Expand All @@ -51,14 +52,10 @@ function expectedDiff(expected, computedStyles) {
return diffOutput.replace(`${chalk.red('+ Received')}\n`, '')
}

function getCSStoParse(document, css) {
return typeof css === 'object' ? parseJStoCSS(document, css) : css
}

export function toHaveStyle(htmlElement, css) {
checkHtmlElement(htmlElement, toHaveStyle, this)
const cssToParse = getCSStoParse(htmlElement.ownerDocument, css)
const parsedCSS = parseCSS(cssToParse, toHaveStyle, this)
const parsedCSS =
typeof css === 'object' ? css : parseCSS(css, toHaveStyle, this)
const {getComputedStyle} = htmlElement.ownerDocument.defaultView

const expected = getStyleDeclaration(htmlElement.ownerDocument, parsedCSS)
Expand Down
7 changes: 0 additions & 7 deletions src/utils.js
Expand Up @@ -192,12 +192,6 @@ function compareArraysAsSet(a, b) {
return undefined
}

function parseJStoCSS(document, css) {
const sandboxElement = document.createElement('div')
Object.assign(sandboxElement.style, css)
return sandboxElement.style.cssText
}
Comment on lines -195 to -199
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is currently not used anywhere else, so I decided to drop this completely


function toSentence(
array,
{wordConnector = ', ', lastWordConnector = ' and '} = {},
Expand All @@ -218,6 +212,5 @@ export {
getTag,
getSingleElementValue,
compareArraysAsSet,
parseJStoCSS,
toSentence,
}