mirror of
https://github.com/vercel/next.js.git
synced 2026-09-20 02:25:18 +08:00
1f52cb42ad
The class names were unnecessarily long. Use the same as the lightningcss default: `[hash]_[local]` which is `<hash of the full file path>_<original class name or identifier>` Keep the previous longer mechanism to aid in debugging in dev Co-authored-by: vercel-fleet-prod[bot] <318278635+vercel-fleet-prod[bot]@users.noreply.github.com>
368 lines
11 KiB
TypeScript
368 lines
11 KiB
TypeScript
/* eslint-disable jest/no-identical-title */
|
|
/* eslint-env jest */
|
|
|
|
import { nextTestSetup } from 'e2e-utils'
|
|
import { join } from 'path'
|
|
|
|
describe('Basic CSS Module Support', () => {
|
|
const { next, isTurbopack } = nextTestSetup({
|
|
files: join(__dirname, 'fixtures', 'basic-module'),
|
|
})
|
|
|
|
it(`should've emitted a single CSS file`, async () => {
|
|
const $ = await next.render$('/')
|
|
|
|
const cssSheet = $('link[rel="stylesheet"]')
|
|
expect(cssSheet.length).toBe(1)
|
|
const stylesheet = cssSheet.attr('href')!
|
|
|
|
const cssContent = await next.fetch(stylesheet).then((res) => res.text())
|
|
|
|
if (isTurbopack) {
|
|
expect(
|
|
cssContent.replace(/\/\*.*?\*\//g, '').trim()
|
|
).toMatchInlineSnapshot(`".KWKY6G_redText{color:red}"`)
|
|
} else {
|
|
expect(
|
|
cssContent.replace(/\/\*.*?\*\//g, '').trim()
|
|
).toMatchInlineSnapshot(`".index_redText__honUV{color:red}"`)
|
|
}
|
|
})
|
|
|
|
it(`should've injected the CSS on server render`, async () => {
|
|
const $ = await next.render$('/')
|
|
|
|
const cssPreload = $('link[rel="preload"][as="style"]')
|
|
expect(cssPreload.length).toBe(1)
|
|
expect(cssPreload.attr('href')).toMatch(
|
|
/^\/_next\/static\/.*\.css(\?dpl=.*)?$/
|
|
)
|
|
|
|
const cssSheet = $('link[rel="stylesheet"]')
|
|
expect(cssSheet.length).toBe(1)
|
|
expect(cssSheet.attr('href')).toMatch(
|
|
/^\/_next\/static\/.*\.css(\?dpl=.*)?$/
|
|
)
|
|
|
|
if (isTurbopack) {
|
|
expect($('#verify-red').attr('class')).toMatchInlineSnapshot(
|
|
`"KWKY6G_redText"`
|
|
)
|
|
} else {
|
|
expect($('#verify-red').attr('class')).toMatchInlineSnapshot(
|
|
`"index_redText__honUV"`
|
|
)
|
|
}
|
|
})
|
|
})
|
|
|
|
describe('3rd Party CSS Module Support', () => {
|
|
const { next, isTurbopack } = nextTestSetup({
|
|
files: join(__dirname, 'fixtures', '3rd-party-module'),
|
|
})
|
|
|
|
it(`should've emitted a single CSS file`, async () => {
|
|
const $ = await next.render$('/')
|
|
|
|
const cssSheet = $('link[rel="stylesheet"]')
|
|
expect(cssSheet.length).toBe(1)
|
|
const stylesheet = cssSheet.attr('href')!
|
|
|
|
const cssContent = await next.fetch(stylesheet).then((res) => res.text())
|
|
if (isTurbopack) {
|
|
expect(
|
|
cssContent.replace(/\/\*.*?\*\//g, '').trim()
|
|
).toMatchInlineSnapshot(
|
|
`".KWKY6G_foo{position:relative}:is(.KWKY6G_foo .bar,.KWKY6G_foo .baz){height:100%;overflow:hidden}.KWKY6G_foo .lol{width:80%}.KWKY6G_foo>.lel{width:80%}"`
|
|
)
|
|
} else {
|
|
expect(
|
|
cssContent.replace(/\/\*.*?\*\//g, '').trim()
|
|
).toMatchInlineSnapshot(
|
|
`".index_foo__6TgnK{position:relative}.index_foo__6TgnK .bar,.index_foo__6TgnK .baz{height:100%;overflow:hidden}.index_foo__6TgnK .lol,.index_foo__6TgnK>.lel{width:80%}"`
|
|
)
|
|
}
|
|
})
|
|
|
|
it(`should've injected the CSS on server render`, async () => {
|
|
const $ = await next.render$('/')
|
|
|
|
const cssPreload = $('link[rel="preload"][as="style"]')
|
|
expect(cssPreload.length).toBe(1)
|
|
expect(cssPreload.attr('href')).toMatch(
|
|
/^\/_next\/static\/.*\.css(\?dpl=.*)?$/
|
|
)
|
|
|
|
const cssSheet = $('link[rel="stylesheet"]')
|
|
expect(cssSheet.length).toBe(1)
|
|
expect(cssSheet.attr('href')).toMatch(
|
|
/^\/_next\/static\/.*\.css(\?dpl=.*)?$/
|
|
)
|
|
|
|
if (isTurbopack) {
|
|
expect($('#verify-div').attr('class')).toMatchInlineSnapshot(
|
|
`"KWKY6G_foo"`
|
|
)
|
|
} else {
|
|
expect($('#verify-div').attr('class')).toMatchInlineSnapshot(
|
|
`"index_foo__6TgnK"`
|
|
)
|
|
}
|
|
})
|
|
})
|
|
|
|
describe('Has CSS Module in computed styles in Production', () => {
|
|
const { next } = nextTestSetup({
|
|
files: join(__dirname, 'fixtures', 'prod-module'),
|
|
})
|
|
|
|
it('should have CSS for page', async () => {
|
|
const browser = await next.browser('/')
|
|
|
|
const currentColor = await browser.eval(
|
|
`window.getComputedStyle(document.querySelector('#verify-red')).color`
|
|
)
|
|
expect(currentColor).toMatchInlineSnapshot(`"rgb(255, 0, 0)"`)
|
|
})
|
|
})
|
|
|
|
describe('Valid CSS Module Usage from within node_modules', () => {
|
|
const { next, isTurbopack } = nextTestSetup({
|
|
files: join(__dirname, 'fixtures', 'nm-module'),
|
|
})
|
|
|
|
it(`should've prerendered with relevant data`, async () => {
|
|
const $ = await next.render$('/')
|
|
|
|
const cssPreload = $('#nm-div')
|
|
if (isTurbopack) {
|
|
expect(cssPreload.text()).toMatchInlineSnapshot(
|
|
`"{"message":"Why hello there","default":{"message":"Why hello there"}} {"redText":"PIKFPa_redText","default":{"redText":"PIKFPa_redText"}}"`
|
|
)
|
|
} else {
|
|
expect(cssPreload.text()).toMatchInlineSnapshot(
|
|
`"{"message":"Why hello there"} {"redText":"example_redText__0ctGB"}"`
|
|
)
|
|
}
|
|
})
|
|
|
|
it(`should've emitted a single CSS file`, async () => {
|
|
const $ = await next.render$('/')
|
|
|
|
const cssSheet = $('link[rel="stylesheet"]')
|
|
expect(cssSheet.length).toBe(1)
|
|
const stylesheet = cssSheet.attr('href')!
|
|
|
|
const cssContent = await next.fetch(stylesheet).then((res) => res.text())
|
|
|
|
if (isTurbopack) {
|
|
expect(
|
|
cssContent.replace(/\/\*.*?\*\//g, '').trim()
|
|
).toMatchInlineSnapshot(`".PIKFPa_redText{color:red}"`)
|
|
} else {
|
|
expect(
|
|
cssContent.replace(/\/\*.*?\*\//g, '').trim()
|
|
).toMatchInlineSnapshot(`".example_redText__0ctGB{color:red}"`)
|
|
}
|
|
})
|
|
})
|
|
|
|
// Disabled with Turbopack because `composes` from `.css` files in `.module.css` files is not supported.
|
|
;(process.env.IS_TURBOPACK_TEST ? describe.skip : describe)(
|
|
'Valid Nested CSS Module Usage from within node_modules',
|
|
() => {
|
|
const { next } = nextTestSetup({
|
|
files: join(__dirname, 'fixtures', 'nm-module-nested'),
|
|
})
|
|
|
|
it(`should've prerendered with relevant data`, async () => {
|
|
const $ = await next.render$('/')
|
|
|
|
const cssPreload = $('#nm-div')
|
|
expect(cssPreload.text()).toMatchInlineSnapshot(
|
|
`"{"message":"Why hello there"} {"subClass":"example_subClass__m6Tyy other_className__OA8dV"}"`
|
|
)
|
|
})
|
|
|
|
it(`should've emitted a single CSS file`, async () => {
|
|
const $ = await next.render$('/')
|
|
|
|
const cssSheet = $('link[rel="stylesheet"]')
|
|
expect(cssSheet.length).toBe(1)
|
|
const stylesheet = cssSheet.attr('href')!
|
|
|
|
const cssContent = await next.fetch(stylesheet).then((res) => res.text())
|
|
|
|
expect(
|
|
cssContent.replace(/\/\*.*?\*\//g, '').trim()
|
|
).toMatchInlineSnapshot(
|
|
`".other2_other2__dYPgz{color:red}.other3_other3__7hgUE{color:violet}.other_className__OA8dV{background:red;color:yellow}.example_subClass__m6Tyy{background:blue}"`
|
|
)
|
|
})
|
|
}
|
|
)
|
|
|
|
describe('CSS Module Composes Usage (Basic)', () => {
|
|
const { next, isTurbopack } = nextTestSetup({
|
|
files: join(__dirname, 'fixtures', 'composes-basic'),
|
|
})
|
|
|
|
it(`should've emitted a single CSS file`, async () => {
|
|
const $ = await next.render$('/')
|
|
|
|
const cssSheet = $('link[rel="stylesheet"]')
|
|
expect(cssSheet.length).toBe(1)
|
|
const stylesheet = cssSheet.attr('href')!
|
|
|
|
const cssContent = await next.fetch(stylesheet).then((res) => res.text())
|
|
|
|
if (isTurbopack) {
|
|
expect(
|
|
cssContent.replace(/\/\*.*?\*\//g, '').trim()
|
|
).toMatchInlineSnapshot(
|
|
`".KWKY6G_className{color:#ff0;background:red}.KWKY6G_subClass{background:#00f;}"`
|
|
)
|
|
} else {
|
|
expect(
|
|
cssContent.replace(/\/\*.*?\*\//g, '').trim()
|
|
).toMatchInlineSnapshot(
|
|
`".index_className__jjcZ1{background:red;color:yellow}.index_subClass__eDzaW{background:blue}"`
|
|
)
|
|
}
|
|
})
|
|
})
|
|
;(process.env.IS_TURBOPACK_TEST ? describe.skip : describe)(
|
|
'CSS Module Composes Usage (External)',
|
|
() => {
|
|
const { next } = nextTestSetup({
|
|
files: join(__dirname, 'fixtures', 'composes-external'),
|
|
})
|
|
|
|
it(`should've emitted a single CSS file`, async () => {
|
|
const $ = await next.render$('/')
|
|
|
|
const cssSheet = $('link[rel="stylesheet"]')
|
|
expect(cssSheet.length).toBe(1)
|
|
const stylesheet = cssSheet.attr('href')!
|
|
|
|
const cssContent = await next.fetch(stylesheet).then((res) => res.text())
|
|
|
|
expect(
|
|
cssContent.replace(/\/\*.*?\*\//g, '').trim()
|
|
).toMatchInlineSnapshot(
|
|
`".other_className__eZV4M{background:red;color:yellow}.index_subClass__eDzaW{background:blue}"`
|
|
)
|
|
})
|
|
}
|
|
)
|
|
|
|
describe('Dynamic Route CSS Module Usage', () => {
|
|
const { next, isTurbopack } = nextTestSetup({
|
|
files: join(__dirname, 'fixtures', 'dynamic-route-module'),
|
|
})
|
|
|
|
it('should apply styles correctly', async () => {
|
|
const browser = await next.browser('/post-1')
|
|
|
|
const background = await browser
|
|
.elementByCss('#my-div')
|
|
.getComputedCss('background-color')
|
|
|
|
expect(background).toMatch(/rgb(a|)\(255, 0, 0/)
|
|
})
|
|
|
|
it(`should've emitted a single CSS file`, async () => {
|
|
const $ = await next.render$('/post-1')
|
|
|
|
const cssSheet = $('link[rel="stylesheet"]')
|
|
expect(cssSheet.length).toBe(1)
|
|
const stylesheet = cssSheet.attr('href')!
|
|
|
|
const cssContent = await next.fetch(stylesheet).then((res) => res.text())
|
|
if (isTurbopack) {
|
|
expect(
|
|
cssContent.replace(/\/\*.*?\*\//g, '').trim()
|
|
).toMatchInlineSnapshot(`"._9fTRMq_home{background:red}"`)
|
|
} else {
|
|
expect(
|
|
cssContent.replace(/\/\*.*?\*\//g, '').trim()
|
|
).toMatchInlineSnapshot(`"._post__home__yRmHz{background:#f00}"`)
|
|
}
|
|
})
|
|
})
|
|
|
|
describe('Catch-all Route CSS Module Usage', () => {
|
|
const { next, isTurbopack } = nextTestSetup({
|
|
files: join(__dirname, 'fixtures', 'catch-all-module'),
|
|
})
|
|
|
|
it('should apply styles correctly', async () => {
|
|
const browser = await next.browser('/post-1')
|
|
|
|
const bg = await browser
|
|
.elementByCss('#my-div')
|
|
.getComputedCss('background-color')
|
|
expect(bg).toMatch(/rgb(a|)\(255, 0, 0/)
|
|
|
|
const fg = await browser.elementByCss('#my-div').getComputedCss('color')
|
|
expect(fg).toMatch(/rgb(a|)\(0, 128, 0/)
|
|
})
|
|
|
|
it(`should've emitted a single CSS file`, async () => {
|
|
const $ = await next.render$('/post-1')
|
|
|
|
const cssSheet = $('link[rel="stylesheet"]')
|
|
expect(cssSheet.length).toBe(1)
|
|
const stylesheet = cssSheet.attr('href')!
|
|
|
|
const cssContent = await next.fetch(stylesheet).then((res) => res.text())
|
|
|
|
if (isTurbopack) {
|
|
expect(cssContent.replace(/\/\*.*?\*\/\n?/g, '').trim())
|
|
.toMatchInlineSnapshot(`
|
|
".vy7_gG_home{background:red}
|
|
.c9Qeqa_home{color:green}"
|
|
`)
|
|
} else {
|
|
expect(
|
|
cssContent.replace(/\/\*.*?\*\//g, '').trim()
|
|
).toMatchInlineSnapshot(
|
|
`".___post__home__e4zfx{background:#f00}.__55css_home__r8Rnq{color:green}"`
|
|
)
|
|
}
|
|
})
|
|
})
|
|
|
|
describe('cssmodules-pure-no-check usage', () => {
|
|
const { next } = nextTestSetup({
|
|
files: join(__dirname, 'fixtures', 'cssmodules-pure-no-check'),
|
|
})
|
|
|
|
it('should apply styles correctly', async () => {
|
|
const browser = await next.browser('/')
|
|
|
|
const elementWithGlobalStyles = await browser
|
|
.elementByCss('#my-div')
|
|
.getComputedCss('font-weight')
|
|
|
|
expect(elementWithGlobalStyles).toBe('700')
|
|
})
|
|
|
|
it(`should've emitted a CSS file`, async () => {
|
|
const $ = await next.render$('/')
|
|
|
|
const cssSheet = $('link[rel="stylesheet"]')
|
|
expect(cssSheet.length).toBe(1)
|
|
const stylesheet = cssSheet[0].attribs['href']
|
|
|
|
const cssContent = await next.fetch(stylesheet).then((res) => res.text())
|
|
|
|
const cssCode = cssContent.replace(/\/\*.*?\*\//g, '').trim()
|
|
|
|
expect(cssCode).toInclude(`.global{font-weight:700}`)
|
|
expect(cssCode).toInclude(
|
|
`::view-transition-old(root){animation-duration:.3s}`
|
|
)
|
|
})
|
|
})
|