tailwindcss/integrations/vite/tests/integration.test.js
Robin Malfait ef2ebb28d5
Explicitly configure Lightning CSS features, and prefer user browserslist over default browserslist (#11402)
* exclude `Features.LogicalProperties` lightningcss feature

We don't want this to automatically apply since we have dedicated
logical property based utilities already.

We also have a feature flag to toggle some utilities to make use of
logical property based ones.

This feature should be opt-in to prevent backwards compatibility (e.g.:
RTL sites that _did_ use a mr-4 explicitly).

* update default browserslist

* explicitly include/exclude Lightning CSS features

* update tests based on new browserslist and include/exclude features from Lightning CSS

* update integration tests

* prefer user browserslist, fallback to built-in browserslist

* always include Nesting

If a custom browserslist config is used, then we don't explicitly set
the include/exclude features from Lightning CSS (except for nesting, we
always want to process nesting)

* ensure to fallback to the current working directory

* update changelog
2023-06-09 20:37:36 +02:00

388 lines
8.5 KiB
JavaScript

require('isomorphic-fetch')
let $ = require('../../execute')
let { css, html, javascript } = require('../../syntax')
let { readOutputFile, appendToInputFile, writeInputFile, removeFile } = require('../../io')({
output: 'dist',
input: '.',
})
let PORT = 1337
async function fetchCSS() {
let response = await fetch(`http://localhost:${PORT}/index.css`, {
headers: {
Accept: 'text/css',
},
})
return response.text()
}
describe('static build', () => {
it('should be possible to generate tailwind output', async () => {
await writeInputFile(
'index.html',
html`
<link rel="stylesheet" href="./index.css" />
<div class="font-bold"></div>
`
)
await $('vite build', {
env: { NODE_ENV: 'production', NO_COLOR: '1' },
})
expect(await readOutputFile(/index.\w+\.css$/)).toIncludeCss(
css`
.font-bold {
font-weight: 700;
}
`
)
})
it('can use a tailwind.config.js configuration file with ESM syntax', async () => {
await writeInputFile(
'index.html',
html`
<link rel="stylesheet" href="./index.css" />
<div class="z-primary"></div>
`
)
await removeFile('tailwind.config.js')
await writeInputFile(
'tailwind.config.js',
javascript`
export default {
content: ['index.html'],
theme: {
extend: {
zIndex: {
primary: 0,
},
},
},
corePlugins: {
preflight: false,
},
}
`
)
await $('vite build', {
env: { NODE_ENV: 'production', NO_COLOR: '1' },
})
expect(await readOutputFile(/index.\w+\.css$/)).toIncludeCss(
css`
.z-primary {
z-index: 0;
}
`
)
})
it('can use a tailwind.config.ts configuration file', async () => {
await writeInputFile(
'index.html',
html`
<link rel="stylesheet" href="./index.css" />
<div class="z-primary"></div>
`
)
await removeFile('tailwind.config.js')
await writeInputFile(
'tailwind.config.ts',
javascript`
import type { Config } from 'tailwindcss'
export default {
content: ['index.html'],
theme: {
extend: {
zIndex: {
primary: 0,
},
},
},
corePlugins: {
preflight: false,
},
} satisfies Config
`
)
await $('vite build', {
env: { NODE_ENV: 'production', NO_COLOR: '1' },
})
expect(await readOutputFile(/index.\w+\.css$/)).toIncludeCss(
css`
.z-primary {
z-index: 0;
}
`
)
})
})
describe('watcher', () => {
test('classes are generated when the html file changes', async () => {
await writeInputFile(
'index.html',
html`
<link rel="stylesheet" href="./index.css" />
<div class="font-bold"></div>
`
)
let runningProcess = $(`vite --port ${PORT}`, {
env: { NO_COLOR: '1' },
})
await runningProcess.onStdout((message) => message.includes('ready in'))
expect(await fetchCSS()).toIncludeCss(
css`
.font-bold {
font-weight: 700;
}
`
)
await appendToInputFile('index.html', html`<div class="font-normal"></div>`)
await runningProcess.onStdout((message) => message.includes('page reload'))
expect(await fetchCSS()).toIncludeCss(
css`
.font-bold {
font-weight: 700;
}
.font-normal {
font-weight: 400;
}
`
)
await appendToInputFile('index.html', html`<div class="z-0"></div>`)
await runningProcess.onStdout((message) => message.includes('page reload'))
expect(await fetchCSS()).toIncludeCss(
css`
.z-0 {
z-index: 0;
}
.font-bold {
font-weight: 700;
}
.font-normal {
font-weight: 400;
}
`
)
return runningProcess.stop()
})
test('classes are generated when globbed files change', async () => {
await writeInputFile('index.html', html` <link rel="stylesheet" href="./index.css" /> `)
await writeInputFile('glob/index.html', html` <div class="font-bold"></div> `)
let runningProcess = $(`vite --port ${PORT}`, {
env: { NO_COLOR: '1' },
})
await runningProcess.onStdout((message) => message.includes('ready in'))
expect(await fetchCSS()).toIncludeCss(
css`
.font-bold {
font-weight: 700;
}
`
)
await appendToInputFile('glob/index.html', html`<div class="font-normal"></div>`)
await runningProcess.onStdout((message) => message.includes('page reload'))
expect(await fetchCSS()).toIncludeCss(
css`
.font-bold {
font-weight: 700;
}
.font-normal {
font-weight: 400;
}
`
)
await appendToInputFile('glob/index.html', html`<div class="z-0"></div>`)
await runningProcess.onStdout((message) => message.includes('page reload'))
expect(await fetchCSS()).toIncludeCss(
css`
.z-0 {
z-index: 0;
}
.font-bold {
font-weight: 700;
}
.font-normal {
font-weight: 400;
}
`
)
return runningProcess.stop()
})
test('classes are generated when the tailwind.config.js file changes', async () => {
await writeInputFile(
'index.html',
html`
<link rel="stylesheet" href="./index.css" />
<div class="font-bold md:font-medium"></div>
`
)
let runningProcess = $(`vite --port ${PORT}`, {
env: { NO_COLOR: '1' },
})
await runningProcess.onStdout((message) => message.includes('ready in'))
expect(await fetchCSS()).toIncludeCss(
css`
.font-bold {
font-weight: 700;
}
@media (min-width: 768px) {
.md\:font-medium {
font-weight: 500;
}
}
`
)
await writeInputFile(
'tailwind.config.js',
javascript`
module.exports = {
content: ['./index.html'],
theme: {
extend: {
screens: {
md: '800px'
},
fontWeight: {
bold: 'bold'
}
},
},
corePlugins: {
preflight: false,
},
plugins: [],
}
`
)
await runningProcess.onStdout((message) => message.includes('[vite]'))
expect(await fetchCSS()).toIncludeCss(
css`
.font-bold {
font-weight: bold;
}
@media (min-width: 800px) {
.md\:font-medium {
font-weight: 500;
}
}
`
)
return runningProcess.stop()
})
test('classes are generated when the index.css file changes', async () => {
await writeInputFile(
'index.html',
html`
<link rel="stylesheet" href="./index.css" />
<div class="btn font-bold"></div>
`
)
let runningProcess = $(`vite --port ${PORT}`, {
env: { NO_COLOR: '1' },
})
await runningProcess.onStdout((message) => message.includes('ready in'))
expect(await fetchCSS()).toIncludeCss(
css`
.font-bold {
font-weight: 700;
}
`
)
await writeInputFile(
'index.css',
css`
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
.btn {
@apply rounded px-2 py-1;
}
}
`
)
await runningProcess.onStdout((message) => message.includes('hmr update /index.css'))
expect(await fetchCSS()).toIncludeCss(
css`
.btn {
border-radius: 0.25rem;
padding: 0.25rem 0.5rem;
}
.font-bold {
font-weight: 700;
}
`
)
await writeInputFile(
'index.css',
css`
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
.btn {
@apply rounded z-0 px-2 py-1;
}
}
`
)
await runningProcess.onStdout((message) => message.includes('hmr update /index.css'))
expect(await fetchCSS()).toIncludeCss(
css`
.btn {
z-index: 0;
border-radius: 0.25rem;
padding: 0.25rem 0.5rem;
}
.font-bold {
font-weight: 700;
}
`
)
return runningProcess.stop()
})
})