use `lightningcss` and `prettier` for `toMatchFormattedCss`
Lightning CSS applies some optimizations and prettier ensures that the
output is always formatted in the same way.
In a future version, we will be using Lightning CSS to apply
optimizations like handling the nesting, optimizing selectors, sorting
declarations, simplifying colors and so on.
To guarantee that we have the same output in both the normal version and
OXIDE version, we can apply lightningcss in our tests so that it always
produces correct results in both version with the same optimizations
applied.
This also aliases `toMatchCss` to `toMatchFormattedCss` so that we can
guarantee the same output. This has a small caveat where `lightningcss`
is pretty strict. It will complain about `@media screen(md) {}` for
example. This is correct because it is not valid CSS, but we eventually
take care of it.
In this case, we will catch the error and use prettier instead (since
this should only happen in tests that doesn't use end-to-end tests, but
uses a more specialized test instead). If prettier still finds an error,
we will ensure to throw the original error.
Eventually, all the "lower" level tests, should probably become higher
level end-to-end tests. But let's do everything step by step!
135 lines
3.3 KiB
JavaScript
135 lines
3.3 KiB
JavaScript
import { run, html, css } from './util/run'
|
|
import { env } from '../src/lib/sharedState'
|
|
|
|
// This is only an issue in the non-oxide version. In fact, we _do_ want nesting in the oxide
|
|
// version!
|
|
let group = env.OXIDE ? describe.skip : describe
|
|
|
|
group('detect-nesting', () => {
|
|
it('should warn when we detect nested css', () => {
|
|
let config = {
|
|
content: [{ raw: html`<div class="nested"></div>` }],
|
|
}
|
|
|
|
let input = css`
|
|
@tailwind utilities;
|
|
|
|
.nested {
|
|
.example {
|
|
}
|
|
}
|
|
`
|
|
|
|
return run(input, config).then((result) => {
|
|
expect(result.messages).toHaveLength(1)
|
|
expect(result.messages).toMatchObject([
|
|
{
|
|
type: 'warning',
|
|
text: [
|
|
'Nested CSS was detected, but CSS nesting has not been configured correctly.',
|
|
'Please enable a CSS nesting plugin *before* Tailwind in your configuration.',
|
|
'See how here: https://tailwindcss.com/docs/using-with-preprocessors#nesting',
|
|
].join('\n'),
|
|
},
|
|
])
|
|
})
|
|
})
|
|
|
|
it('should not warn when we detect nested css inside css @layer rules', () => {
|
|
let config = {
|
|
content: [{ raw: html`<div class="underline"></div>` }],
|
|
}
|
|
|
|
let input = css`
|
|
@layer tw-base, tw-components, tw-utilities;
|
|
@layer tw-utilities {
|
|
@tailwind utilities;
|
|
}
|
|
`
|
|
|
|
return run(input, config).then((result) => {
|
|
expect(result.css).toMatchFormattedCss(css`
|
|
@layer tw-base, tw-components, tw-utilities;
|
|
@layer tw-utilities {
|
|
.underline {
|
|
text-decoration-line: underline;
|
|
}
|
|
}
|
|
`)
|
|
expect(result.messages).toHaveLength(0)
|
|
})
|
|
})
|
|
|
|
it('should warn when we detect namespaced @tailwind at rules', () => {
|
|
let config = {
|
|
content: [{ raw: html`<div class="text-center"></div>` }],
|
|
}
|
|
|
|
let input = css`
|
|
.namespace {
|
|
@tailwind utilities;
|
|
}
|
|
`
|
|
|
|
return run(input, config).then((result) => {
|
|
expect(result.messages).toHaveLength(1)
|
|
expect(result.messages).toMatchObject([
|
|
{
|
|
type: 'warning',
|
|
text: [
|
|
'Nested @tailwind rules were detected, but are not supported.',
|
|
"Consider using a prefix to scope Tailwind's classes: https://tailwindcss.com/docs/configuration#prefix",
|
|
'Alternatively, use the important selector strategy: https://tailwindcss.com/docs/configuration#selector-strategy',
|
|
].join('\n'),
|
|
},
|
|
])
|
|
})
|
|
})
|
|
|
|
it('should not warn when nesting a single rule inside a media query', () => {
|
|
let config = {
|
|
content: [{ raw: html`<div class="nested"></div>` }],
|
|
}
|
|
|
|
let input = css`
|
|
@tailwind utilities;
|
|
|
|
@media (min-width: 768px) {
|
|
.nested {
|
|
}
|
|
}
|
|
`
|
|
|
|
return run(input, config).then((result) => {
|
|
expect(result.messages).toHaveLength(0)
|
|
expect(result.messages).toEqual([])
|
|
})
|
|
})
|
|
|
|
it('should only warn for the first detected nesting ', () => {
|
|
let config = {
|
|
content: [{ raw: html`<div class="nested other"></div>` }],
|
|
}
|
|
|
|
let input = css`
|
|
@tailwind utilities;
|
|
|
|
.nested {
|
|
.example {
|
|
}
|
|
|
|
.other {
|
|
}
|
|
}
|
|
|
|
.other {
|
|
.example {
|
|
}
|
|
}
|
|
`
|
|
|
|
return run(input, config).then((result) => {
|
|
expect(result.messages).toHaveLength(1)
|
|
})
|
|
})
|
|
})
|