Files
next.js/test/e2e/app-dir/experimental-lightningcss-features/experimental-lightningcss-features.test.ts
Sam PoderandGitHub 4b1c74a3bc Fix support for custom-media-queries in LightningCSS (#95689)
Closes https://github.com/vercel/next.js/issues/95677. Added an e2e test
that roughly matches the original issue and tests that it works.
2026-07-10 19:07:17 +00:00

115 lines
3.7 KiB
TypeScript

import { nextTestSetup } from 'e2e-utils'
/** Collect all CSS reachable from a page (inline <style> + linked .css). */
async function collectPageCss(
next: ReturnType<typeof nextTestSetup>['next'],
path: string
): Promise<string> {
const html = await (await next.fetch(path)).text()
let css = ''
// Inline <style> blocks
for (const m of html.matchAll(/<style[^>]*>([\s\S]*?)<\/style>/g)) {
css += m[1]
}
// External <link> stylesheets (href may contain query strings like ?dpl=...)
for (const m of html.matchAll(/<link[^>]*href="([^"]*\.css[^"]*?)"[^>]*>/g)) {
const res = await next.fetch(m[1])
if (res.ok) css += await res.text()
}
return css
}
describe('experimental-lightningcss-features', () => {
describe('include', () => {
const { next } = nextTestSetup({
files: __dirname,
dependencies: { lightningcss: '^1.23.0' },
// Chrome 123 supports light-dark() natively — using it here proves that
// the `include` flag forces transpilation regardless of browser support.
packageJson: {
browserslist: ['chrome 123'],
},
nextConfig: {
experimental: {
useLightningcss: true,
lightningCssFeatures: {
include: ['light-dark'],
},
},
},
})
it('should transpile light-dark() when included in lightningCssFeatures', async () => {
const html = await next.render('/')
expect(html).toContain('Hello')
// lightningcss transpiles light-dark(a, b) into fallback custom
// properties: var(--lightningcss-light, a) var(--lightningcss-dark, b).
const css = await collectPageCss(next, '/')
expect(css).not.toContain('light-dark(')
expect(css).toContain('--lightningcss-light')
expect(css).toContain('--lightningcss-dark')
})
})
describe('custom-media-queries', () => {
const { next } = nextTestSetup({
files: __dirname,
dependencies: { lightningcss: '^1.23.0' },
packageJson: {
browserslist: ['chrome 123'],
},
nextConfig: {
experimental: {
useLightningcss: true,
lightningCssFeatures: {
include: ['custom-media-queries'],
},
},
},
})
it('should substitute @custom-media when custom-media-queries is included', async () => {
const html = await next.render('/custom-media')
expect(html).toContain('Custom media')
const css = await collectPageCss(next, '/custom-media')
expect(css).not.toContain('@custom-media')
expect(css).not.toContain('--narrow')
expect(css).toMatch(/max-width:\s*960px|width\s*<=\s*960px/)
})
})
describe('exclude', () => {
const { next } = nextTestSetup({
files: __dirname,
dependencies: { lightningcss: '^1.23.0' },
// Chrome 100 does NOT support light-dark() natively, so lightningcss would
// normally transpile it. Using `exclude: ['light-dark']` should prevent that.
packageJson: {
browserslist: ['chrome 100'],
},
nextConfig: {
experimental: {
useLightningcss: true,
lightningCssFeatures: {
exclude: ['light-dark'],
},
},
},
})
it('should preserve light-dark() when excluded from lightningCssFeatures', async () => {
const html = await next.render('/')
expect(html).toContain('Hello')
// With `exclude: ['light-dark']`, lightningcss should NOT transpile
// light-dark() — the raw function should remain in the output.
const css = await collectPageCss(next, '/')
expect(css).toContain('light-dark(')
expect(css).not.toContain('--lightningcss-light')
expect(css).not.toContain('--lightningcss-dark')
})
})
})