2020-08-12 19:47:21 -04:00
import postcss from 'postcss'
import resolveConfig from '../src/util/resolveConfig'
import defaultConfig from '../stubs/defaultConfig.stub.js'
2020-08-19 09:33:03 -04:00
import tailwind from '../src/index'
2020-08-12 19:47:21 -04:00
2020-08-19 09:33:03 -04:00
function run ( input , config = { } ) {
return postcss ( [
tailwind ( { experimental : { applyComplexClasses : true } , ... config } ) ,
] ) . process ( input , { from : undefined } )
2020-08-12 19:47:21 -04:00
}
test ( 'it copies class declarations into itself' , ( ) => {
const output = '.a { color: red; } .b { color: red; }'
2020-08-22 00:06:47 +02:00
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( '.a { color: red; } .b { @apply a; }' ) . then ( ( result ) => {
2020-08-19 09:33:03 -04:00
expect ( result . css ) . toMatchCss ( output )
2020-08-12 19:47:21 -04:00
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
2020-08-22 00:03:42 +02:00
test ( 'apply values can contain tabs' , ( ) => {
const input = `
. a {
@ apply p - 4 \ tm - 4 ;
}
`
const expected = `
. a {
margin : 1 rem ;
padding : 1 rem ;
}
`
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input ) . then ( ( result ) => {
2020-08-22 00:03:42 +02:00
expect ( result . css ) . toMatchCss ( expected )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
test ( 'apply values can contain newlines' , ( ) => {
const input = `
. a {
@ apply p - 4 m - 4
flex flex - col ;
}
`
const expected = `
. a {
display : flex ;
flex - direction : column ;
margin : 1 rem ;
padding : 1 rem ;
}
`
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input ) . then ( ( result ) => {
2020-08-22 00:03:42 +02:00
expect ( result . css ) . toMatchCss ( expected )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
2020-08-12 19:47:21 -04:00
test ( 'selectors with invalid characters do not need to be manually escaped' , ( ) => {
const input = `
. a \ \ : 1 \ \ / 2 { color : red ; }
. b { @ apply a : 1 / 2 ; }
`
const expected = `
. a \ \ : 1 \ \ / 2 { color : red ; }
. b { color : red ; }
`
2020-08-22 00:06:47 +02:00
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input ) . then ( ( result ) => {
2020-08-13 20:46:27 -04:00
expect ( result . css ) . toMatchCss ( expected )
2020-08-12 19:47:21 -04:00
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
2020-08-13 12:14:26 -04:00
test ( 'it removes important from applied classes by default' , ( ) => {
2020-08-12 19:47:21 -04:00
const input = `
. a { color : red ! important ; }
2020-08-28 08:17:18 -04:00
. a : hover { color : blue ! important ; }
2020-08-12 19:47:21 -04:00
. b { @ apply a ; }
`
const expected = `
. a { color : red ! important ; }
2020-08-28 08:17:18 -04:00
. a : hover { color : blue ! important ; }
2020-08-12 19:47:21 -04:00
. b { color : red ; }
2020-08-28 08:17:18 -04:00
. b : hover { color : blue ; }
2020-08-12 19:47:21 -04:00
`
2020-08-22 00:06:47 +02:00
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input ) . then ( ( result ) => {
2020-08-13 20:46:27 -04:00
expect ( result . css ) . toMatchCss ( expected )
2020-08-12 19:47:21 -04:00
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
2020-08-13 12:14:26 -04:00
test ( 'applied rules can be made !important' , ( ) => {
2020-08-12 19:47:21 -04:00
const input = `
. a { color : red ; }
. b { @ apply a ! important ; }
`
const expected = `
. a { color : red ; }
. b { color : red ! important ; }
`
2020-08-22 00:06:47 +02:00
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input ) . then ( ( result ) => {
2020-08-13 20:46:27 -04:00
expect ( result . css ) . toMatchCss ( expected )
2020-08-12 19:47:21 -04:00
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
2020-08-13 07:51:46 -04:00
test ( 'cssnext custom property sets are no longer supported' , ( ) => {
2020-08-12 19:47:21 -04:00
const input = `
. a {
color : red ;
}
. b {
@ apply a -- custom - property - set ;
}
`
2020-08-22 00:06:47 +02:00
expect . assertions ( 1 )
2020-10-16 15:39:44 -04:00
return run ( input ) . catch ( ( e ) => {
2020-08-13 07:51:46 -04:00
expect ( e ) . toMatchObject ( { name : 'CssSyntaxError' } )
2020-08-12 19:47:21 -04:00
} )
} )
test ( 'it fails if the class does not exist' , ( ) => {
2020-08-22 00:06:47 +02:00
expect . assertions ( 1 )
2020-10-16 15:39:44 -04:00
return run ( '.b { @apply a; }' ) . catch ( ( e ) => {
2020-08-12 19:47:21 -04:00
expect ( e ) . toMatchObject ( { name : 'CssSyntaxError' } )
} )
} )
test ( 'applying classes that are defined in a media query is supported' , ( ) => {
const input = `
@ media ( min - width : 300 px ) {
. a { color : blue ; }
}
. b {
@ apply a ;
}
`
const output = `
@ media ( min - width : 300 px ) {
. a { color : blue ; }
}
@ media ( min - width : 300 px ) {
. b { color : blue ; }
}
`
2020-08-22 00:06:47 +02:00
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input ) . then ( ( result ) => {
2020-08-12 19:47:21 -04:00
expect ( result . css ) . toMatchCss ( output )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
test ( 'applying classes that are used in a media query is supported' , ( ) => {
const input = `
. a {
color : red ;
}
@ media ( min - width : 300 px ) {
. a { color : blue ; }
}
. b {
@ apply a ;
}
`
const output = `
. a {
color : red ;
}
@ media ( min - width : 300 px ) {
. a { color : blue ; }
}
. b {
color : red ;
}
@ media ( min - width : 300 px ) {
. b { color : blue ; }
}
`
2020-08-22 00:06:47 +02:00
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input ) . then ( ( result ) => {
2020-08-12 19:47:21 -04:00
expect ( result . css ) . toMatchCss ( output )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
test ( 'it matches classes that include pseudo-selectors' , ( ) => {
const input = `
. a : hover {
color : red ;
}
. b {
@ apply a ;
}
`
const output = `
. a : hover {
color : red ;
}
. b : hover {
color : red ;
}
`
2020-08-22 00:06:47 +02:00
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input ) . then ( ( result ) => {
2020-08-12 19:47:21 -04:00
expect ( result . css ) . toMatchCss ( output )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
test ( 'it matches classes that have multiple rules' , ( ) => {
const input = `
. a {
color : red ;
}
. b {
@ apply a ;
}
. a {
color : blue ;
}
`
const output = `
. a {
color : red ;
}
. b {
color : red ;
color : blue ;
}
. a {
color : blue ;
}
`
2020-08-22 00:06:47 +02:00
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input ) . then ( ( result ) => {
2020-08-12 19:47:21 -04:00
expect ( result . css ) . toMatchCss ( output )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
2020-08-14 19:12:45 -04:00
test ( 'applying a class that appears multiple times in one selector' , ( ) => {
const input = `
. a + . a > . a {
color : red ;
}
. b {
@ apply a ;
}
`
const output = `
. a + . a > . a {
color : red ;
}
. b + . a > . a {
color : red ;
}
. a + . b > . a {
color : red ;
}
. a + . a > . b {
color : red ;
}
`
2020-08-22 00:06:47 +02:00
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input ) . then ( ( result ) => {
2020-08-14 19:12:45 -04:00
expect ( result . css ) . toMatchCss ( output )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
2020-08-13 12:14:26 -04:00
test ( 'you can apply utility classes that do not actually exist as long as they would exist if utilities were being generated' , ( ) => {
2020-08-12 19:47:21 -04:00
const input = `
. foo { @ apply mt - 4 ; }
`
const expected = `
. foo { margin - top : 1 rem ; }
`
2020-08-22 00:06:47 +02:00
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input ) . then ( ( result ) => {
2020-08-13 20:46:27 -04:00
expect ( result . css ) . toMatchCss ( expected )
2020-08-12 19:47:21 -04:00
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
2020-08-13 20:16:56 -04:00
test ( 'the shadow lookup is only used if no @tailwind rules were in the source tree' , ( ) => {
const input = `
@ tailwind base ;
. foo { @ apply mt - 4 ; }
`
2020-08-22 00:06:47 +02:00
expect . assertions ( 1 )
2020-10-16 15:39:44 -04:00
return run ( input ) . catch ( ( e ) => {
2020-08-13 20:16:56 -04:00
expect ( e ) . toMatchObject ( { name : 'CssSyntaxError' } )
} )
} )
2020-08-13 20:46:27 -04:00
test ( 'you can apply a class that is defined in multiple rules' , ( ) => {
const input = `
. foo {
color : red ;
}
. bar {
@ apply foo ;
}
. foo {
2020-08-14 11:15:17 -04:00
opacity : . 5 ;
2020-08-13 20:46:27 -04:00
}
`
const expected = `
. foo {
color : red ;
}
. bar {
color : red ;
2020-08-14 11:15:17 -04:00
opacity : . 5 ;
2020-08-13 20:46:27 -04:00
}
. foo {
2020-08-14 11:15:17 -04:00
opacity : . 5 ;
2020-08-13 20:46:27 -04:00
}
`
2020-08-22 00:06:47 +02:00
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input ) . then ( ( result ) => {
2020-08-13 20:46:27 -04:00
expect ( result . css ) . toMatchCss ( expected )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
test ( 'you can apply a class that is defined in a media query' , ( ) => {
const input = `
. foo {
@ apply sm : text - center ;
}
`
const expected = `
@ media ( min - width : 640 px ) {
. foo {
text - align : center
}
}
`
2020-08-22 00:06:47 +02:00
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input ) . then ( ( result ) => {
2020-08-13 20:46:27 -04:00
expect ( result . css ) . toMatchCss ( expected )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
test ( 'you can apply pseudo-class variant utilities' , ( ) => {
const input = `
. foo {
@ apply hover : opacity - 50 ;
}
`
const expected = `
. foo : hover {
opacity : 0.5
}
`
2020-08-22 00:06:47 +02:00
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input ) . then ( ( result ) => {
2020-08-13 20:46:27 -04:00
expect ( result . css ) . toMatchCss ( expected )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
test ( 'you can apply responsive pseudo-class variant utilities' , ( ) => {
const input = `
. foo {
@ apply sm : hover : opacity - 50 ;
}
`
const expected = `
@ media ( min - width : 640 px ) {
. foo : hover {
opacity : 0.5
}
}
`
2020-08-22 00:06:47 +02:00
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input ) . then ( ( result ) => {
2020-08-13 20:46:27 -04:00
expect ( result . css ) . toMatchCss ( expected )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
test ( 'you can apply the container component' , ( ) => {
const input = `
. foo {
@ apply container ;
}
`
const expected = `
. foo {
width : 100 % ;
}
@ media ( min - width : 640 px ) {
. foo {
max - width : 640 px ;
}
}
@ media ( min - width : 768 px ) {
. foo {
max - width : 768 px ;
}
}
@ media ( min - width : 1024 px ) {
. foo {
max - width : 1024 px ;
}
}
@ media ( min - width : 1280 px ) {
. foo {
max - width : 1280 px ;
}
}
`
2020-08-22 00:06:47 +02:00
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input ) . then ( ( result ) => {
2020-08-13 20:46:27 -04:00
expect ( result . css ) . toMatchCss ( expected )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
test ( 'classes are applied according to CSS source order, not apply order' , ( ) => {
const input = `
. foo {
color : red ;
}
. bar {
color : blue ;
}
. baz {
@ apply bar foo ;
}
`
const expected = `
. foo {
color : red ;
}
. bar {
color : blue ;
}
. baz {
color : red ;
color : blue ;
}
`
2020-08-22 00:06:47 +02:00
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input ) . then ( ( result ) => {
2020-08-13 20:46:27 -04:00
expect ( result . css ) . toMatchCss ( expected )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
test ( 'you can apply utilities with multi-class selectors like group-hover variants' , ( ) => {
const input = `
. foo {
@ apply group - hover : bar ;
}
. bar {
color : blue ;
}
. group : hover . group - hover \ \ : bar {
color : blue ;
}
`
const expected = `
. group : hover . foo {
color : blue ;
}
. bar {
color : blue ;
}
. group : hover . group - hover \ \ : bar {
color : blue ;
}
`
2020-08-22 00:06:47 +02:00
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input ) . then ( ( result ) => {
2020-08-13 20:46:27 -04:00
expect ( result . css ) . toMatchCss ( expected )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
test ( 'you can apply classes recursively' , ( ) => {
const input = `
. foo {
@ apply bar ;
}
. bar {
@ apply baz ;
}
. baz {
color : blue ;
}
`
const expected = `
. foo {
color : blue ;
}
. bar {
color : blue ;
}
. baz {
color : blue ;
}
`
2020-08-22 00:06:47 +02:00
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input ) . then ( ( result ) => {
2020-08-13 20:46:27 -04:00
expect ( result . css ) . toMatchCss ( expected )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
test ( 'applied classes are always inserted before subsequent declarations in the same rule, even if it means moving those subsequent declarations to a new rule' , ( ) => {
const input = `
. foo {
background : blue ;
@ apply opacity - 50 hover : opacity - 100 text - right sm : align - middle ;
color : red ;
}
`
const expected = `
. foo {
background : blue ;
opacity : 0.5 ;
}
. foo : hover {
opacity : 1 ;
}
. foo {
text - align : right ;
}
@ media ( min - width : 640 px ) {
. foo {
vertical - align : middle ;
}
}
. foo {
color : red ;
}
`
2020-08-22 00:06:47 +02:00
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input ) . then ( ( result ) => {
2020-08-13 20:46:27 -04:00
expect ( result . css ) . toMatchCss ( expected )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
test ( 'adjacent rules are collapsed after being applied' , ( ) => {
const input = `
. foo {
@ apply hover : bg - white hover : opacity - 50 absolute text - right sm : align - middle sm : text - center ;
}
`
const expected = `
. foo : hover {
-- bg - opacity : 1 ;
background - color : rgba ( 255 , 255 , 255 , var ( -- bg - opacity ) ) ;
opacity : 0.5 ;
}
. foo {
position : absolute ;
text - align : right ;
}
@ media ( min - width : 640 px ) {
. foo {
text - align : center ;
vertical - align : middle ;
}
}
`
2020-08-22 00:06:47 +02:00
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input ) . then ( ( result ) => {
2020-08-13 20:46:27 -04:00
expect ( result . css ) . toMatchCss ( expected )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
test ( 'applying a class applies all instances of that class, even complex selectors' , ( ) => {
const input = `
h1 > p : hover . banana : first - child * {
@ apply bar ;
}
. bar {
color : blue ;
}
@ media ( print ) {
@ supports ( display : grid ) {
. baz . bar : hover {
text - align : right ;
float : left ;
}
}
}
`
const expected = `
h1 > p : hover . banana : first - child * {
color : blue ;
}
@ media ( print ) {
@ supports ( display : grid ) {
. baz h1 > p : hover . banana : first - child * : hover {
text - align : right ;
float : left ;
}
}
}
. bar {
color : blue ;
}
@ media ( print ) {
@ supports ( display : grid ) {
. baz . bar : hover {
text - align : right ;
float : left ;
}
}
}
`
2020-08-22 00:06:47 +02:00
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input ) . then ( ( result ) => {
2020-08-13 20:46:27 -04:00
expect ( result . css ) . toMatchCss ( expected )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
test ( 'you can apply classes to rules within at-rules' , ( ) => {
const input = `
@ supports ( display : grid ) {
. baz . bar {
@ apply text - right float - left hover : opacity - 50 md : float - right ;
}
}
`
const expected = `
@ supports ( display : grid ) {
. baz . bar {
float : left ;
}
. baz . bar : hover {
opacity : 0.5 ;
}
. baz . bar {
text - align : right ;
}
@ media ( min - width : 768 px ) {
. baz . bar {
float : right ;
}
}
}
`
2020-08-22 00:06:47 +02:00
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input ) . then ( ( result ) => {
2020-08-13 20:46:27 -04:00
expect ( result . css ) . toMatchCss ( expected )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
2020-08-14 11:15:45 -04:00
describe ( 'using apply with the prefix option' , ( ) => {
test ( 'applying a class including the prefix' , ( ) => {
const input = `
. foo { @ apply tw - mt - 4 ; }
`
2020-08-12 19:47:21 -04:00
2020-08-14 11:15:45 -04:00
const expected = `
. foo { margin - top : 1 rem ; }
`
2020-08-12 19:47:21 -04:00
2020-08-14 11:15:45 -04:00
const config = resolveConfig ( [
{
... defaultConfig ,
prefix : 'tw-' ,
} ,
] )
2020-08-12 19:47:21 -04:00
2020-08-22 00:06:47 +02:00
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input , config ) . then ( ( result ) => {
2020-08-14 11:15:45 -04:00
expect ( result . css ) . toMatchCss ( expected )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
2020-08-12 19:47:21 -04:00
} )
2020-08-14 11:15:45 -04:00
test ( 'applying a class including the prefix when using a prefix function' , ( ) => {
const input = `
. foo { @ apply tw - func - mt - 4 ; }
`
2020-08-12 19:47:21 -04:00
2020-08-14 11:15:45 -04:00
const expected = `
. foo { margin - top : 1 rem ; }
`
2020-08-12 19:47:21 -04:00
2020-08-14 11:15:45 -04:00
const config = resolveConfig ( [
{
... defaultConfig ,
prefix : ( ) => {
return 'tw-func-'
} ,
2020-08-12 19:47:21 -04:00
} ,
2020-08-14 11:15:45 -04:00
] )
2020-08-12 19:47:21 -04:00
2020-08-22 00:06:47 +02:00
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input , config ) . then ( ( result ) => {
2020-08-14 11:15:45 -04:00
expect ( result . css ) . toMatchCss ( expected )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
test ( 'applying a class without the prefix fails' , ( ) => {
const input = `
. foo { @ apply mt - 4 ; }
`
const config = resolveConfig ( [
{
... defaultConfig ,
prefix : 'tw-' ,
} ,
] )
2020-08-22 00:06:47 +02:00
expect . assertions ( 1 )
2020-10-16 15:39:44 -04:00
return run ( input , config ) . catch ( ( e ) => {
2020-08-14 11:15:45 -04:00
expect ( e ) . toMatchObject ( { name : 'CssSyntaxError' } )
} )
} )
test ( 'custom classes with no prefix can be applied' , ( ) => {
const input = `
. foo { @ apply mt - 4 ; }
. mt - 4 { color : red ; }
`
const expected = `
. foo { color : red ; }
. mt - 4 { color : red ; }
`
const config = resolveConfig ( [
{
... defaultConfig ,
prefix : 'tw-' ,
} ,
] )
2020-08-22 00:06:47 +02:00
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input , config ) . then ( ( result ) => {
2020-08-14 11:15:45 -04:00
expect ( result . css ) . toMatchCss ( expected )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
test ( 'built-in prefixed utilities can be extended and applied' , ( ) => {
const input = `
. foo { @ apply tw - mt - 4 ; }
. tw - mt - 4 { color : red ; }
`
const expected = `
. foo { margin - top : 1 rem ; color : red ; }
. tw - mt - 4 { color : red ; }
`
const config = resolveConfig ( [
{
... defaultConfig ,
prefix : 'tw-' ,
} ,
] )
2020-08-22 00:06:47 +02:00
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input , config ) . then ( ( result ) => {
2020-08-14 11:15:45 -04:00
expect ( result . css ) . toMatchCss ( expected )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
test ( 'a helpful error message is provided if it appears the user forgot to include their prefix' , ( ) => {
const input = `
. foo { @ apply mt - 4 ; }
`
const config = resolveConfig ( [
{
... defaultConfig ,
prefix : 'tw-' ,
} ,
] )
expect . assertions ( 1 )
2020-10-16 15:39:44 -04:00
return run ( input , config ) . catch ( ( e ) => {
2020-08-14 11:15:45 -04:00
expect ( e ) . toMatchObject ( {
name : 'CssSyntaxError' ,
reason : 'The `mt-4` class does not exist, but `tw-mt-4` does. Did you forget the prefix?' ,
} )
} )
2020-08-12 19:47:21 -04:00
} )
2020-08-14 12:23:28 -04:00
test ( 'you can apply classes with important and a prefix enabled' , ( ) => {
const input = `
. foo { @ apply tw - mt - 4 ; }
`
const expected = `
. foo { margin - top : 1 rem ; }
`
const config = resolveConfig ( [
{
... defaultConfig ,
prefix : 'tw-' ,
important : true ,
} ,
] )
2020-08-22 00:06:47 +02:00
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input , config ) . then ( ( result ) => {
2020-08-14 12:23:28 -04:00
expect ( result . css ) . toMatchCss ( expected )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
test ( 'you can apply classes with an important selector and a prefix enabled' , ( ) => {
const input = `
. foo { @ apply tw - mt - 4 ; }
`
const expected = `
. foo { margin - top : 1 rem ; }
`
const config = resolveConfig ( [
{
... defaultConfig ,
prefix : 'tw-' ,
important : '#app' ,
} ,
] )
2020-08-22 00:06:47 +02:00
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input , config ) . then ( ( result ) => {
2020-08-14 12:23:28 -04:00
expect ( result . css ) . toMatchCss ( expected )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
2020-08-12 19:47:21 -04:00
} )
2020-08-14 12:23:28 -04:00
test ( 'you can apply utility classes when a selector is used for the important option' , ( ) => {
2020-08-12 19:47:21 -04:00
const input = `
2020-08-13 12:14:26 -04:00
. foo {
@ apply mt - 8 mb - 8 ;
}
2020-08-12 19:47:21 -04:00
`
const expected = `
2020-08-13 12:14:26 -04:00
. foo {
margin - top : 2 rem ;
margin - bottom : 2 rem ;
}
2020-08-12 19:47:21 -04:00
`
const config = resolveConfig ( [
{
... defaultConfig ,
important : '#app' ,
} ,
] )
2020-08-22 00:06:47 +02:00
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input , config ) . then ( ( result ) => {
2020-08-13 20:46:27 -04:00
expect ( result . css ) . toMatchCss ( expected )
2020-08-12 19:47:21 -04:00
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
2020-08-20 16:29:07 -04:00
test ( 'you can apply classes to a rule with multiple selectors' , ( ) => {
const input = `
@ supports ( display : grid ) {
. foo , h1 > . bar * {
@ apply float - left opacity - 50 hover : opacity - 100 md : float - right ;
}
}
`
const expected = `
@ supports ( display : grid ) {
. foo , h1 > . bar * {
float : left ;
opacity : 0.5 ;
}
. foo : hover , h1 > . bar * : hover {
opacity : 1 ;
}
@ media ( min - width : 768 px ) {
. foo , h1 > . bar * {
float : right ;
}
}
}
`
2020-10-16 15:39:44 -04:00
return run ( input ) . then ( ( result ) => {
2020-08-20 16:29:07 -04:00
expect ( result . css ) . toMatchCss ( expected )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
2020-09-07 02:36:09 +02:00
test ( 'you can apply classes in a nested rule' , ( ) => {
const input = `
. selector {
& : hover {
@ apply text - white ;
}
}
`
const expected = `
. selector {
& : hover {
-- text - opacity : 1 ;
color : rgba ( 255 , 255 , 255 , var ( -- text - opacity ) ) ;
}
}
`
2020-10-16 15:39:44 -04:00
return run ( input ) . then ( ( result ) => {
2020-09-07 02:36:09 +02:00
expect ( result . css ) . toMatchCss ( expected )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
test ( 'you can apply classes in a nested @atrule' , ( ) => {
const input = `
. selector {
@ media ( min - width : 200 px ) {
@ apply overflow - hidden ;
}
}
`
const expected = `
. selector {
@ media ( min - width : 200 px ) {
overflow : hidden ;
}
}
`
2020-10-16 15:39:44 -04:00
return run ( input ) . then ( ( result ) => {
2020-09-07 02:36:09 +02:00
expect ( result . css ) . toMatchCss ( expected )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
test ( 'you can apply classes in a custom nested @atrule' , ( ) => {
const input = `
. selector {
@ screen md {
@ apply w - 2 / 6 ;
}
}
`
const expected = `
. selector {
@ media ( min - width : 768 px ) {
width : 33.333333 % ;
}
}
`
2020-10-16 15:39:44 -04:00
return run ( input ) . then ( ( result ) => {
2020-09-07 02:36:09 +02:00
expect ( result . css ) . toMatchCss ( expected )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
test ( 'you can deeply apply classes in a custom nested @atrule' , ( ) => {
const input = `
. selector {
. subselector {
@ screen md {
@ apply w - 2 / 6 ;
}
}
}
`
const expected = `
. selector {
. subselector {
@ media ( min - width : 768 px ) {
width : 33.333333 %
}
}
}
`
2020-10-16 15:39:44 -04:00
return run ( input ) . then ( ( result ) => {
2020-09-07 02:36:09 +02:00
expect ( result . css ) . toMatchCss ( expected )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
2020-09-13 09:44:19 -04:00
test ( 'declarations within a rule that uses @apply can be !important' , ( ) => {
const input = `
. foo {
@ apply text - center ;
float : left ;
display : block ! important ;
}
`
const expected = `
. foo {
text - align : center ;
float : left ;
display : block ! important ;
}
`
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input ) . then ( ( result ) => {
2020-09-13 09:44:19 -04:00
expect ( result . css ) . toMatchCss ( expected )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )
test ( 'declarations within a rule that uses @apply with !important remain not !important' , ( ) => {
const input = `
. foo {
@ apply text - center ! important ;
float : left ;
display : block ! important ;
}
`
const expected = `
. foo {
text - align : center ! important ;
float : left ;
display : block ! important ;
}
`
expect . assertions ( 2 )
2020-10-16 15:39:44 -04:00
return run ( input ) . then ( ( result ) => {
2020-09-13 09:44:19 -04:00
expect ( result . css ) . toMatchCss ( expected )
expect ( result . warnings ( ) . length ) . toBe ( 0 )
} )
} )