tailwindcss/jest/customMatchers.js
Robin Malfait d2fdf9eb09
Allow returning parallel variants from addVariant or matchVariant callback functions (#8455)
* allow to return an array of format strings from matchVariant or
addVariant

* add parallel variant with function test

* upgrade test to use a function call

* allow to return parallel variants from variant function

Caveat: this now belongs to the same plugin and is not registered as
separate variants which means that sort order can differ.

* prevent crash if `.toMatchFormattedCss()` receives undefined

* update changelog

* ensure that we use a local list of variant functions

Now that a variant function can return a list of variant functions from
within the plugin, we have to make sure to executed and register those
functions as well.

However, we need to make sure that this list is local for the variant
and not "globally" registered otherwise we keep add a dynamic function
to the global list which results in duplicate output becaus multiple
duplicate variants will be registered.

* add little warning regarding potential clashes

* Update CHANGELOG.md
2022-05-31 15:03:06 +02:00

151 lines
4.5 KiB
JavaScript

const prettier = require('prettier')
const { diff } = require('jest-diff')
function format(input) {
return prettier.format(input, {
parser: 'css',
printWidth: 100,
})
}
expect.extend({
// Compare two CSS strings with all whitespace removed
// This is probably naive but it's fast and works well enough.
toMatchCss(received, argument) {
function stripped(str) {
return str.replace(/\s/g, '').replace(/;/g, '')
}
const options = {
comment: 'stripped(received) === stripped(argument)',
isNot: this.isNot,
promise: this.promise,
}
const pass = stripped(received) === stripped(argument)
const message = pass
? () => {
return (
this.utils.matcherHint('toMatchCss', undefined, undefined, options) +
'\n\n' +
`Expected: not ${this.utils.printExpected(format(received))}\n` +
`Received: ${this.utils.printReceived(format(argument))}`
)
}
: () => {
const actual = format(received)
const expected = format(argument)
const diffString = diff(expected, actual, {
expand: this.expand,
})
return (
this.utils.matcherHint('toMatchCss', undefined, undefined, options) +
'\n\n' +
(diffString && diffString.includes('- Expect')
? `Difference:\n\n${diffString}`
: `Expected: ${this.utils.printExpected(expected)}\n` +
`Received: ${this.utils.printReceived(actual)}`)
)
}
return { actual: received, message, pass }
},
toIncludeCss(received, argument) {
function stripped(str) {
return str.replace('/* prettier-ignore */', '').replace(/\s/g, '').replace(/;/g, '')
}
const options = {
comment: 'stripped(received).includes(stripped(argument))',
isNot: this.isNot,
promise: this.promise,
}
const pass = stripped(received).includes(stripped(argument))
const message = pass
? () => {
return (
this.utils.matcherHint('toIncludeCss', undefined, undefined, options) +
'\n\n' +
`Expected: not ${this.utils.printExpected(format(received))}\n` +
`Received: ${this.utils.printReceived(format(argument))}`
)
}
: () => {
const actual = format(received)
const expected = format(argument)
const diffString = diff(expected, actual, {
expand: this.expand,
})
return (
this.utils.matcherHint('toIncludeCss', undefined, undefined, options) +
'\n\n' +
(diffString && diffString.includes('- Expect')
? `Difference:\n\n${diffString}`
: `Expected: ${this.utils.printExpected(expected)}\n` +
`Received: ${this.utils.printReceived(actual)}`)
)
}
return { actual: received, message, pass }
},
})
expect.extend({
// Compare two CSS strings with all whitespace removed
// This is probably naive but it's fast and works well enough.
toMatchFormattedCss(received = '', argument = '') {
function format(input) {
return prettier.format(input.replace(/\n/g, ''), {
parser: 'css',
printWidth: 100,
})
}
const options = {
comment: 'stripped(received) === stripped(argument)',
isNot: this.isNot,
promise: this.promise,
}
let formattedReceived = format(received)
let formattedArgument = format(argument)
const pass = formattedReceived === formattedArgument
const message = pass
? () => {
return (
this.utils.matcherHint('toMatchCss', undefined, undefined, options) +
'\n\n' +
`Expected: not ${this.utils.printExpected(formattedReceived)}\n` +
`Received: ${this.utils.printReceived(formattedArgument)}`
)
}
: () => {
const actual = formattedReceived
const expected = formattedArgument
const diffString = diff(expected, actual, {
expand: this.expand,
})
return (
this.utils.matcherHint('toMatchCss', undefined, undefined, options) +
'\n\n' +
(diffString && diffString.includes('- Expect')
? `Difference:\n\n${diffString}`
: `Expected: ${this.utils.printExpected(expected)}\n` +
`Received: ${this.utils.printReceived(actual)}`)
)
}
return { actual: received, message, pass }
},
})