import { run, html, css } from './util/run'
test('partial arbitrary variants', () => {
let config = {
content: [
{
raw: html`
`,
},
],
corePlugins: { preflight: false },
plugins: [
({ matchVariant }) => {
matchVariant('potato', (flavor) => `.potato-${flavor} &`)
},
],
}
let input = css`
@tailwind utilities;
`
return run(input, config).then((result) => {
expect(result.css).toMatchFormattedCss(css`
.potato-baked .potato-\[baked\]\:w-3 {
width: 0.75rem;
}
.potato-yellow .potato-\[yellow\]\:bg-yellow-200 {
--tw-bg-opacity: 1;
background-color: rgb(254 240 138 / var(--tw-bg-opacity));
}
`)
})
})
test('partial arbitrary variants with at-rules', () => {
let config = {
content: [
{
raw: html` `,
},
],
corePlugins: { preflight: false },
plugins: [
({ matchVariant }) => {
matchVariant('potato', (flavor) => `@media (potato: ${flavor})`)
},
],
}
let input = css`
@tailwind utilities;
`
return run(input, config).then((result) => {
expect(result.css).toMatchFormattedCss(css`
@media (potato: baked) {
.potato-\[baked\]\:w-3 {
width: 0.75rem;
}
}
@media (potato: yellow) {
.potato-\[yellow\]\:bg-yellow-200 {
--tw-bg-opacity: 1;
background-color: rgb(254 240 138 / var(--tw-bg-opacity));
}
}
`)
})
})
test('partial arbitrary variants with at-rules and placeholder', () => {
let config = {
content: [
{
raw: html` `,
},
],
corePlugins: { preflight: false },
plugins: [
({ matchVariant }) => {
matchVariant('potato', (flavor) => `@media (potato: ${flavor}) { &:potato }`)
},
],
}
let input = css`
@tailwind utilities;
`
return run(input, config).then((result) => {
expect(result.css).toMatchFormattedCss(css`
@media (potato: baked) {
.potato-\[baked\]\:w-3:potato {
width: 0.75rem;
}
}
@media (potato: yellow) {
.potato-\[yellow\]\:bg-yellow-200:potato {
--tw-bg-opacity: 1;
background-color: rgb(254 240 138 / var(--tw-bg-opacity));
}
}
`)
})
})
test('partial arbitrary variants with default values', () => {
let config = {
content: [
{
raw: html``,
},
],
corePlugins: { preflight: false },
plugins: [
({ matchVariant }) => {
matchVariant('tooltip', (side) => `&${side}`, {
values: {
bottom: '[data-location="bottom"]',
top: '[data-location="top"]',
},
})
},
],
}
let input = css`
@tailwind utilities;
`
return run(input, config).then((result) => {
expect(result.css).toMatchFormattedCss(css`
.tooltip-bottom\:mt-2[data-location='bottom'] {
margin-top: 0.5rem;
}
.tooltip-top\:mb-2[data-location='top'] {
margin-bottom: 0.5rem;
}
`)
})
})
test('matched variant values maintain the sort order they are registered in', () => {
let config = {
content: [
{
raw: html``,
},
],
corePlugins: { preflight: false },
plugins: [
({ matchVariant }) => {
matchVariant('alphabet', (side) => `&${side}`, {
values: {
a: '[data-value="a"]',
b: '[data-value="b"]',
c: '[data-value="c"]',
d: '[data-value="d"]',
},
})
},
],
}
let input = css`
@tailwind utilities;
`
return run(input, config).then((result) => {
expect(result.css).toMatchFormattedCss(css`
.alphabet-a\:underline[data-value='a'] {
text-decoration-line: underline;
}
.alphabet-b\:underline[data-value='b'] {
text-decoration-line: underline;
}
.alphabet-c\:underline[data-value='c'] {
text-decoration-line: underline;
}
.alphabet-d\:underline[data-value='d'] {
text-decoration-line: underline;
}
`)
})
})
test('matchVariant can return an array of format strings from the function', () => {
let config = {
content: [
{
raw: html``,
},
],
corePlugins: { preflight: false },
plugins: [
({ matchVariant }) => {
matchVariant('test', (selector) =>
selector.split(',').map((selector) => `&.${selector} > *`)
)
},
],
}
let input = css`
@tailwind utilities;
`
return run(input, config).then((result) => {
expect(result.css).toMatchFormattedCss(css`
.test-\[a\2c b\2c c\]\:underline.a > * {
text-decoration-line: underline;
}
.test-\[a\2c b\2c c\]\:underline.b > * {
text-decoration-line: underline;
}
.test-\[a\2c b\2c c\]\:underline.c > * {
text-decoration-line: underline;
}
`)
})
})
it('should be possible to sort variants', () => {
let config = {
content: [
{
raw: html`
`,
},
],
corePlugins: { preflight: false },
plugins: [
({ matchVariant }) => {
matchVariant('testmin', (value) => `@media (min-width: ${value})`, {
sort(a, z) {
return parseInt(a.value) - parseInt(z.value)
},
})
},
],
}
let input = css`
@tailwind utilities;
`
return run(input, config).then((result) => {
expect(result.css).toMatchFormattedCss(css`
@media (min-width: 500px) {
.testmin-\[500px\]\:underline {
text-decoration-line: underline;
}
}
@media (min-width: 700px) {
.testmin-\[700px\]\:italic {
font-style: italic;
}
}
`)
})
})
it('should be possible to compare arbitrary variants and hardcoded variants', () => {
let config = {
content: [
{
raw: html`
`,
},
],
corePlugins: { preflight: false },
plugins: [
({ matchVariant }) => {
matchVariant('testmin', (value) => `@media (min-width: ${value})`, {
values: {
example: '600px',
},
sort(a, z) {
return parseInt(a.value) - parseInt(z.value)
},
})
},
],
}
let input = css`
@tailwind utilities;
`
return run(input, config).then((result) => {
expect(result.css).toMatchFormattedCss(css`
@media (min-width: 500px) {
.testmin-\[500px\]\:italic {
font-style: italic;
}
}
@media (min-width: 600px) {
.testmin-example\:italic {
font-style: italic;
}
}
@media (min-width: 700px) {
.testmin-\[700px\]\:italic {
font-style: italic;
}
}
`)
})
})
it('should be possible to sort stacked arbitrary variants correctly', () => {
let config = {
content: [
{
raw: html`
`,
},
],
corePlugins: { preflight: false },
plugins: [
({ matchVariant }) => {
matchVariant('testmin', (value) => `@media (min-width: ${value})`, {
sort(a, z) {
return parseInt(a.value) - parseInt(z.value)
},
})
matchVariant('testmax', (value) => `@media (max-width: ${value})`, {
sort(a, z) {
return parseInt(z.value) - parseInt(a.value)
},
})
},
],
}
let input = css`
@tailwind utilities;
`
return run(input, config).then((result) => {
expect(result.css).toMatchFormattedCss(css`
@media (min-width: 100px) {
@media (max-width: 400px) {
.testmin-\[100px\]\:testmax-\[400px\]\:underline {
text-decoration-line: underline;
}
}
@media (max-width: 350px) {
.testmin-\[100px\]\:testmax-\[350px\]\:underline {
text-decoration-line: underline;
}
}
@media (max-width: 300px) {
.testmin-\[100px\]\:testmax-\[300px\]\:underline {
text-decoration-line: underline;
}
}
}
@media (min-width: 150px) {
@media (max-width: 400px) {
.testmin-\[150px\]\:testmax-\[400px\]\:underline {
text-decoration-line: underline;
}
}
}
`)
})
})
it('should maintain sort from other variants, if sort functions of arbitrary variants return 0', () => {
let config = {
content: [
{
raw: html`
`,
},
],
corePlugins: { preflight: false },
plugins: [
({ matchVariant }) => {
matchVariant('testmin', (value) => `@media (min-width: ${value})`, {
sort(a, z) {
return parseInt(a.value) - parseInt(z.value)
},
})
matchVariant('testmax', (value) => `@media (max-width: ${value})`, {
sort(a, z) {
return parseInt(z.value) - parseInt(a.value)
},
})
},
],
}
let input = css`
@tailwind utilities;
`
return run(input, config).then((result) => {
expect(result.css).toMatchFormattedCss(css`
@media (min-width: 100px) {
@media (max-width: 200px) {
.testmin-\[100px\]\:testmax-\[200px\]\:hover\:underline:hover {
text-decoration-line: underline;
}
.testmin-\[100px\]\:testmax-\[200px\]\:focus\:underline:focus {
text-decoration-line: underline;
}
}
}
`)
})
})
it('should sort arbitrary variants left to right (1)', () => {
let config = {
content: [
{
raw: html`
`,
},
],
corePlugins: { preflight: false },
plugins: [
({ matchVariant }) => {
matchVariant('testmin', (value) => `@media (min-width: ${value})`, {
sort(a, z) {
return parseInt(a.value) - parseInt(z.value)
},
})
matchVariant('testmax', (value) => `@media (max-width: ${value})`, {
sort(a, z) {
return parseInt(z.value) - parseInt(a.value)
},
})
},
],
}
let input = css`
@tailwind utilities;
`
return run(input, config).then((result) => {
expect(result.css).toMatchFormattedCss(css`
@media (min-width: 100px) {
@media (max-width: 400px) {
.testmin-\[100px\]\:testmax-\[400px\]\:underline {
text-decoration-line: underline;
}
}
@media (max-width: 300px) {
.testmin-\[100px\]\:testmax-\[300px\]\:underline {
text-decoration-line: underline;
}
}
}
@media (min-width: 200px) {
@media (max-width: 400px) {
.testmin-\[200px\]\:testmax-\[400px\]\:underline {
text-decoration-line: underline;
}
}
@media (max-width: 300px) {
.testmin-\[200px\]\:testmax-\[300px\]\:underline {
text-decoration-line: underline;
}
}
}
`)
})
})
it('should sort arbitrary variants left to right (2)', () => {
let config = {
content: [
{
raw: html`
`,
},
],
corePlugins: { preflight: false },
plugins: [
({ matchVariant }) => {
matchVariant('testmin', (value) => `@media (min-width: ${value})`, {
sort(a, z) {
return parseInt(a.value) - parseInt(z.value)
},
})
matchVariant('testmax', (value) => `@media (max-width: ${value})`, {
sort(a, z) {
return parseInt(z.value) - parseInt(a.value)
},
})
},
],
}
let input = css`
@tailwind utilities;
`
return run(input, config).then((result) => {
expect(result.css).toMatchFormattedCss(css`
@media (max-width: 400px) {
@media (min-width: 100px) {
.testmax-\[400px\]\:testmin-\[100px\]\:underline {
text-decoration-line: underline;
}
}
@media (min-width: 200px) {
.testmax-\[400px\]\:testmin-\[200px\]\:underline {
text-decoration-line: underline;
}
}
}
@media (max-width: 300px) {
@media (min-width: 100px) {
.testmax-\[300px\]\:testmin-\[100px\]\:underline {
text-decoration-line: underline;
}
}
@media (min-width: 200px) {
.testmax-\[300px\]\:testmin-\[200px\]\:underline {
text-decoration-line: underline;
}
}
}
`)
})
})
it('should guarantee that we are not passing values from other variants to the wrong function', () => {
let config = {
content: [
{
raw: html`
`,
},
],
corePlugins: { preflight: false },
plugins: [
({ matchVariant }) => {
matchVariant('testmin', (value) => `@media (min-width: ${value})`, {
sort(a, z) {
let lookup = ['100px', '200px']
if (lookup.indexOf(a.value) === -1 || lookup.indexOf(z.value) === -1) {
throw new Error('We are seeing values that should not be there!')
}
return lookup.indexOf(a.value) - lookup.indexOf(z.value)
},
})
matchVariant('testmax', (value) => `@media (max-width: ${value})`, {
sort(a, z) {
let lookup = ['300px', '400px']
if (lookup.indexOf(a.value) === -1 || lookup.indexOf(z.value) === -1) {
throw new Error('We are seeing values that should not be there!')
}
return lookup.indexOf(z.value) - lookup.indexOf(a.value)
},
})
},
],
}
let input = css`
@tailwind utilities;
`
return run(input, config).then((result) => {
expect(result.css).toMatchFormattedCss(css`
@media (min-width: 100px) {
@media (max-width: 400px) {
.testmin-\[100px\]\:testmax-\[400px\]\:underline {
text-decoration-line: underline;
}
}
@media (max-width: 300px) {
.testmin-\[100px\]\:testmax-\[300px\]\:underline {
text-decoration-line: underline;
}
}
}
@media (min-width: 200px) {
@media (max-width: 400px) {
.testmin-\[200px\]\:testmax-\[400px\]\:underline {
text-decoration-line: underline;
}
}
@media (max-width: 300px) {
.testmin-\[200px\]\:testmax-\[300px\]\:underline {
text-decoration-line: underline;
}
}
}
`)
})
})