tailwindcss/__tests__/processPlugins.test.js
2018-03-05 09:58:35 -05:00

498 lines
10 KiB
JavaScript

import _ from 'lodash'
import postcss from 'postcss'
import processPlugins from '../src/util/processPlugins'
function css(nodes) {
return postcss.root({ nodes }).toString()
}
test('plugins can create utilities', () => {
const [components, utilities] = processPlugins({
plugins: [
function({ rule, addUtilities }) {
addUtilities([
rule('.object-fill', {
'object-fit': 'fill',
}),
rule('.object-contain', {
'object-fit': 'contain',
}),
rule('.object-cover', {
'object-fit': 'cover',
}),
])
},
],
})
expect(components.length).toBe(0)
expect(css(utilities)).toMatchCss(`
@variants {
.object-fill {
object-fit: fill
}
.object-contain {
object-fit: contain
}
.object-cover {
object-fit: cover
}
}
`)
})
test('plugins can create utilities with variants', () => {
const [components, utilities] = processPlugins({
plugins: [
function({ rule, addUtilities }) {
addUtilities(
[
rule('.object-fill', {
'object-fit': 'fill',
}),
rule('.object-contain', {
'object-fit': 'contain',
}),
rule('.object-cover', {
'object-fit': 'cover',
}),
],
['responsive', 'hover', 'group-hover', 'focus']
)
},
],
})
expect(components.length).toBe(0)
expect(css(utilities)).toMatchCss(`
@variants responsive, hover, group-hover, focus {
.object-fill {
object-fit: fill
}
.object-contain {
object-fit: contain
}
.object-cover {
object-fit: cover
}
}
`)
})
test('plugins can create components', () => {
const [components, utilities] = processPlugins({
plugins: [
function({ rule, addComponents }) {
addComponents([
rule('.btn-blue', {
'background-color': 'blue',
color: 'white',
padding: '.5rem 1rem',
'border-radius': '.25rem',
}),
rule('.btn-blue:hover', {
'background-color': 'darkblue',
}),
])
},
],
})
expect(utilities.length).toBe(0)
expect(css(components)).toMatchCss(`
.btn-blue {
background-color: blue;
color: white;
padding: .5rem 1rem;
border-radius: .25rem
}
.btn-blue:hover {
background-color: darkblue
}
`)
})
test('plugins can create components with media queries', () => {
const [components, utilities] = processPlugins({
plugins: [
function({ rule, atRule, addComponents }) {
addComponents([
rule('.container', {
width: '100%',
}),
atRule('@media (min-width: 100px)', [
rule('.container', {
'max-width': '100px',
}),
]),
atRule('@media (min-width: 200px)', [
rule('.container', {
'max-width': '200px',
}),
]),
atRule('@media (min-width: 300px)', [
rule('.container', {
'max-width': '300px',
}),
]),
])
},
],
})
expect(utilities.length).toBe(0)
expect(css(components)).toMatchCss(`
.container {
width: 100%
}
@media (min-width: 100px) {
.container {
max-width: 100px
}
}
@media (min-width: 200px) {
.container {
max-width: 200px
}
}
@media (min-width: 300px) {
.container {
max-width: 300px
}
}
`)
})
test('plugins can create rules with escaped selectors', () => {
const config = {
plugins: [
function({ e, rule, addUtilities }) {
addUtilities(
[
rule(`.${e('top-1/4')}`, {
top: '25%',
}),
],
[]
)
},
],
}
const [components, utilities] = processPlugins(config)
expect(components.length).toBe(0)
expect(css(utilities)).toMatchCss(`
@variants {
.top-1\\/4 {
top: 25%
}
}
`)
})
test('plugins can access the current config', () => {
const [components, utilities] = processPlugins({
screens: {
sm: '576px',
md: '768px',
lg: '992px',
xl: '1200px',
},
plugins: [
function({ rule, atRule, addComponents, config }) {
const containerClasses = [
rule('.container', {
width: '100%',
}),
]
_.forEach(config('screens'), breakpoint => {
const mediaQuery = atRule(`@media (min-width: ${breakpoint})`, [
rule('.container', { 'max-width': breakpoint }),
])
containerClasses.push(mediaQuery)
})
addComponents(containerClasses)
},
],
})
expect(utilities.length).toBe(0)
expect(css(components)).toMatchCss(`
.container {
width: 100%
}
@media (min-width: 576px) {
.container {
max-width: 576px
}
}
@media (min-width: 768px) {
.container {
max-width: 768px
}
}
@media (min-width: 992px) {
.container {
max-width: 992px
}
}
@media (min-width: 1200px) {
.container {
max-width: 1200px
}
}
`)
})
test('plugins can provide fallbacks to keys missing from the config', () => {
const [components, utilities] = processPlugins({
borderRadius: {
'1': '1px',
'2': '2px',
'4': '4px',
'8': '8px',
},
plugins: [
function({ rule, addComponents, config }) {
addComponents([
rule('.btn', {
'border-radius': config('borderRadius.default', '.25rem'),
}),
])
},
],
})
expect(utilities.length).toBe(0)
expect(css(components)).toMatchCss(`
.btn {
border-radius: .25rem
}
`)
})
test("the '@' sign is optional in at-rules", () => {
const [components, utilities] = processPlugins({
plugins: [
function({ rule, atRule, addComponents }) {
addComponents([
rule('.card', {
padding: '.5rem',
}),
atRule('media (min-width: 500px)', [
rule('.card', {
padding: '1rem',
}),
]),
atRule('@media (min-width: 800px)', [
rule('.card', {
padding: '1.5rem',
}),
]),
])
},
],
})
expect(utilities.length).toBe(0)
expect(css(components)).toMatchCss(`
.card {
padding: .5rem
}
@media (min-width: 500px) {
.card {
padding: 1rem
}
}
@media (min-width: 800px) {
.card {
padding: 1.5rem
}
}
`)
})
test('variants are optional when adding utilities', () => {
const [, utilities] = processPlugins({
plugins: [
function({ rule, addUtilities }) {
addUtilities([
rule('.border-collapse', {
'border-collapse': 'collapse',
}),
])
},
],
})
expect(css(utilities)).toMatchCss(`
@variants {
.border-collapse {
border-collapse: collapse
}
}
`)
})
test('plugins can add multiple sets of utilities and components', () => {
const [components, utilities] = processPlugins({
plugins: [
function({ rule, addUtilities, addComponents }) {
addComponents([
rule('.card', {
padding: '1rem',
'border-radius': '.25rem',
}),
])
addUtilities([
rule('.skew-12deg', {
transform: 'skewY(-12deg)',
}),
])
addComponents([
rule('.btn', {
padding: '1rem .5rem',
display: 'inline-block',
}),
])
addUtilities([
rule('.border-collapse', {
'border-collapse': 'collapse',
}),
])
},
],
})
expect(css(utilities)).toMatchCss(`
@variants {
.skew-12deg {
transform: skewY(-12deg)
}
}
@variants {
.border-collapse {
border-collapse: collapse
}
}
`)
expect(css(components)).toMatchCss(`
.card {
padding: 1rem;
border-radius: .25rem
}
.btn {
padding: 1rem .5rem;
display: inline-block
}
`)
})
test("plugins can apply the user's chosen prefix", () => {
const [, utilities] = processPlugins({
plugins: [
function({ rule, addUtilities, prefix }) {
addUtilities([
rule(prefix('.skew-12deg'), {
transform: 'skewY(-12deg)',
}),
])
},
],
options: {
prefix: 'tw-',
},
})
expect(css(utilities)).toMatchCss(`
@variants {
.tw-skew-12deg {
transform: skewY(-12deg)
}
}
`)
})
test('utilities are escaped and automatically respect prefix and important options when created via `utility`', () => {
const [, utilities] = processPlugins({
plugins: [
function({ utility, addUtilities }) {
addUtilities([
utility('.rotate-1/4', {
transform: 'rotate(90deg)',
}),
])
},
],
options: {
prefix: 'tw-',
important: true,
},
})
expect(css(utilities)).toMatchCss(`
@variants {
.tw-rotate-1\\/4 {
transform: rotate(90deg) !important
}
}
`)
})
test("leading '.' is optional when creating utilities via `utility`", () => {
const [, utilities] = processPlugins({
plugins: [
function({ utility, addUtilities }) {
addUtilities([
utility('rotate-1/4', {
transform: 'rotate(90deg)',
}),
])
},
],
options: {
prefix: 'tw-',
important: true,
},
})
expect(css(utilities)).toMatchCss(`
@variants {
.tw-rotate-1\\/4 {
transform: rotate(90deg) !important
}
}
`)
})
test('plugins can choose to make declarations !important', () => {
const [, utilities] = processPlugins({
plugins: [
function({ rule, addUtilities, config }) {
addUtilities([
rule('.skew-12deg', {
transform: `skewY(-12deg)${config('options.important') ? ' !important' : ''}`,
}),
])
},
],
options: {
important: true,
},
})
expect(css(utilities)).toMatchCss(`
@variants {
.skew-12deg {
transform: skewY(-12deg) !important
}
}
`)
})