More test updates (#56146)

Follow-up to #56089

<!-- Thanks for opening a PR! Your contribution is much appreciated.i
To make sure your PR is handled as smoothly as possible we request that
you follow the checklist sections below.
Choose the right checklist for the change(s) that you're making:

## For Contributors

### Improving Documentation

- Run `pnpm prettier-fix` to fix formatting issues before opening the
PR.
- Read the Docs Contribution Guide to ensure your contribution follows
the docs guidelines:
https://nextjs.org/docs/community/contribution-guide

### Adding or Updating Examples

- The "examples guidelines" are followed from our contributing doc
https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md
- Make sure the linting passes by running `pnpm build && pnpm lint`. See
https://github.com/vercel/next.js/blob/canary/contributing/repository/linting.md

### Fixing a bug

- Related issues linked using `fixes #number`
- Tests added. See:
https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs
- Errors have a helpful link attached, see
https://github.com/vercel/next.js/blob/canary/contributing.md

### Adding a feature

- Implements an existing feature request or RFC. Make sure the feature
request has been accepted for implementation before opening a PR. (A
discussion must be opened, see
https://github.com/vercel/next.js/discussions/new?category=ideas)
- Related issues/discussions are linked using `fixes #number`
- e2e tests added
(https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs)
- Documentation added
- Telemetry added. In case of a feature if it's used or not.
- Errors have a helpful link attached, see
https://github.com/vercel/next.js/blob/canary/contributing.md


## For Maintainers

- Minimal description (aim for explaining to someone not on the team to
understand the PR)
- When linking to a Slack thread, you might want to share details of the
conclusion
- Link both the Linear (Fixes NEXT-xxx) and the GitHub issues
- Add review comments if necessary to explain to the reviewer the logic
behind a change

### What?

### Why?

### How?

Closes NEXT-
Fixes #

-->
This commit is contained in:
Tim Neutkens 2023-09-28 13:11:11 +02:00 committed by GitHub
parent 3e32378c73
commit 711fa2133d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 1896 additions and 1748 deletions

View file

@ -8,375 +8,383 @@ import escapeStringRegexp from 'escape-string-regexp'
const fixturesDir = join(__dirname, '../..', 'css-fixtures')
describe('CSS Customization', () => {
const appDir = join(fixturesDir, 'custom-configuration')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const appDir = join(fixturesDir, 'custom-configuration')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it(`should've compiled and prefixed`, async () => {
const cssFolder = join(appDir, '.next/static/css')
describe('Basic CSS', () => {
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
it(`should've compiled and prefixed`, async () => {
const cssFolder = join(appDir, '.next/static/css')
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchInlineSnapshot(
`"@media (480px <= width < 768px){::placeholder{color:green}}.video{max-width:400px;max-height:300px}"`
)
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
// Contains a source map
expect(cssContent).toMatch(/\/\*#\s*sourceMappingURL=(.+\.map)\s*\*\//)
})
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(
cssContent.replace(/\/\*.*?\*\//g, '').trim()
).toMatchInlineSnapshot(
`"@media (480px <= width < 768px){::placeholder{color:green}}.video{max-width:400px;max-height:300px}"`
)
it(`should've emitted a source map`, async () => {
const cssFolder = join(appDir, '.next/static/css')
// Contains a source map
expect(cssContent).toMatch(/\/\*#\s*sourceMappingURL=(.+\.map)\s*\*\//)
})
const files = await readdir(cssFolder)
const cssMapFiles = files.filter((f) => /\.css\.map$/.test(f))
it(`should've emitted a source map`, async () => {
const cssFolder = join(appDir, '.next/static/css')
expect(cssMapFiles.length).toBe(1)
const cssMapContent = (
await readFile(join(cssFolder, cssMapFiles[0]), 'utf8')
).trim()
const files = await readdir(cssFolder)
const cssMapFiles = files.filter((f) => /\.css\.map$/.test(f))
const { version, mappings, sourcesContent } = JSON.parse(cssMapContent)
expect({ version, mappings, sourcesContent }).toMatchInlineSnapshot(`
Object {
"mappings": "AACA,gCACE,cACE,WACF,CACF,CAGA,OACE,eAA0B,CAA1B,gBACF",
"sourcesContent": Array [
"/* this should pass through untransformed */
@media (480px <= width < 768px) {
::placeholder {
color: green;
}
}
expect(cssMapFiles.length).toBe(1)
const cssMapContent = (
await readFile(join(cssFolder, cssMapFiles[0]), 'utf8')
).trim()
/* this should be transformed to width/height */
.video {
-xyz-max-size: 400px 300px;
}
",
],
"version": 3,
}
`)
})
})
const { version, mappings, sourcesContent } = JSON.parse(cssMapContent)
expect({ version, mappings, sourcesContent }).toMatchInlineSnapshot(`
Object {
"mappings": "AACA,gCACE,cACE,WACF,CACF,CAGA,OACE,eAA0B,CAA1B,gBACF",
"sourcesContent": Array [
"/* this should pass through untransformed */
@media (480px <= width < 768px) {
::placeholder {
color: green;
}
}
describe('CSS Customization Array', () => {
const appDir = join(fixturesDir, 'custom-configuration-arr')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
/* this should be transformed to width/height */
.video {
-xyz-max-size: 400px 300px;
}
",
],
"version": 3,
}
`)
})
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it(`should've compiled and prefixed`, async () => {
const cssFolder = join(appDir, '.next/static/css')
describe('Correct CSS Customization Array', () => {
const appDir = join(fixturesDir, 'custom-configuration-arr')
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchInlineSnapshot(
`"@media (480px <= width < 768px){a:before{content:\\"\\"}::placeholder{color:green}}.video{max-width:6400px;max-height:4800px;max-width:400rem;max-height:300rem}"`
)
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
// Contains a source map
expect(cssContent).toMatch(/\/\*#\s*sourceMappingURL=(.+\.map)\s*\*\//)
})
it(`should've compiled and prefixed`, async () => {
const cssFolder = join(appDir, '.next/static/css')
it(`should've emitted a source map`, async () => {
const cssFolder = join(appDir, '.next/static/css')
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
const files = await readdir(cssFolder)
const cssMapFiles = files.filter((f) => /\.css\.map$/.test(f))
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(
cssContent.replace(/\/\*.*?\*\//g, '').trim()
).toMatchInlineSnapshot(
`"@media (480px <= width < 768px){a:before{content:\\"\\"}::placeholder{color:green}}.video{max-width:6400px;max-height:4800px;max-width:400rem;max-height:300rem}"`
)
expect(cssMapFiles.length).toBe(1)
const cssMapContent = (
await readFile(join(cssFolder, cssMapFiles[0]), 'utf8')
).trim()
// Contains a source map
expect(cssContent).toMatch(/\/\*#\s*sourceMappingURL=(.+\.map)\s*\*\//)
})
const { version, mappings, sourcesContent } = JSON.parse(cssMapContent)
expect({ version, mappings, sourcesContent }).toMatchInlineSnapshot(`
Object {
"mappings": "AACA,gCACE,SACE,UACF,CACA,cACE,WACF,CACF,CAGA,OACE,gBAA4B,CAA5B,iBAA4B,CAA5B,gBAA4B,CAA5B,iBACF",
"sourcesContent": Array [
"/* this should pass through untransformed */
@media (480px <= width < 768px) {
a::before {
content: '';
}
::placeholder {
color: green;
}
}
it(`should've emitted a source map`, async () => {
const cssFolder = join(appDir, '.next/static/css')
/* this should be transformed to width/height */
.video {
-xyz-max-size: 400rem 300rem;
}
",
],
"version": 3,
}
`)
})
})
const files = await readdir(cssFolder)
const cssMapFiles = files.filter((f) => /\.css\.map$/.test(f))
describe('CSS Customization custom loader', () => {
const appDir = join(fixturesDir, 'custom-configuration-loader')
expect(cssMapFiles.length).toBe(1)
const cssMapContent = (
await readFile(join(cssFolder, cssMapFiles[0]), 'utf8')
).trim()
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
const { version, mappings, sourcesContent } = JSON.parse(cssMapContent)
expect({ version, mappings, sourcesContent }).toMatchInlineSnapshot(`
Object {
"mappings": "AACA,gCACE,SACE,UACF,CACA,cACE,WACF,CACF,CAGA,OACE,gBAA4B,CAA5B,iBAA4B,CAA5B,gBAA4B,CAA5B,iBACF",
"sourcesContent": Array [
"/* this should pass through untransformed */
@media (480px <= width < 768px) {
a::before {
content: '';
}
::placeholder {
color: green;
}
}
it('should compile successfully', async () => {
const { code, stdout, stderr } = await nextBuild(appDir, [], {
stdout: true,
stderr: true,
/* this should be transformed to width/height */
.video {
-xyz-max-size: 400rem 300rem;
}
",
],
"version": 3,
}
`)
})
})
expect(code).toBe(0)
expect(stderr).toMatch(/Built-in CSS support is being disabled/)
expect(stdout).toMatch(/Compiled successfully/)
})
it(`should've applied style`, async () => {
const pagesFolder = join(appDir, '.next/static/chunks/pages')
describe('Correct CSS Customization custom loader', () => {
const appDir = join(fixturesDir, 'custom-configuration-loader')
const files = await readdir(pagesFolder)
const indexFiles = files.filter((f) => /^index.+\.js$/.test(f))
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
expect(indexFiles.length).toBe(1)
const indexContent = await readFile(
join(pagesFolder, indexFiles[0]),
'utf8'
)
expect(indexContent).toMatch(/\.my-text\.jsx-[0-9a-z]+{color:red}/)
})
})
it('should compile successfully', async () => {
const { code, stdout, stderr } = await nextBuild(appDir, [], {
stdout: true,
stderr: true,
})
expect(code).toBe(0)
expect(stderr).toMatch(/Built-in CSS support is being disabled/)
expect(stdout).toMatch(/Compiled successfully/)
})
describe('Bad CSS Customization', () => {
const appDir = join(fixturesDir, 'bad-custom-configuration')
it(`should've applied style`, async () => {
const pagesFolder = join(appDir, '.next/static/chunks/pages')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
const files = await readdir(pagesFolder)
const indexFiles = files.filter((f) => /^index.+\.js$/.test(f))
it('should compile successfully', async () => {
const { stdout, stderr } = await nextBuild(appDir, [], {
stdout: true,
stderr: true,
expect(indexFiles.length).toBe(1)
const indexContent = await readFile(
join(pagesFolder, indexFiles[0]),
'utf8'
)
expect(indexContent).toMatch(/\.my-text\.jsx-[0-9a-z]+{color:red}/)
})
})
expect(stdout).toMatch(/Compiled successfully/)
expect(stderr).toMatch(/field which is not supported.*?sourceMap/)
;[
'postcss-modules-values',
'postcss-modules-scope',
'postcss-modules-extract-imports',
'postcss-modules-local-by-default',
'postcss-modules',
].forEach((plugin) => {
expect(stderr).toMatch(
new RegExp(`Please remove the.*?${escapeStringRegexp(plugin)}`)
)
describe('Bad CSS Customization', () => {
const appDir = join(fixturesDir, 'bad-custom-configuration')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should compile successfully', async () => {
const { stdout, stderr } = await nextBuild(appDir, [], {
stdout: true,
stderr: true,
})
expect(stdout).toMatch(/Compiled successfully/)
expect(stderr).toMatch(/field which is not supported.*?sourceMap/)
;[
'postcss-modules-values',
'postcss-modules-scope',
'postcss-modules-extract-imports',
'postcss-modules-local-by-default',
'postcss-modules',
].forEach((plugin) => {
expect(stderr).toMatch(
new RegExp(`Please remove the.*?${escapeStringRegexp(plugin)}`)
)
})
})
it(`should've compiled and prefixed`, async () => {
const cssFolder = join(appDir, '.next/static/css')
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(
cssContent.replace(/\/\*.*?\*\//g, '').trim()
).toMatchInlineSnapshot(`".video{max-width:400px;max-height:300px}"`)
// Contains a source map
expect(cssContent).toMatch(/\/\*#\s*sourceMappingURL=(.+\.map)\s*\*\//)
})
it(`should've emitted a source map`, async () => {
const cssFolder = join(appDir, '.next/static/css')
const files = await readdir(cssFolder)
const cssMapFiles = files.filter((f) => /\.css\.map$/.test(f))
expect(cssMapFiles.length).toBe(1)
})
})
describe('Bad CSS Customization Array (1)', () => {
const appDir = join(fixturesDir, 'bad-custom-configuration-arr-1')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should fail the build', async () => {
const { stderr } = await nextBuild(appDir, [], { stderr: true })
expect(stderr).toMatch(
/A PostCSS Plugin was passed as an array but did not provide its configuration \('postcss-trolling'\)/
)
expect(stderr).toMatch(/Build failed because of webpack errors/)
})
})
describe('Bad CSS Customization Array (2)', () => {
const appDir = join(fixturesDir, 'bad-custom-configuration-arr-2')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should fail the build', async () => {
const { stderr } = await nextBuild(appDir, [], { stderr: true })
expect(stderr).toMatch(
/Error: Your PostCSS configuration for 'postcss-trolling' cannot have null configuration./
)
expect(stderr).toMatch(
/To disable 'postcss-trolling', pass false, otherwise, pass true or a configuration object./
)
expect(stderr).toMatch(/Build failed because of webpack errors/)
})
})
describe('Bad CSS Customization Array (3)', () => {
const appDir = join(fixturesDir, 'bad-custom-configuration-arr-3')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should fail the build', async () => {
const { stderr } = await nextBuild(appDir, [], { stderr: true })
expect(stderr).toMatch(
/A PostCSS Plugin must be provided as a string. Instead, we got: '5'/
)
expect(stderr).toMatch(/Build failed because of webpack errors/)
})
})
describe('Bad CSS Customization Array (4)', () => {
const appDir = join(fixturesDir, 'bad-custom-configuration-arr-4')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should fail the build', async () => {
const { stderr } = await nextBuild(appDir, [], { stderr: true })
expect(stderr).toMatch(/An unknown PostCSS plugin was provided \(5\)/)
expect(stderr).toMatch(/Build failed because of webpack errors/)
})
})
describe('Bad CSS Customization Array (5)', () => {
const appDir = join(fixturesDir, 'bad-custom-configuration-arr-5')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should fail the build', async () => {
const { stderr } = await nextBuild(appDir, [], { stderr: true })
expect(stderr).toMatch(
/Your custom PostCSS configuration must export a `plugins` key./
)
expect(stderr).toMatch(/Build failed because of webpack errors/)
})
})
describe('Bad CSS Customization Array (6)', () => {
const appDir = join(fixturesDir, 'bad-custom-configuration-arr-6')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should fail the build', async () => {
const { stderr } = await nextBuild(appDir, [], { stderr: true })
expect(stderr).toMatch(
/Your custom PostCSS configuration must export a `plugins` key./
)
expect(stderr).toMatch(/Build failed because of webpack errors/)
})
})
describe('Bad CSS Customization Array (7)', () => {
const appDir = join(fixturesDir, 'bad-custom-configuration-arr-7')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should fail the build', async () => {
const { stderr } = await nextBuild(appDir, [], { stderr: true })
expect(stderr).toMatch(
/A PostCSS Plugin was passed as an array but did not provide its configuration \('postcss-trolling'\)/
)
expect(stderr).toMatch(/Build failed because of webpack errors/)
})
})
describe('Bad CSS Customization Array (8)', () => {
const appDir = join(fixturesDir, 'bad-custom-configuration-arr-8')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should fail the build', async () => {
const { stderr } = await nextBuild(appDir, [], { stderr: true })
expect(stderr).toMatch(
/A PostCSS Plugin was passed as a function using require\(\), but it must be provided as a string/
)
expect(stderr).toMatch(/Build failed because of webpack errors/)
})
})
describe('Bad CSS Customization Function', () => {
const appDir = join(fixturesDir, 'bad-custom-configuration-func')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should fail the build', async () => {
const { stderr } = await nextBuild(appDir, [], { stderr: true })
expect(stderr).toMatch(
/Your custom PostCSS configuration may not export a function/
)
expect(stderr).toMatch(/Build failed because of webpack errors/)
})
})
})
it(`should've compiled and prefixed`, async () => {
const cssFolder = join(appDir, '.next/static/css')
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchInlineSnapshot(
`".video{max-width:400px;max-height:300px}"`
)
// Contains a source map
expect(cssContent).toMatch(/\/\*#\s*sourceMappingURL=(.+\.map)\s*\*\//)
})
it(`should've emitted a source map`, async () => {
const cssFolder = join(appDir, '.next/static/css')
const files = await readdir(cssFolder)
const cssMapFiles = files.filter((f) => /\.css\.map$/.test(f))
expect(cssMapFiles.length).toBe(1)
})
})
describe('Bad CSS Customization Array (1)', () => {
const appDir = join(fixturesDir, 'bad-custom-configuration-arr-1')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should fail the build', async () => {
const { stderr } = await nextBuild(appDir, [], { stderr: true })
expect(stderr).toMatch(
/A PostCSS Plugin was passed as an array but did not provide its configuration \('postcss-trolling'\)/
)
expect(stderr).toMatch(/Build failed because of webpack errors/)
})
})
describe('Bad CSS Customization Array (2)', () => {
const appDir = join(fixturesDir, 'bad-custom-configuration-arr-2')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should fail the build', async () => {
const { stderr } = await nextBuild(appDir, [], { stderr: true })
expect(stderr).toMatch(
/Error: Your PostCSS configuration for 'postcss-trolling' cannot have null configuration./
)
expect(stderr).toMatch(
/To disable 'postcss-trolling', pass false, otherwise, pass true or a configuration object./
)
expect(stderr).toMatch(/Build failed because of webpack errors/)
})
})
describe('Bad CSS Customization Array (3)', () => {
const appDir = join(fixturesDir, 'bad-custom-configuration-arr-3')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should fail the build', async () => {
const { stderr } = await nextBuild(appDir, [], { stderr: true })
expect(stderr).toMatch(
/A PostCSS Plugin must be provided as a string. Instead, we got: '5'/
)
expect(stderr).toMatch(/Build failed because of webpack errors/)
})
})
describe('Bad CSS Customization Array (4)', () => {
const appDir = join(fixturesDir, 'bad-custom-configuration-arr-4')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should fail the build', async () => {
const { stderr } = await nextBuild(appDir, [], { stderr: true })
expect(stderr).toMatch(/An unknown PostCSS plugin was provided \(5\)/)
expect(stderr).toMatch(/Build failed because of webpack errors/)
})
})
describe('Bad CSS Customization Array (5)', () => {
const appDir = join(fixturesDir, 'bad-custom-configuration-arr-5')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should fail the build', async () => {
const { stderr } = await nextBuild(appDir, [], { stderr: true })
expect(stderr).toMatch(
/Your custom PostCSS configuration must export a `plugins` key./
)
expect(stderr).toMatch(/Build failed because of webpack errors/)
})
})
describe('Bad CSS Customization Array (6)', () => {
const appDir = join(fixturesDir, 'bad-custom-configuration-arr-6')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should fail the build', async () => {
const { stderr } = await nextBuild(appDir, [], { stderr: true })
expect(stderr).toMatch(
/Your custom PostCSS configuration must export a `plugins` key./
)
expect(stderr).toMatch(/Build failed because of webpack errors/)
})
})
describe('Bad CSS Customization Array (7)', () => {
const appDir = join(fixturesDir, 'bad-custom-configuration-arr-7')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should fail the build', async () => {
const { stderr } = await nextBuild(appDir, [], { stderr: true })
expect(stderr).toMatch(
/A PostCSS Plugin was passed as an array but did not provide its configuration \('postcss-trolling'\)/
)
expect(stderr).toMatch(/Build failed because of webpack errors/)
})
})
describe('Bad CSS Customization Array (8)', () => {
const appDir = join(fixturesDir, 'bad-custom-configuration-arr-8')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should fail the build', async () => {
const { stderr } = await nextBuild(appDir, [], { stderr: true })
expect(stderr).toMatch(
/A PostCSS Plugin was passed as a function using require\(\), but it must be provided as a string/
)
expect(stderr).toMatch(/Build failed because of webpack errors/)
})
})
describe('Bad CSS Customization Function', () => {
const appDir = join(fixturesDir, 'bad-custom-configuration-func')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should fail the build', async () => {
const { stderr } = await nextBuild(appDir, [], { stderr: true })
expect(stderr).toMatch(
/Your custom PostCSS configuration may not export a function/
)
expect(stderr).toMatch(/Build failed because of webpack errors/)
})
})

View file

@ -18,115 +18,121 @@ import { join } from 'path'
const fixturesDir = join(__dirname, '../../css-fixtures')
describe('Basic CSS Module Support', () => {
const appDir = join(fixturesDir, 'basic-module')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const appDir = join(fixturesDir, 'basic-module')
let appPort
let app
let stdout
let code
beforeAll(async () => {
await remove(join(appDir, '.next'))
;({ code, stdout } = await nextBuild(appDir, [], {
stdout: true,
}))
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(async () => {
await killApp(app)
})
let appPort
let app
let stdout
let code
beforeAll(async () => {
await remove(join(appDir, '.next'))
;({ code, stdout } = await nextBuild(appDir, [], {
stdout: true,
}))
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(async () => {
await killApp(app)
})
it('should have compiled successfully', () => {
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
expect(stdout).toContain('.css')
})
it('should have compiled successfully', () => {
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
expect(stdout).toContain('.css')
})
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchInlineSnapshot(
`".index_redText__honUV{color:red}"`
)
})
expect(
cssContent.replace(/\/\*.*?\*\//g, '').trim()
).toMatchInlineSnapshot(`".index_redText__honUV{color:red}"`)
})
it(`should've injected the CSS on server render`, async () => {
const content = await renderViaHTTP(appPort, '/')
const $ = cheerio.load(content)
it(`should've injected the CSS on server render`, async () => {
const content = await renderViaHTTP(appPort, '/')
const $ = cheerio.load(content)
const cssPreload = $('link[rel="preload"][as="style"]')
expect(cssPreload.length).toBe(1)
expect(cssPreload.attr('href')).toMatch(/^\/_next\/static\/css\/.*\.css$/)
const cssPreload = $('link[rel="preload"][as="style"]')
expect(cssPreload.length).toBe(1)
expect(cssPreload.attr('href')).toMatch(/^\/_next\/static\/css\/.*\.css$/)
const cssSheet = $('link[rel="stylesheet"]')
expect(cssSheet.length).toBe(1)
expect(cssSheet.attr('href')).toMatch(/^\/_next\/static\/css\/.*\.css$/)
const cssSheet = $('link[rel="stylesheet"]')
expect(cssSheet.length).toBe(1)
expect(cssSheet.attr('href')).toMatch(/^\/_next\/static\/css\/.*\.css$/)
expect($('#verify-red').attr('class')).toMatchInlineSnapshot(
`"index_redText__honUV"`
)
expect($('#verify-red').attr('class')).toMatchInlineSnapshot(
`"index_redText__honUV"`
)
})
})
})
describe('3rd Party CSS Module Support', () => {
const appDir = join(fixturesDir, '3rd-party-module')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const appDir = join(fixturesDir, '3rd-party-module')
let appPort
let app
let stdout
let code
beforeAll(async () => {
await remove(join(appDir, '.next'))
;({ code, stdout } = await nextBuild(appDir, [], {
stdout: true,
}))
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(async () => {
await killApp(app)
})
let appPort
let app
let stdout
let code
beforeAll(async () => {
await remove(join(appDir, '.next'))
;({ code, stdout } = await nextBuild(appDir, [], {
stdout: true,
}))
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(async () => {
await killApp(app)
})
it('should have compiled successfully', () => {
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it('should have compiled successfully', () => {
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
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%}"`
)
})
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 content = await renderViaHTTP(appPort, '/')
const $ = cheerio.load(content)
it(`should've injected the CSS on server render`, async () => {
const content = await renderViaHTTP(appPort, '/')
const $ = cheerio.load(content)
const cssPreload = $('link[rel="preload"][as="style"]')
expect(cssPreload.length).toBe(1)
expect(cssPreload.attr('href')).toMatch(/^\/_next\/static\/css\/.*\.css$/)
const cssPreload = $('link[rel="preload"][as="style"]')
expect(cssPreload.length).toBe(1)
expect(cssPreload.attr('href')).toMatch(/^\/_next\/static\/css\/.*\.css$/)
const cssSheet = $('link[rel="stylesheet"]')
expect(cssSheet.length).toBe(1)
expect(cssSheet.attr('href')).toMatch(/^\/_next\/static\/css\/.*\.css$/)
const cssSheet = $('link[rel="stylesheet"]')
expect(cssSheet.length).toBe(1)
expect(cssSheet.attr('href')).toMatch(/^\/_next\/static\/css\/.*\.css$/)
expect($('#verify-div').attr('class')).toMatchInlineSnapshot(
`"index_foo__6TgnK"`
)
expect($('#verify-div').attr('class')).toMatchInlineSnapshot(
`"index_foo__6TgnK"`
)
})
})
})
@ -155,36 +161,38 @@ describe('Has CSS Module in computed styles in Development', () => {
})
describe('Has CSS Module in computed styles in Production', () => {
const appDir = join(fixturesDir, 'prod-module')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const appDir = join(fixturesDir, 'prod-module')
let appPort
let app
let stdout
let code
beforeAll(async () => {
await remove(join(appDir, '.next'))
;({ code, stdout } = await nextBuild(appDir, [], {
stdout: true,
}))
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(async () => {
await killApp(app)
})
let appPort
let app
let stdout
let code
beforeAll(async () => {
await remove(join(appDir, '.next'))
;({ code, stdout } = await nextBuild(appDir, [], {
stdout: true,
}))
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(async () => {
await killApp(app)
})
it('should have compiled successfully', () => {
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it('should have compiled successfully', () => {
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it('should have CSS for page', async () => {
const browser = await webdriver(appPort, '/')
it('should have CSS for page', async () => {
const browser = await webdriver(appPort, '/')
const currentColor = await browser.eval(
`window.getComputedStyle(document.querySelector('#verify-red')).color`
)
expect(currentColor).toMatchInlineSnapshot(`"rgb(255, 0, 0)"`)
const currentColor = await browser.eval(
`window.getComputedStyle(document.querySelector('#verify-red')).color`
)
expect(currentColor).toMatchInlineSnapshot(`"rgb(255, 0, 0)"`)
})
})
})
@ -277,271 +285,291 @@ describe.skip('Invalid Global CSS Module Usage in node_modules', () => {
})
describe('Valid CSS Module Usage from within node_modules', () => {
const appDir = join(fixturesDir, 'nm-module')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const appDir = join(fixturesDir, 'nm-module')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
let appPort
let app
let stdout
let code
beforeAll(async () => {
await remove(join(appDir, '.next'))
;({ code, stdout } = await nextBuild(appDir, [], {
stdout: true,
}))
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(async () => {
await killApp(app)
})
let appPort
let app
let stdout
let code
beforeAll(async () => {
await remove(join(appDir, '.next'))
;({ code, stdout } = await nextBuild(appDir, [], {
stdout: true,
}))
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(async () => {
await killApp(app)
})
it('should have compiled successfully', () => {
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it('should have compiled successfully', () => {
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it(`should've prerendered with relevant data`, async () => {
const content = await renderViaHTTP(appPort, '/')
const $ = cheerio.load(content)
it(`should've prerendered with relevant data`, async () => {
const content = await renderViaHTTP(appPort, '/')
const $ = cheerio.load(content)
const cssPreload = $('#nm-div')
expect(cssPreload.text()).toMatchInlineSnapshot(
`"{\\"message\\":\\"Why hello there\\"} {\\"redText\\":\\"example_redText__0ctGB\\"}"`
)
})
const cssPreload = $('#nm-div')
expect(cssPreload.text()).toMatchInlineSnapshot(
`"{\\"message\\":\\"Why hello there\\"} {\\"redText\\":\\"example_redText__0ctGB\\"}"`
)
})
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchInlineSnapshot(
`".example_redText__0ctGB{color:red}"`
)
expect(
cssContent.replace(/\/\*.*?\*\//g, '').trim()
).toMatchInlineSnapshot(`".example_redText__0ctGB{color:red}"`)
})
})
})
describe('Valid Nested CSS Module Usage from within node_modules', () => {
const appDir = join(fixturesDir, 'nm-module-nested')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const appDir = join(fixturesDir, 'nm-module-nested')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
let appPort
let app
let stdout
let code
beforeAll(async () => {
await remove(join(appDir, '.next'))
;({ code, stdout } = await nextBuild(appDir, [], {
stdout: true,
}))
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(async () => {
await killApp(app)
})
let appPort
let app
let stdout
let code
beforeAll(async () => {
await remove(join(appDir, '.next'))
;({ code, stdout } = await nextBuild(appDir, [], {
stdout: true,
}))
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(async () => {
await killApp(app)
})
it('should have compiled successfully', () => {
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it('should have compiled successfully', () => {
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it(`should've prerendered with relevant data`, async () => {
const content = await renderViaHTTP(appPort, '/')
const $ = cheerio.load(content)
it(`should've prerendered with relevant data`, async () => {
const content = await renderViaHTTP(appPort, '/')
const $ = cheerio.load(content)
const cssPreload = $('#nm-div')
expect(cssPreload.text()).toMatchInlineSnapshot(
`"{\\"message\\":\\"Why hello there\\"} {\\"subClass\\":\\"example_subClass__m6Tyy other_className__OA8dV\\"}"`
)
})
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 cssFolder = join(appDir, '.next/static/css')
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchInlineSnapshot(
`".other2_other2__dYPgz{color:red}.other3_other3__7hgUE{color:violet}.other_className__OA8dV{background:red;color:#ff0}.example_subClass__m6Tyy{background:blue}"`
)
expect(
cssContent.replace(/\/\*.*?\*\//g, '').trim()
).toMatchInlineSnapshot(
`".other2_other2__dYPgz{color:red}.other3_other3__7hgUE{color:violet}.other_className__OA8dV{background:red;color:#ff0}.example_subClass__m6Tyy{background:blue}"`
)
})
})
})
describe('CSS Module Composes Usage (Basic)', () => {
// This is a very bad feature. Do not use it.
const appDir = join(fixturesDir, 'composes-basic')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
// This is a very bad feature. Do not use it.
const appDir = join(fixturesDir, 'composes-basic')
let stdout
let code
beforeAll(async () => {
await remove(join(appDir, '.next'))
;({ code, stdout } = await nextBuild(appDir, [], {
stdout: true,
}))
})
let stdout
let code
beforeAll(async () => {
await remove(join(appDir, '.next'))
;({ code, stdout } = await nextBuild(appDir, [], {
stdout: true,
}))
})
it('should have compiled successfully', () => {
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it('should have compiled successfully', () => {
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchInlineSnapshot(
`".index_className__jjcZ1{background:red;color:#ff0}.index_subClass__eDzaW{background:blue}"`
)
expect(
cssContent.replace(/\/\*.*?\*\//g, '').trim()
).toMatchInlineSnapshot(
`".index_className__jjcZ1{background:red;color:#ff0}.index_subClass__eDzaW{background:blue}"`
)
})
})
})
describe('CSS Module Composes Usage (External)', () => {
// This is a very bad feature. Do not use it.
const appDir = join(fixturesDir, 'composes-external')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
// This is a very bad feature. Do not use it.
const appDir = join(fixturesDir, 'composes-external')
let stdout
let code
beforeAll(async () => {
await remove(join(appDir, '.next'))
;({ code, stdout } = await nextBuild(appDir, [], {
stdout: true,
}))
})
let stdout
let code
beforeAll(async () => {
await remove(join(appDir, '.next'))
;({ code, stdout } = await nextBuild(appDir, [], {
stdout: true,
}))
})
it('should have compiled successfully', () => {
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it('should have compiled successfully', () => {
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchInlineSnapshot(
`".other_className__eZV4M{background:red;color:#ff0}.index_subClass__eDzaW{background:blue}"`
)
expect(
cssContent.replace(/\/\*.*?\*\//g, '').trim()
).toMatchInlineSnapshot(
`".other_className__eZV4M{background:red;color:#ff0}.index_subClass__eDzaW{background:blue}"`
)
})
})
})
describe('Dynamic Route CSS Module Usage', () => {
const appDir = join(fixturesDir, 'dynamic-route-module')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const appDir = join(fixturesDir, 'dynamic-route-module')
let stdout
let code
let app
let appPort
let stdout
let code
let app
let appPort
beforeAll(async () => {
await remove(join(appDir, '.next'))
;({ code, stdout } = await nextBuild(appDir, [], {
stdout: true,
}))
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(() => killApp(app))
beforeAll(async () => {
await remove(join(appDir, '.next'))
;({ code, stdout } = await nextBuild(appDir, [], {
stdout: true,
}))
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(() => killApp(app))
it('should have compiled successfully', () => {
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it('should have compiled successfully', () => {
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it('should apply styles correctly', async () => {
const browser = await webdriver(appPort, '/post-1')
it('should apply styles correctly', async () => {
const browser = await webdriver(appPort, '/post-1')
const background = await browser
.elementByCss('#my-div')
.getComputedCss('background-color')
const background = await browser
.elementByCss('#my-div')
.getComputedCss('background-color')
expect(background).toMatch(/rgb(a|)\(255, 0, 0/)
})
expect(background).toMatch(/rgb(a|)\(255, 0, 0/)
})
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchInlineSnapshot(
`"._post__home__yRmHz{background:red}"`
)
expect(
cssContent.replace(/\/\*.*?\*\//g, '').trim()
).toMatchInlineSnapshot(`"._post__home__yRmHz{background:red}"`)
})
})
})
describe('Catch-all Route CSS Module Usage', () => {
const appDir = join(fixturesDir, 'catch-all-module')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const appDir = join(fixturesDir, 'catch-all-module')
let stdout
let code
let app
let appPort
let stdout
let code
let app
let appPort
beforeAll(async () => {
await remove(join(appDir, '.next'))
;({ code, stdout } = await nextBuild(appDir, [], {
stdout: true,
}))
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(() => killApp(app))
beforeAll(async () => {
await remove(join(appDir, '.next'))
;({ code, stdout } = await nextBuild(appDir, [], {
stdout: true,
}))
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(() => killApp(app))
it('should have compiled successfully', () => {
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it('should have compiled successfully', () => {
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it('should apply styles correctly', async () => {
const browser = await webdriver(appPort, '/post-1')
it('should apply styles correctly', async () => {
const browser = await webdriver(appPort, '/post-1')
const bg = await browser
.elementByCss('#my-div')
.getComputedCss('background-color')
expect(bg).toMatch(/rgb(a|)\(255, 0, 0/)
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/)
})
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 cssFolder = join(appDir, '.next/static/css')
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchInlineSnapshot(
`".___post__home__e4zfx{background:red}.__55css_home__r8Rnq{color:green}"`
)
expect(
cssContent.replace(/\/\*.*?\*\//g, '').trim()
).toMatchInlineSnapshot(
`".___post__home__e4zfx{background:red}.__55css_home__r8Rnq{color:green}"`
)
})
})
})

View file

@ -7,311 +7,331 @@ import { join } from 'path'
const fixturesDir = join(__dirname, '../..', 'css-fixtures')
describe('Basic Global Support', () => {
const appDir = join(fixturesDir, 'single-global')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const appDir = join(fixturesDir, 'single-global')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
expect(cssFiles.length).toBe(1)
expect(await readFile(join(cssFolder, cssFiles[0]), 'utf8')).toContain(
'color:red'
)
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
expect(cssFiles.length).toBe(1)
expect(await readFile(join(cssFolder, cssFiles[0]), 'utf8')).toContain(
'color:red'
)
})
})
})
describe('Basic Global Support with special characters in path', () => {
const appDir = join(fixturesDir, 'single-global-special-characters', 'a+b')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const appDir = join(fixturesDir, 'single-global-special-characters', 'a+b')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
expect(cssFiles.length).toBe(1)
expect(await readFile(join(cssFolder, cssFiles[0]), 'utf8')).toContain(
'color:red'
)
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
expect(cssFiles.length).toBe(1)
expect(await readFile(join(cssFolder, cssFiles[0]), 'utf8')).toContain(
'color:red'
)
})
})
})
describe('Basic Global Support with src/ dir', () => {
const appDir = join(fixturesDir, 'single-global-src')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const appDir = join(fixturesDir, 'single-global-src')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
expect(cssFiles.length).toBe(1)
expect(await readFile(join(cssFolder, cssFiles[0]), 'utf8')).toContain(
'color:red'
)
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
expect(cssFiles.length).toBe(1)
expect(await readFile(join(cssFolder, cssFiles[0]), 'utf8')).toContain(
'color:red'
)
})
})
})
describe('Multi Global Support', () => {
const appDir = join(fixturesDir, 'multi-global')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const appDir = join(fixturesDir, 'multi-global')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchInlineSnapshot(
`".red-text{color:red}.blue-text{color:blue}"`
)
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(
cssContent.replace(/\/\*.*?\*\//g, '').trim()
).toMatchInlineSnapshot(`".red-text{color:red}.blue-text{color:blue}"`)
})
})
})
describe('Nested @import() Global Support', () => {
const appDir = join(fixturesDir, 'nested-global')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const appDir = join(fixturesDir, 'nested-global')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchInlineSnapshot(
`".red-text{color:purple;font-weight:bolder;color:red}.blue-text{color:orange;font-weight:bolder;color:blue}"`
)
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(
cssContent.replace(/\/\*.*?\*\//g, '').trim()
).toMatchInlineSnapshot(
`".red-text{color:purple;font-weight:bolder;color:red}.blue-text{color:orange;font-weight:bolder;color:blue}"`
)
})
})
})
// Tests css ordering
describe('Multi Global Support (reversed)', () => {
const appDir = join(fixturesDir, 'multi-global-reversed')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const appDir = join(fixturesDir, 'multi-global-reversed')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchInlineSnapshot(
`".blue-text{color:blue}.red-text{color:red}"`
)
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(
cssContent.replace(/\/\*.*?\*\//g, '').trim()
).toMatchInlineSnapshot(`".blue-text{color:blue}.red-text{color:red}"`)
})
})
})
describe('CSS URL via `file-loader`', () => {
const appDir = join(fixturesDir, 'url-global')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const appDir = join(fixturesDir, 'url-global')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it(`should've emitted expected files`, async () => {
const cssFolder = join(appDir, '.next/static/css')
const mediaFolder = join(appDir, '.next/static/media')
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
it(`should've emitted expected files`, async () => {
const cssFolder = join(appDir, '.next/static/css')
const mediaFolder = join(appDir, '.next/static/media')
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatch(
/^\.red-text\{color:red;background-image:url\(\/_next\/static\/media\/dark\.[a-f0-9]{8}\.svg\) url\(\/_next\/static\/media\/dark2\.[a-f0-9]{8}\.svg\)\}\.blue-text\{color:orange;font-weight:bolder;background-image:url\(\/_next\/static\/media\/light\.[a-f0-9]{8}\.svg\);color:blue\}$/
)
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
const mediaFiles = await readdir(mediaFolder)
expect(mediaFiles.length).toBe(3)
expect(
mediaFiles
.map((fileName) =>
/^(.+?)\..{8}\.(.+?)$/.exec(fileName).slice(1).join('.')
)
.sort()
).toMatchInlineSnapshot(`
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatch(
/^\.red-text\{color:red;background-image:url\(\/_next\/static\/media\/dark\.[a-f0-9]{8}\.svg\) url\(\/_next\/static\/media\/dark2\.[a-f0-9]{8}\.svg\)\}\.blue-text\{color:orange;font-weight:bolder;background-image:url\(\/_next\/static\/media\/light\.[a-f0-9]{8}\.svg\);color:blue\}$/
)
const mediaFiles = await readdir(mediaFolder)
expect(mediaFiles.length).toBe(3)
expect(
mediaFiles
.map((fileName) =>
/^(.+?)\..{8}\.(.+?)$/.exec(fileName).slice(1).join('.')
)
.sort()
).toMatchInlineSnapshot(`
Array [
"dark.svg",
"dark2.svg",
"light.svg",
]
`)
})
})
})
describe('CSS URL via `file-loader` and asset prefix (1)', () => {
const appDir = join(fixturesDir, 'url-global-asset-prefix-1')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const appDir = join(fixturesDir, 'url-global-asset-prefix-1')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it(`should've emitted expected files`, async () => {
const cssFolder = join(appDir, '.next/static/css')
const mediaFolder = join(appDir, '.next/static/media')
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
it(`should've emitted expected files`, async () => {
const cssFolder = join(appDir, '.next/static/css')
const mediaFolder = join(appDir, '.next/static/media')
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatch(
/^\.red-text\{color:red;background-image:url\(\/foo\/_next\/static\/media\/dark\.[a-f0-9]{8}\.svg\) url\(\/foo\/_next\/static\/media\/dark2\.[a-f0-9]{8}\.svg\)\}\.blue-text\{color:orange;font-weight:bolder;background-image:url\(\/foo\/_next\/static\/media\/light\.[a-f0-9]{8}\.svg\);color:blue\}$/
)
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
const mediaFiles = await readdir(mediaFolder)
expect(mediaFiles.length).toBe(3)
expect(
mediaFiles
.map((fileName) =>
/^(.+?)\..{8}\.(.+?)$/.exec(fileName).slice(1).join('.')
)
.sort()
).toMatchInlineSnapshot(`
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatch(
/^\.red-text\{color:red;background-image:url\(\/foo\/_next\/static\/media\/dark\.[a-f0-9]{8}\.svg\) url\(\/foo\/_next\/static\/media\/dark2\.[a-f0-9]{8}\.svg\)\}\.blue-text\{color:orange;font-weight:bolder;background-image:url\(\/foo\/_next\/static\/media\/light\.[a-f0-9]{8}\.svg\);color:blue\}$/
)
const mediaFiles = await readdir(mediaFolder)
expect(mediaFiles.length).toBe(3)
expect(
mediaFiles
.map((fileName) =>
/^(.+?)\..{8}\.(.+?)$/.exec(fileName).slice(1).join('.')
)
.sort()
).toMatchInlineSnapshot(`
Array [
"dark.svg",
"dark2.svg",
"light.svg",
]
`)
})
})
})
describe('CSS URL via `file-loader` and asset prefix (2)', () => {
const appDir = join(fixturesDir, 'url-global-asset-prefix-2')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const appDir = join(fixturesDir, 'url-global-asset-prefix-2')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it(`should've emitted expected files`, async () => {
const cssFolder = join(appDir, '.next/static/css')
const mediaFolder = join(appDir, '.next/static/media')
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
it(`should've emitted expected files`, async () => {
const cssFolder = join(appDir, '.next/static/css')
const mediaFolder = join(appDir, '.next/static/media')
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatch(
/^\.red-text\{color:red;background-image:url\(\/foo\/_next\/static\/media\/dark\.[a-f0-9]{8}\.svg\) url\(\/foo\/_next\/static\/media\/dark2\.[a-f0-9]{8}\.svg\)\}\.blue-text\{color:orange;font-weight:bolder;background-image:url\(\/foo\/_next\/static\/media\/light\.[a-f0-9]{8}\.svg\);color:blue\}$/
)
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
const mediaFiles = await readdir(mediaFolder)
expect(mediaFiles.length).toBe(3)
expect(
mediaFiles
.map((fileName) =>
/^(.+?)\..{8}\.(.+?)$/.exec(fileName).slice(1).join('.')
)
.sort()
).toMatchInlineSnapshot(`
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatch(
/^\.red-text\{color:red;background-image:url\(\/foo\/_next\/static\/media\/dark\.[a-f0-9]{8}\.svg\) url\(\/foo\/_next\/static\/media\/dark2\.[a-f0-9]{8}\.svg\)\}\.blue-text\{color:orange;font-weight:bolder;background-image:url\(\/foo\/_next\/static\/media\/light\.[a-f0-9]{8}\.svg\);color:blue\}$/
)
const mediaFiles = await readdir(mediaFolder)
expect(mediaFiles.length).toBe(3)
expect(
mediaFiles
.map((fileName) =>
/^(.+?)\..{8}\.(.+?)$/.exec(fileName).slice(1).join('.')
)
.sort()
).toMatchInlineSnapshot(`
Array [
"dark.svg",
"dark2.svg",
"light.svg",
]
`)
})
})
})

View file

@ -111,57 +111,61 @@ describe('Basic CSS Modules Ordering', () => {
})
describe('should handle unresolved files gracefully', () => {
const workDir = join(fixturesDir, 'unresolved-css-url')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const workDir = join(fixturesDir, 'unresolved-css-url')
it('should build correctly', async () => {
await remove(join(workDir, '.next'))
const { code } = await nextBuild(workDir)
expect(code).toBe(0)
})
it('should build correctly', async () => {
await remove(join(workDir, '.next'))
const { code } = await nextBuild(workDir)
expect(code).toBe(0)
})
it('should have correct file references in CSS output', async () => {
const cssFiles = await readdir(join(workDir, '.next/static/css'))
it('should have correct file references in CSS output', async () => {
const cssFiles = await readdir(join(workDir, '.next/static/css'))
for (const file of cssFiles) {
if (file.endsWith('.css.map')) continue
for (const file of cssFiles) {
if (file.endsWith('.css.map')) continue
const content = await readFile(
join(workDir, '.next/static/css', file),
'utf8'
)
console.log(file, content)
const content = await readFile(
join(workDir, '.next/static/css', file),
'utf8'
)
console.log(file, content)
// if it is the combined global CSS file there are double the expected
// results
const howMany = content.includes('p{') || content.includes('p,') ? 2 : 1
// if it is the combined global CSS file there are double the expected
// results
const howMany = content.includes('p{') || content.includes('p,') ? 2 : 1
expect(content.match(/\(\/vercel\.svg/g).length).toBe(howMany)
// expect(content.match(/\(vercel\.svg/g).length).toBe(howMany)
expect(content.match(/\(\/_next\/static\/media/g).length).toBe(1)
expect(content.match(/\(https:\/\//g).length).toBe(howMany)
}
expect(content.match(/\(\/vercel\.svg/g).length).toBe(howMany)
// expect(content.match(/\(vercel\.svg/g).length).toBe(howMany)
expect(content.match(/\(\/_next\/static\/media/g).length).toBe(1)
expect(content.match(/\(https:\/\//g).length).toBe(howMany)
}
})
})
})
describe('Data URLs', () => {
const workDir = join(fixturesDir, 'data-url')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const workDir = join(fixturesDir, 'data-url')
it('should compile successfully', async () => {
await remove(join(workDir, '.next'))
const { code } = await nextBuild(workDir)
expect(code).toBe(0)
})
it('should compile successfully', async () => {
await remove(join(workDir, '.next'))
const { code } = await nextBuild(workDir)
expect(code).toBe(0)
})
it('should have emitted expected files', async () => {
const cssFolder = join(workDir, '.next/static/css')
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
it('should have emitted expected files', async () => {
const cssFolder = join(workDir, '.next/static/css')
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatch(
/background:url\("data:[^"]+"\)/
)
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatch(
/background:url\("data:[^"]+"\)/
)
})
})
})
@ -249,36 +253,38 @@ describe('Ordering with Global CSS and Modules (dev)', () => {
})
describe('Ordering with Global CSS and Modules (prod)', () => {
const appDir = join(fixturesDir, 'global-and-module-ordering')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const appDir = join(fixturesDir, 'global-and-module-ordering')
let appPort
let app
let stdout
let code
beforeAll(async () => {
await remove(join(appDir, '.next'))
;({ code, stdout } = await nextBuild(appDir, [], {
stdout: true,
}))
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(async () => {
await killApp(app)
})
let appPort
let app
let stdout
let code
beforeAll(async () => {
await remove(join(appDir, '.next'))
;({ code, stdout } = await nextBuild(appDir, [], {
stdout: true,
}))
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(async () => {
await killApp(app)
})
it('should have compiled successfully', () => {
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it('should have compiled successfully', () => {
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it('should have the correct color (css ordering)', async () => {
const browser = await webdriver(appPort, '/')
it('should have the correct color (css ordering)', async () => {
const browser = await webdriver(appPort, '/')
const currentColor = await browser.eval(
`window.getComputedStyle(document.querySelector('#blueText')).color`
)
expect(currentColor).toMatchInlineSnapshot(`"rgb(0, 0, 255)"`)
const currentColor = await browser.eval(
`window.getComputedStyle(document.querySelector('#blueText')).color`
)
expect(currentColor).toMatchInlineSnapshot(`"rgb(0, 0, 255)"`)
})
})
})

View file

@ -178,150 +178,186 @@ describe('Font Optimization', () => {
})
// Re-run build to check if it works when build is cached
it('should work when build is cached', async () => {
await nextBuild(appDir)
const testJson = JSON.parse(
await fs.readFile(builtPage('font-manifest.json'), {
encoding: 'utf-8',
})
)
expect(testJson.length).toBeGreaterThan(0)
})
;(process.env.TURBOPACK ? it.skip : it)(
'should work when build is cached',
async () => {
await nextBuild(appDir)
const testJson = JSON.parse(
await fs.readFile(builtPage('font-manifest.json'), {
encoding: 'utf-8',
})
)
expect(testJson.length).toBeGreaterThan(0)
}
)
}
describe('Font optimization for SSR apps', () => {
beforeAll(async () => {
if (fs.pathExistsSync(join(appDir, '.next'))) {
await fs.remove(join(appDir, '.next'))
;(process.env.TURBOPACK ? describe.skip : describe)(
'production mode',
() => {
beforeAll(async () => {
if (fs.pathExistsSync(join(appDir, '.next'))) {
await fs.remove(join(appDir, '.next'))
}
await nextBuild(appDir)
appPort = await findPort()
app = await nextStart(appDir, appPort)
builtServerPagesDir = join(appDir, '.next', 'server')
builtPage = (file) => join(builtServerPagesDir, file)
})
afterAll(() => killApp(app))
runTests()
}
await nextBuild(appDir)
appPort = await findPort()
app = await nextStart(appDir, appPort)
builtServerPagesDir = join(appDir, '.next', 'server')
builtPage = (file) => join(builtServerPagesDir, file)
})
afterAll(() => killApp(app))
runTests()
)
})
describe('Font optimization for unreachable font definitions.', () => {
beforeAll(async () => {
await nextBuild(appDir)
await fs.writeFile(
join(appDir, '.next', 'server', 'font-manifest.json'),
'[]',
'utf8'
)
appPort = await findPort()
app = await nextStart(appDir, appPort)
builtServerPagesDir = join(appDir, '.next', 'server')
builtPage = (file) => join(builtServerPagesDir, file)
})
afterAll(() => killApp(app))
it('should fallback to normal stylesheet if the contents of the fonts are unreachable', async () => {
const html = await renderViaHTTP(appPort, '/stars')
expect(await fsExists(builtPage('font-manifest.json'))).toBe(true)
expect(html).toContain(`<link rel="stylesheet" href="${starsFont}"/>`)
})
it('should not inline multiple fallback link tag', async () => {
await renderViaHTTP(appPort, '/stars')
// second render to make sure that the page is requested more than once.
const html = await renderViaHTTP(appPort, '/stars')
expect(await fsExists(builtPage('font-manifest.json'))).toBe(true)
expect(html).not.toContain(
`<link rel="stylesheet" href="${staticFont}"/><link rel="stylesheet" href="${starsFont}"/><link rel="stylesheet" href="${staticFont}"/><link rel="stylesheet" href="${starsFont}"/>`
)
})
;(process.env.TURBOPACK ? describe.skip : describe)(
'production mode',
() => {
beforeAll(async () => {
await nextBuild(appDir)
await fs.writeFile(
join(appDir, '.next', 'server', 'font-manifest.json'),
'[]',
'utf8'
)
appPort = await findPort()
app = await nextStart(appDir, appPort)
builtServerPagesDir = join(appDir, '.next', 'server')
builtPage = (file) => join(builtServerPagesDir, file)
})
afterAll(() => killApp(app))
it('should fallback to normal stylesheet if the contents of the fonts are unreachable', async () => {
const html = await renderViaHTTP(appPort, '/stars')
expect(await fsExists(builtPage('font-manifest.json'))).toBe(true)
expect(html).toContain(
`<link rel="stylesheet" href="${starsFont}"/>`
)
})
it('should not inline multiple fallback link tag', async () => {
await renderViaHTTP(appPort, '/stars')
// second render to make sure that the page is requested more than once.
const html = await renderViaHTTP(appPort, '/stars')
expect(await fsExists(builtPage('font-manifest.json'))).toBe(true)
expect(html).not.toContain(
`<link rel="stylesheet" href="${staticFont}"/><link rel="stylesheet" href="${starsFont}"/><link rel="stylesheet" href="${staticFont}"/><link rel="stylesheet" href="${starsFont}"/>`
)
})
}
)
})
}
)
test('Spread operator regression on <link>', async () => {
const appDir = join(fixturesDir, 'spread-operator-regression')
const { code } = await nextBuild(appDir)
expect(code).toBe(0)
})
test('makeStylesheetInert regression', async () => {
const appDir = join(fixturesDir, 'make-stylesheet-inert-regression')
const { code } = await nextBuild(appDir)
expect(code).toBe(0)
})
;(process.env.TURBOPACK ? it.skip : it)(
'Spread operator regression on <link>',
async () => {
const appDir = join(fixturesDir, 'spread-operator-regression')
const { code } = await nextBuild(appDir)
// eslint-disable-next-line
expect(code).toBe(0)
}
)
;(process.env.TURBOPACK ? it.skip : it)(
'makeStylesheetInert regression',
async () => {
const appDir = join(fixturesDir, 'make-stylesheet-inert-regression')
const { code } = await nextBuild(appDir)
// eslint-disable-next-line
expect(code).toBe(0)
}
)
describe('font override', () => {
let app, appPort
;(process.env.TURBOPACK ? describe.skip : describe)(
'production mode',
() => {
let app, appPort
beforeAll(async () => {
const appDir = join(fixturesDir, 'font-override')
await nextBuild(appDir)
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(() => killApp(app))
it('should inline font-override values', async () => {
const html = await renderViaHTTP(appPort, '/')
const $ = cheerio.load(html)
const inlineStyle = $(
'style[data-href="https://fonts.googleapis.com/css2?family=Roboto&display=swap"]'
)
const inlineStyleMultiple = $(
'style[data-href="https://fonts.googleapis.com/css2?family=Open+Sans&family=Libre+Baskerville&display=swap"]'
)
expect(inlineStyle.length).toBe(1)
expect(inlineStyle.html()).toContain(
'@font-face{font-family:"Roboto Fallback";ascent-override:92.77%;descent-override:24.41%;line-gap-override:0.00%;src:local("Arial")}'
)
expect(inlineStyleMultiple.length).toBe(1)
expect(inlineStyleMultiple.html()).toContain(
'@font-face{font-family:"Libre Baskerville Fallback";ascent-override:97.00%;descent-override:27.00%;line-gap-override:0.00%;src:local("Times New Roman")}'
)
expect(inlineStyleMultiple.html()).toContain(
'@font-face{font-family:"Open Sans Fallback";ascent-override:106.88%;descent-override:29.30%;line-gap-override:0.00%;src:local("Arial")}'
)
})
beforeAll(async () => {
const appDir = join(fixturesDir, 'font-override')
await nextBuild(appDir)
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(() => killApp(app))
it('should inline font-override values', async () => {
const html = await renderViaHTTP(appPort, '/')
const $ = cheerio.load(html)
const inlineStyle = $(
'style[data-href="https://fonts.googleapis.com/css2?family=Roboto&display=swap"]'
)
const inlineStyleMultiple = $(
'style[data-href="https://fonts.googleapis.com/css2?family=Open+Sans&family=Libre+Baskerville&display=swap"]'
)
expect(inlineStyle.length).toBe(1)
expect(inlineStyle.html()).toContain(
'@font-face{font-family:"Roboto Fallback";ascent-override:92.77%;descent-override:24.41%;line-gap-override:0.00%;src:local("Arial")}'
)
expect(inlineStyleMultiple.length).toBe(1)
expect(inlineStyleMultiple.html()).toContain(
'@font-face{font-family:"Libre Baskerville Fallback";ascent-override:97.00%;descent-override:27.00%;line-gap-override:0.00%;src:local("Times New Roman")}'
)
expect(inlineStyleMultiple.html()).toContain(
'@font-face{font-family:"Open Sans Fallback";ascent-override:106.88%;descent-override:29.30%;line-gap-override:0.00%;src:local("Arial")}'
)
})
}
)
})
describe('font override with size adjust', () => {
let app, appPort
;(process.env.TURBOPACK ? describe.skip : describe)(
'production mode',
() => {
let app, appPort
beforeAll(async () => {
const appDir = join(fixturesDir, 'font-override-size-adjust')
await nextBuild(appDir)
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(() => killApp(app))
it('should inline font-override values', async () => {
const html = await renderViaHTTP(appPort, '/')
const $ = cheerio.load(html)
const inlineStyle = $(
'style[data-href="https://fonts.googleapis.com/css2?family=Roboto&display=swap"]'
)
const inlineStyleMultiple = $(
'style[data-href="https://fonts.googleapis.com/css2?family=Open+Sans&family=Libre+Baskerville&display=swap"]'
)
expect(inlineStyle.length).toBe(1)
expect(inlineStyle.html()).toContain(
'@font-face{font-family:"Roboto Fallback";ascent-override:92.67%;descent-override:24.39%;line-gap-override:0.00%;size-adjust:100.11%;src:local("Arial")}'
)
expect(inlineStyleMultiple.length).toBe(1)
expect(inlineStyleMultiple.html()).toContain(
'@font-face{font-family:"Libre Baskerville Fallback";ascent-override:75.76%;descent-override:21.09%;line-gap-override:0.00%;size-adjust:128.03%;src:local("Times New Roman")}'
)
expect(inlineStyleMultiple.html()).toContain(
'@font-face{font-family:"Open Sans Fallback";ascent-override:101.18%;descent-override:27.73%;line-gap-override:0.00%;size-adjust:105.64%;src:local("Arial")}'
)
})
beforeAll(async () => {
const appDir = join(fixturesDir, 'font-override-size-adjust')
await nextBuild(appDir)
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(() => killApp(app))
it('should inline font-override values', async () => {
const html = await renderViaHTTP(appPort, '/')
const $ = cheerio.load(html)
const inlineStyle = $(
'style[data-href="https://fonts.googleapis.com/css2?family=Roboto&display=swap"]'
)
const inlineStyleMultiple = $(
'style[data-href="https://fonts.googleapis.com/css2?family=Open+Sans&family=Libre+Baskerville&display=swap"]'
)
expect(inlineStyle.length).toBe(1)
expect(inlineStyle.html()).toContain(
'@font-face{font-family:"Roboto Fallback";ascent-override:92.67%;descent-override:24.39%;line-gap-override:0.00%;size-adjust:100.11%;src:local("Arial")}'
)
expect(inlineStyleMultiple.length).toBe(1)
expect(inlineStyleMultiple.html()).toContain(
'@font-face{font-family:"Libre Baskerville Fallback";ascent-override:75.76%;descent-override:21.09%;line-gap-override:0.00%;size-adjust:128.03%;src:local("Times New Roman")}'
)
expect(inlineStyleMultiple.html()).toContain(
'@font-face{font-family:"Open Sans Fallback";ascent-override:101.18%;descent-override:27.73%;line-gap-override:0.00%;size-adjust:105.64%;src:local("Arial")}'
)
})
}
)
})
describe('invalid configuration', () => {
it('should show a proper error if assetPrefix starts with .', async () => {
const appDir = join(fixturesDir, 'invalid-assertprefix')
const { stderr } = await nextBuild(appDir, undefined, {
stderr: true,
})
expect(stderr).toContain(
'assetPrefix must start with a leading slash or be an absolute URL(http:// or https://)'
)
})
;(process.env.TURBOPACK ? describe.skip : describe)(
'production mode',
() => {
it('should show a proper error if assetPrefix starts with .', async () => {
const appDir = join(fixturesDir, 'invalid-assertprefix')
const { stderr } = await nextBuild(appDir, undefined, {
stderr: true,
})
expect(stderr).toContain(
'assetPrefix must start with a leading slash or be an absolute URL(http:// or https://)'
)
})
}
)
})
})

View file

@ -37,7 +37,7 @@ function runTests(url: string) {
})
}
describe('Image Loader Config', () => {
describe('Image Loader Config new', () => {
describe('dev mode - component', () => {
beforeAll(async () => {
appPort = await findPort()

View file

@ -1,49 +0,0 @@
import {
check,
findPort,
killApp,
launchApp,
renderViaHTTP,
} from 'next-test-utils'
import { join } from 'path'
import fs from 'fs-extra'
import stripAnsi from 'strip-ansi'
describe.skip('Project Directory Delete Handling', () => {
it('should gracefully exit on project dir delete', async () => {
const appDir = join(__dirname, 'app')
const appPort = await findPort()
await fs.ensureDir(join(appDir, 'pages'))
await fs.writeFile(
join(appDir, 'pages', 'index.js'),
`
export default function Page() {
return <p>hello world</p>
}
`
)
let output = ''
const app = await launchApp(appDir, appPort, {
onStdout(msg) {
output += msg
},
onStderr(msg) {
output += msg
},
})
expect(await renderViaHTTP(appPort, '/')).toContain('hello world')
await fs.remove(appDir)
await check(
() => stripAnsi(output),
/Project directory could not be found, restart Next\.js in your new directory/
)
try {
await killApp(app)
} catch (_) {}
})
})

View file

@ -11,208 +11,234 @@ let app
let server
describe('Query String with Encoding', () => {
beforeAll(async () => {
await nextBuild(appDir)
app = nextServer({
dir: join(__dirname, '../'),
dev: false,
quiet: true,
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
beforeAll(async () => {
await nextBuild(appDir)
app = nextServer({
dir: join(__dirname, '../'),
dev: false,
quiet: true,
})
server = await startApp(app)
appPort = server.address().port
})
afterAll(() => stopApp(server))
describe('new line', () => {
it('should have correct query on SSR', async () => {
const browser = await webdriver(appPort, '/?test=abc%0A')
try {
const text = await browser.elementByCss('#query-content').text()
expect(text).toBe('{"test":"abc\\n"}')
} finally {
await browser.close()
}
})
it('should have correct query on Router#push', async () => {
const browser = await webdriver(appPort, '/')
try {
await browser.waitForCondition('!!window.next.router')
await browser.eval(
`window.next.router.push({pathname:'/',query:{abc:'def\\n'}})`
)
const text = await browser
.waitForElementByCss('#query-content')
.text()
expect(text).toBe('{"abc":"def\\n"}')
} finally {
await browser.close()
}
})
it('should have correct query on simple client-side <Link>', async () => {
const browser = await webdriver(appPort, '/newline')
try {
await browser.waitForElementByCss('#hello-lf').click()
const text = await browser
.waitForElementByCss('#query-content')
.text()
expect(text).toBe('{"another":"hello\\n"}')
} finally {
await browser.close()
}
})
it('should have correct query on complex client-side <Link>', async () => {
const browser = await webdriver(appPort, '/newline')
try {
await browser.waitForElementByCss('#hello-complex').click()
const text = await browser
.waitForElementByCss('#query-content')
.text()
expect(text).toBe('{"complex":"yes\\n"}')
} finally {
await browser.close()
}
})
})
server = await startApp(app)
appPort = server.address().port
})
afterAll(() => stopApp(server))
describe('trailing space', () => {
it('should have correct query on SSR', async () => {
const browser = await webdriver(appPort, '/?test=abc%20')
try {
const text = await browser.elementByCss('#query-content').text()
expect(text).toBe('{"test":"abc "}')
} finally {
await browser.close()
}
})
describe('new line', () => {
it('should have correct query on SSR', async () => {
const browser = await webdriver(appPort, '/?test=abc%0A')
try {
const text = await browser.elementByCss('#query-content').text()
expect(text).toBe('{"test":"abc\\n"}')
} finally {
await browser.close()
}
it('should have correct query on Router#push', async () => {
const browser = await webdriver(appPort, '/')
try {
await browser.waitForCondition('!!window.next.router')
await browser.eval(
`window.next.router.push({pathname:'/',query:{abc:'def '}})`
)
const text = await browser
.waitForElementByCss('#query-content')
.text()
expect(text).toBe('{"abc":"def "}')
} finally {
await browser.close()
}
})
it('should have correct query on simple client-side <Link>', async () => {
const browser = await webdriver(appPort, '/space')
try {
await browser.waitForElementByCss('#hello-space').click()
const text = await browser
.waitForElementByCss('#query-content')
.text()
expect(text).toBe('{"another":"hello "}')
} finally {
await browser.close()
}
})
it('should have correct query on complex client-side <Link>', async () => {
const browser = await webdriver(appPort, '/space')
try {
await browser.waitForElementByCss('#hello-complex').click()
const text = await browser
.waitForElementByCss('#query-content')
.text()
expect(text).toBe('{"complex":"yes "}')
} finally {
await browser.close()
}
})
})
it('should have correct query on Router#push', async () => {
const browser = await webdriver(appPort, '/')
try {
await browser.waitForCondition('!!window.next.router')
await browser.eval(
`window.next.router.push({pathname:'/',query:{abc:'def\\n'}})`
)
const text = await browser.waitForElementByCss('#query-content').text()
expect(text).toBe('{"abc":"def\\n"}')
} finally {
await browser.close()
}
describe('percent', () => {
it('should have correct query on SSR', async () => {
const browser = await webdriver(appPort, '/?test=abc%25')
try {
const text = await browser.elementByCss('#query-content').text()
expect(text).toBe('{"test":"abc%"}')
} finally {
await browser.close()
}
})
it('should have correct query on Router#push', async () => {
const browser = await webdriver(appPort, '/')
try {
await browser.waitForCondition('!!window.next.router')
await browser.eval(
`window.next.router.push({pathname:'/',query:{abc:'def%'}})`
)
const text = await browser
.waitForElementByCss('#query-content')
.text()
expect(text).toBe('{"abc":"def%"}')
} finally {
await browser.close()
}
})
it('should have correct query on simple client-side <Link>', async () => {
const browser = await webdriver(appPort, '/percent')
try {
await browser.waitForElementByCss('#hello-percent').click()
const text = await browser
.waitForElementByCss('#query-content')
.text()
expect(text).toBe('{"another":"hello%"}')
} finally {
await browser.close()
}
})
it('should have correct query on complex client-side <Link>', async () => {
const browser = await webdriver(appPort, '/percent')
try {
await browser.waitForElementByCss('#hello-complex').click()
const text = await browser
.waitForElementByCss('#query-content')
.text()
expect(text).toBe('{"complex":"yes%"}')
} finally {
await browser.close()
}
})
})
it('should have correct query on simple client-side <Link>', async () => {
const browser = await webdriver(appPort, '/newline')
try {
await browser.waitForElementByCss('#hello-lf').click()
const text = await browser.waitForElementByCss('#query-content').text()
expect(text).toBe('{"another":"hello\\n"}')
} finally {
await browser.close()
}
})
describe('plus', () => {
it('should have correct query on SSR', async () => {
const browser = await webdriver(appPort, '/?test=abc%2B')
try {
const text = await browser.elementByCss('#query-content').text()
expect(text).toBe('{"test":"abc+"}')
} finally {
await browser.close()
}
})
it('should have correct query on complex client-side <Link>', async () => {
const browser = await webdriver(appPort, '/newline')
try {
await browser.waitForElementByCss('#hello-complex').click()
const text = await browser.waitForElementByCss('#query-content').text()
expect(text).toBe('{"complex":"yes\\n"}')
} finally {
await browser.close()
}
})
})
it('should have correct query on Router#push', async () => {
const browser = await webdriver(appPort, '/')
try {
await browser.waitForCondition('!!window.next.router')
await browser.eval(
`window.next.router.push({pathname:'/',query:{abc:'def+'}})`
)
const text = await browser
.waitForElementByCss('#query-content')
.text()
expect(text).toBe('{"abc":"def+"}')
} finally {
await browser.close()
}
})
describe('trailing space', () => {
it('should have correct query on SSR', async () => {
const browser = await webdriver(appPort, '/?test=abc%20')
try {
const text = await browser.elementByCss('#query-content').text()
expect(text).toBe('{"test":"abc "}')
} finally {
await browser.close()
}
})
it('should have correct query on simple client-side <Link>', async () => {
const browser = await webdriver(appPort, '/plus')
try {
await browser.waitForElementByCss('#hello-plus').click()
const text = await browser
.waitForElementByCss('#query-content')
.text()
expect(text).toBe('{"another":"hello+"}')
} finally {
await browser.close()
}
})
it('should have correct query on Router#push', async () => {
const browser = await webdriver(appPort, '/')
try {
await browser.waitForCondition('!!window.next.router')
await browser.eval(
`window.next.router.push({pathname:'/',query:{abc:'def '}})`
)
const text = await browser.waitForElementByCss('#query-content').text()
expect(text).toBe('{"abc":"def "}')
} finally {
await browser.close()
}
})
it('should have correct query on simple client-side <Link>', async () => {
const browser = await webdriver(appPort, '/space')
try {
await browser.waitForElementByCss('#hello-space').click()
const text = await browser.waitForElementByCss('#query-content').text()
expect(text).toBe('{"another":"hello "}')
} finally {
await browser.close()
}
})
it('should have correct query on complex client-side <Link>', async () => {
const browser = await webdriver(appPort, '/space')
try {
await browser.waitForElementByCss('#hello-complex').click()
const text = await browser.waitForElementByCss('#query-content').text()
expect(text).toBe('{"complex":"yes "}')
} finally {
await browser.close()
}
})
})
describe('percent', () => {
it('should have correct query on SSR', async () => {
const browser = await webdriver(appPort, '/?test=abc%25')
try {
const text = await browser.elementByCss('#query-content').text()
expect(text).toBe('{"test":"abc%"}')
} finally {
await browser.close()
}
})
it('should have correct query on Router#push', async () => {
const browser = await webdriver(appPort, '/')
try {
await browser.waitForCondition('!!window.next.router')
await browser.eval(
`window.next.router.push({pathname:'/',query:{abc:'def%'}})`
)
const text = await browser.waitForElementByCss('#query-content').text()
expect(text).toBe('{"abc":"def%"}')
} finally {
await browser.close()
}
})
it('should have correct query on simple client-side <Link>', async () => {
const browser = await webdriver(appPort, '/percent')
try {
await browser.waitForElementByCss('#hello-percent').click()
const text = await browser.waitForElementByCss('#query-content').text()
expect(text).toBe('{"another":"hello%"}')
} finally {
await browser.close()
}
})
it('should have correct query on complex client-side <Link>', async () => {
const browser = await webdriver(appPort, '/percent')
try {
await browser.waitForElementByCss('#hello-complex').click()
const text = await browser.waitForElementByCss('#query-content').text()
expect(text).toBe('{"complex":"yes%"}')
} finally {
await browser.close()
}
})
})
describe('plus', () => {
it('should have correct query on SSR', async () => {
const browser = await webdriver(appPort, '/?test=abc%2B')
try {
const text = await browser.elementByCss('#query-content').text()
expect(text).toBe('{"test":"abc+"}')
} finally {
await browser.close()
}
})
it('should have correct query on Router#push', async () => {
const browser = await webdriver(appPort, '/')
try {
await browser.waitForCondition('!!window.next.router')
await browser.eval(
`window.next.router.push({pathname:'/',query:{abc:'def+'}})`
)
const text = await browser.waitForElementByCss('#query-content').text()
expect(text).toBe('{"abc":"def+"}')
} finally {
await browser.close()
}
})
it('should have correct query on simple client-side <Link>', async () => {
const browser = await webdriver(appPort, '/plus')
try {
await browser.waitForElementByCss('#hello-plus').click()
const text = await browser.waitForElementByCss('#query-content').text()
expect(text).toBe('{"another":"hello+"}')
} finally {
await browser.close()
}
})
it('should have correct query on complex client-side <Link>', async () => {
const browser = await webdriver(appPort, '/plus')
try {
await browser.waitForElementByCss('#hello-complex').click()
const text = await browser.waitForElementByCss('#query-content').text()
expect(text).toBe('{"complex":"yes+"}')
} finally {
await browser.close()
}
it('should have correct query on complex client-side <Link>', async () => {
const browser = await webdriver(appPort, '/plus')
try {
await browser.waitForElementByCss('#hello-complex').click()
const text = await browser
.waitForElementByCss('#query-content')
.text()
expect(text).toBe('{"complex":"yes+"}')
} finally {
await browser.close()
}
})
})
})
})

View file

@ -18,114 +18,120 @@ import { join } from 'path'
const fixturesDir = join(__dirname, '../../scss-fixtures')
describe('Basic SCSS Module Support', () => {
const appDir = join(fixturesDir, 'basic-module')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const appDir = join(fixturesDir, 'basic-module')
let appPort
let app
let stdout
let code
beforeAll(async () => {
await remove(join(appDir, '.next'))
;({ code, stdout } = await nextBuild(appDir, [], {
stdout: true,
}))
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(async () => {
await killApp(app)
})
let appPort
let app
let stdout
let code
beforeAll(async () => {
await remove(join(appDir, '.next'))
;({ code, stdout } = await nextBuild(appDir, [], {
stdout: true,
}))
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(async () => {
await killApp(app)
})
it('should have compiled successfully', () => {
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it('should have compiled successfully', () => {
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchInlineSnapshot(
`".index_redText__zXafh{color:red}"`
)
})
expect(
cssContent.replace(/\/\*.*?\*\//g, '').trim()
).toMatchInlineSnapshot(`".index_redText__zXafh{color:red}"`)
})
it(`should've injected the CSS on server render`, async () => {
const content = await renderViaHTTP(appPort, '/')
const $ = cheerio.load(content)
it(`should've injected the CSS on server render`, async () => {
const content = await renderViaHTTP(appPort, '/')
const $ = cheerio.load(content)
const cssPreload = $('link[rel="preload"][as="style"]')
expect(cssPreload.length).toBe(1)
expect(cssPreload.attr('href')).toMatch(/^\/_next\/static\/css\/.*\.css$/)
const cssPreload = $('link[rel="preload"][as="style"]')
expect(cssPreload.length).toBe(1)
expect(cssPreload.attr('href')).toMatch(/^\/_next\/static\/css\/.*\.css$/)
const cssSheet = $('link[rel="stylesheet"]')
expect(cssSheet.length).toBe(1)
expect(cssSheet.attr('href')).toMatch(/^\/_next\/static\/css\/.*\.css$/)
const cssSheet = $('link[rel="stylesheet"]')
expect(cssSheet.length).toBe(1)
expect(cssSheet.attr('href')).toMatch(/^\/_next\/static\/css\/.*\.css$/)
expect($('#verify-red').attr('class')).toMatchInlineSnapshot(
`"index_redText__zXafh"`
)
expect($('#verify-red').attr('class')).toMatchInlineSnapshot(
`"index_redText__zXafh"`
)
})
})
})
describe('3rd Party CSS Module Support', () => {
const appDir = join(fixturesDir, '3rd-party-module')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const appDir = join(fixturesDir, '3rd-party-module')
let appPort
let app
let stdout
let code
beforeAll(async () => {
await remove(join(appDir, '.next'))
;({ code, stdout } = await nextBuild(appDir, [], {
stdout: true,
}))
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(async () => {
await killApp(app)
})
let appPort
let app
let stdout
let code
beforeAll(async () => {
await remove(join(appDir, '.next'))
;({ code, stdout } = await nextBuild(appDir, [], {
stdout: true,
}))
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(async () => {
await killApp(app)
})
it('should have compiled successfully', () => {
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it('should have compiled successfully', () => {
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchInlineSnapshot(
`".index_foo__72b4D{position:relative}.index_foo__72b4D .bar,.index_foo__72b4D .baz{height:100%;overflow:hidden}.index_foo__72b4D .lol,.index_foo__72b4D>.lel{width:80%}"`
)
})
expect(
cssContent.replace(/\/\*.*?\*\//g, '').trim()
).toMatchInlineSnapshot(
`".index_foo__72b4D{position:relative}.index_foo__72b4D .bar,.index_foo__72b4D .baz{height:100%;overflow:hidden}.index_foo__72b4D .lol,.index_foo__72b4D>.lel{width:80%}"`
)
})
it(`should've injected the CSS on server render`, async () => {
const content = await renderViaHTTP(appPort, '/')
const $ = cheerio.load(content)
it(`should've injected the CSS on server render`, async () => {
const content = await renderViaHTTP(appPort, '/')
const $ = cheerio.load(content)
const cssPreload = $('link[rel="preload"][as="style"]')
expect(cssPreload.length).toBe(1)
expect(cssPreload.attr('href')).toMatch(/^\/_next\/static\/css\/.*\.css$/)
const cssPreload = $('link[rel="preload"][as="style"]')
expect(cssPreload.length).toBe(1)
expect(cssPreload.attr('href')).toMatch(/^\/_next\/static\/css\/.*\.css$/)
const cssSheet = $('link[rel="stylesheet"]')
expect(cssSheet.length).toBe(1)
expect(cssSheet.attr('href')).toMatch(/^\/_next\/static\/css\/.*\.css$/)
const cssSheet = $('link[rel="stylesheet"]')
expect(cssSheet.length).toBe(1)
expect(cssSheet.attr('href')).toMatch(/^\/_next\/static\/css\/.*\.css$/)
expect($('#verify-div').attr('class')).toMatchInlineSnapshot(
`"index_foo__72b4D"`
)
expect($('#verify-div').attr('class')).toMatchInlineSnapshot(
`"index_foo__72b4D"`
)
})
})
})
@ -154,36 +160,38 @@ describe('Has CSS Module in computed styles in Development', () => {
})
describe('Has CSS Module in computed styles in Production', () => {
const appDir = join(fixturesDir, 'prod-module')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const appDir = join(fixturesDir, 'prod-module')
let appPort
let app
let stdout
let code
beforeAll(async () => {
await remove(join(appDir, '.next'))
;({ code, stdout } = await nextBuild(appDir, [], {
stdout: true,
}))
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(async () => {
await killApp(app)
})
let appPort
let app
let stdout
let code
beforeAll(async () => {
await remove(join(appDir, '.next'))
;({ code, stdout } = await nextBuild(appDir, [], {
stdout: true,
}))
appPort = await findPort()
app = await nextStart(appDir, appPort)
})
afterAll(async () => {
await killApp(app)
})
it('should have compiled successfully', () => {
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it('should have compiled successfully', () => {
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it('should have CSS for page', async () => {
const browser = await webdriver(appPort, '/')
it('should have CSS for page', async () => {
const browser = await webdriver(appPort, '/')
const currentColor = await browser.eval(
`window.getComputedStyle(document.querySelector('#verify-red')).color`
)
expect(currentColor).toMatchInlineSnapshot(`"rgb(255, 0, 0)"`)
const currentColor = await browser.eval(
`window.getComputedStyle(document.querySelector('#verify-red')).color`
)
expect(currentColor).toMatchInlineSnapshot(`"rgb(255, 0, 0)"`)
})
})
})
@ -234,67 +242,75 @@ describe('Can hot reload CSS Module without losing state', () => {
})
describe('CSS Module Composes Usage (Basic)', () => {
// This is a very bad feature. Do not use it.
const appDir = join(fixturesDir, 'composes-basic')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
// This is a very bad feature. Do not use it.
const appDir = join(fixturesDir, 'composes-basic')
let stdout
let code
beforeAll(async () => {
await remove(join(appDir, '.next'))
;({ code, stdout } = await nextBuild(appDir, [], {
stdout: true,
}))
})
let stdout
let code
beforeAll(async () => {
await remove(join(appDir, '.next'))
;({ code, stdout } = await nextBuild(appDir, [], {
stdout: true,
}))
})
it('should have compiled successfully', () => {
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it('should have compiled successfully', () => {
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchInlineSnapshot(
`".index_className__OLWEh{background:red;color:#ff0}.index_subClass__Z_IFg{background:blue}"`
)
expect(
cssContent.replace(/\/\*.*?\*\//g, '').trim()
).toMatchInlineSnapshot(
`".index_className__OLWEh{background:red;color:#ff0}.index_subClass__Z_IFg{background:blue}"`
)
})
})
})
describe('CSS Module Composes Usage (External)', () => {
// This is a very bad feature. Do not use it.
const appDir = join(fixturesDir, 'composes-external')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
// This is a very bad feature. Do not use it.
const appDir = join(fixturesDir, 'composes-external')
let stdout
let code
beforeAll(async () => {
await remove(join(appDir, '.next'))
;({ code, stdout } = await nextBuild(appDir, [], {
stdout: true,
}))
})
let stdout
let code
beforeAll(async () => {
await remove(join(appDir, '.next'))
;({ code, stdout } = await nextBuild(appDir, [], {
stdout: true,
}))
})
it('should have compiled successfully', () => {
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it('should have compiled successfully', () => {
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchInlineSnapshot(
`".other_className__A8aN2{background:red;color:#ff0}.index_subClass__Z_IFg{background:blue}"`
)
expect(
cssContent.replace(/\/\*.*?\*\//g, '').trim()
).toMatchInlineSnapshot(
`".other_className__A8aN2{background:red;color:#ff0}.index_subClass__Z_IFg{background:blue}"`
)
})
})
})

View file

@ -7,274 +7,296 @@ import { join } from 'path'
const fixturesDir = join(__dirname, '../..', 'scss-fixtures')
describe('Basic Global Support', () => {
const appDir = join(fixturesDir, 'single-global')
describe('Basic Global Support scss', () => {
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const appDir = join(fixturesDir, 'single-global')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
expect(cssFiles.length).toBe(1)
expect(await readFile(join(cssFolder, cssFiles[0]), 'utf8')).toContain(
'color:red'
)
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
expect(cssFiles.length).toBe(1)
expect(await readFile(join(cssFolder, cssFiles[0]), 'utf8')).toContain(
'color:red'
)
})
})
})
describe('Basic Module Include Paths Support', () => {
const appDir = join(fixturesDir, 'basic-module-include-paths')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const appDir = join(fixturesDir, 'basic-module-include-paths')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
expect(cssFiles.length).toBe(1)
expect(await readFile(join(cssFolder, cssFiles[0]), 'utf8')).toContain(
'color:red'
)
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
expect(cssFiles.length).toBe(1)
expect(await readFile(join(cssFolder, cssFiles[0]), 'utf8')).toContain(
'color:red'
)
})
})
})
describe('Basic Module Prepend Data Support', () => {
const appDir = join(fixturesDir, 'basic-module-prepend-data')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const appDir = join(fixturesDir, 'basic-module-prepend-data')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
expect(cssFiles.length).toBe(1)
expect(await readFile(join(cssFolder, cssFiles[0]), 'utf8')).toContain(
'color:red'
)
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
expect(cssFiles.length).toBe(1)
expect(await readFile(join(cssFolder, cssFiles[0]), 'utf8')).toContain(
'color:red'
)
})
})
})
describe('Basic Global Support with src/ dir', () => {
const appDir = join(fixturesDir, 'single-global-src')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const appDir = join(fixturesDir, 'single-global-src')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
expect(cssFiles.length).toBe(1)
expect(await readFile(join(cssFolder, cssFiles[0]), 'utf8')).toContain(
'color:red'
)
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
expect(cssFiles.length).toBe(1)
expect(await readFile(join(cssFolder, cssFiles[0]), 'utf8')).toContain(
'color:red'
)
})
})
})
describe('Multi Global Support', () => {
const appDir = join(fixturesDir, 'multi-global')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const appDir = join(fixturesDir, 'multi-global')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchInlineSnapshot(
`".red-text{color:red}.blue-text{color:blue}"`
)
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(
cssContent.replace(/\/\*.*?\*\//g, '').trim()
).toMatchInlineSnapshot(`".red-text{color:red}.blue-text{color:blue}"`)
})
})
})
describe('Nested @import() Global Support', () => {
const appDir = join(fixturesDir, 'nested-global')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const appDir = join(fixturesDir, 'nested-global')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchInlineSnapshot(
`".red-text{color:purple;font-weight:bolder;color:red}.blue-text{color:orange;font-weight:bolder;color:blue}"`
)
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(
cssContent.replace(/\/\*.*?\*\//g, '').trim()
).toMatchInlineSnapshot(
`".red-text{color:purple;font-weight:bolder;color:red}.blue-text{color:orange;font-weight:bolder;color:blue}"`
)
})
})
})
// Tests css ordering
describe('Multi Global Support (reversed)', () => {
const appDir = join(fixturesDir, 'multi-global-reversed')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const appDir = join(fixturesDir, 'multi-global-reversed')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchInlineSnapshot(
`".blue-text{color:blue}.red-text{color:red}"`
)
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(
cssContent.replace(/\/\*.*?\*\//g, '').trim()
).toMatchInlineSnapshot(`".blue-text{color:blue}.red-text{color:red}"`)
})
})
})
describe('Good CSS Import from node_modules', () => {
const appDir = join(fixturesDir, 'npm-import')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const appDir = join(fixturesDir, 'npm-import')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatch(/nprogress/)
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatch(/nprogress/)
})
})
})
describe('Good Nested CSS Import from node_modules', () => {
const appDir = join(fixturesDir, 'npm-import-nested')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const appDir = join(fixturesDir, 'npm-import-nested')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
it(`should've emitted a single CSS file`, async () => {
const cssFolder = join(appDir, '.next/static/css')
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchInlineSnapshot(
`".other{color:blue}.test{color:red}"`
)
const files = await readdir(cssFolder)
const cssFiles = files.filter((f) => /\.css$/.test(f))
expect(cssFiles.length).toBe(1)
const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8')
expect(
cssContent.replace(/\/\*.*?\*\//g, '').trim()
).toMatchInlineSnapshot(`".other{color:blue}.test{color:red}"`)
})
})
})
describe('CSS Import from node_modules', () => {
const appDir = join(fixturesDir, 'npm-import-bad')
;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => {
const appDir = join(fixturesDir, 'npm-import-bad')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should fail the build', async () => {
const { code, stderr } = await nextBuild(appDir, [], { stderr: true })
it('should fail the build', async () => {
const { code, stderr } = await nextBuild(appDir, [], { stderr: true })
expect(code).toBe(0)
expect(stderr).not.toMatch(/Can't resolve '[^']*?nprogress[^']*?'/)
expect(stderr).not.toMatch(/Build error occurred/)
expect(code).toBe(0)
expect(stderr).not.toMatch(/Can't resolve '[^']*?nprogress[^']*?'/)
expect(stderr).not.toMatch(/Build error occurred/)
})
})
})

View file

@ -28,26 +28,33 @@ describe('SCSS Support', () => {
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
;(process.env.TURBOPACK ? it.skip : it)(
'should be a friendly error successfully',
async () => {
const { code, stderr } = await nextBuild(appDir, [], {
env: { NODE_OPTIONS: shellQuote([`--require`, mockFile]) },
stderr: true,
})
let cleanScssErrMsg =
'\n\n' +
'./styles/global.scss\n' +
"To use Next.js' built-in Sass support, you first need to install `sass`.\n" +
'Run `npm i sass` or `yarn add sass` inside your workspace.\n' +
'\n' +
'Learn more: https://nextjs.org/docs/messages/install-sass\n'
it('should be a friendly error successfully', async () => {
const { code, stderr } = await nextBuild(appDir, [], {
env: { NODE_OPTIONS: shellQuote([`--require`, mockFile]) },
stderr: true,
})
let cleanScssErrMsg =
'\n\n' +
'./styles/global.scss\n' +
"To use Next.js' built-in Sass support, you first need to install `sass`.\n" +
'Run `npm i sass` or `yarn add sass` inside your workspace.\n' +
'\n' +
'Learn more: https://nextjs.org/docs/messages/install-sass\n'
expect(code).toBe(1)
expect(stderr).toContain('Failed to compile.')
expect(stderr).toContain(cleanScssErrMsg)
expect(stderr).not.toContain('css-loader')
expect(stderr).not.toContain('sass-loader')
})
// eslint-disable-next-line
expect(code).toBe(1)
// eslint-disable-next-line
expect(stderr).toContain('Failed to compile.')
// eslint-disable-next-line
expect(stderr).toContain(cleanScssErrMsg)
// eslint-disable-next-line
expect(stderr).not.toContain('css-loader')
// eslint-disable-next-line
expect(stderr).not.toContain('sass-loader')
}
)
})
describe('CSS Compilation and Prefixing', () => {

View file

@ -7,21 +7,25 @@ import { join } from 'path'
const fixturesDir = join(__dirname, '../..', 'scss-fixtures')
describe('SCSS Support', () => {
describe('SCSS Support loader handling', () => {
describe('CSS URL via `file-loader`', () => {
const appDir = join(fixturesDir, 'url-global')
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
;(process.env.TURBOPACK ? it.skip : it)(
'should compile successfully',
async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
// eslint-disable-next-line
expect(code).toBe(0)
// eslint-disable-next-line
expect(stdout).toMatch(/Compiled successfully/)
}
)
it(`should've emitted expected files`, async () => {
const cssFolder = join(appDir, '.next/static/css')
@ -60,14 +64,18 @@ describe('SCSS Support', () => {
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
;(process.env.TURBOPACK ? it.skip : it)(
'should compile successfully',
async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
// eslint-disable-next-line
expect(code).toBe(0)
// eslint-disable-next-line
expect(stdout).toMatch(/Compiled successfully/)
}
)
it(`should've emitted expected files`, async () => {
const cssFolder = join(appDir, '.next/static/css')
@ -108,14 +116,18 @@ describe('SCSS Support', () => {
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
;(process.env.TURBOPACK ? it.skip : it)(
'should compile successfully',
async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
// eslint-disable-next-line
expect(code).toBe(0)
// eslint-disable-next-line
expect(stdout).toMatch(/Compiled successfully/)
}
)
it(`should've emitted expected files`, async () => {
const cssFolder = join(appDir, '.next/static/css')
@ -154,14 +166,18 @@ describe('SCSS Support', () => {
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
;(process.env.TURBOPACK ? it.skip : it)(
'should compile successfully',
async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
// eslint-disable-next-line
expect(code).toBe(0)
// eslint-disable-next-line
expect(stdout).toMatch(/Compiled successfully/)
}
)
it(`should've emitted expected files`, async () => {
const cssFolder = join(appDir, '.next/static/css')
@ -200,14 +216,18 @@ describe('SCSS Support', () => {
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
;(process.env.TURBOPACK ? it.skip : it)(
'should compile successfully',
async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
// eslint-disable-next-line
expect(code).toBe(0)
// eslint-disable-next-line
expect(stdout).toMatch(/Compiled successfully/)
}
)
it(`should've emitted expected files`, async () => {
const cssFolder = join(appDir, '.next/static/css')
@ -229,14 +249,18 @@ describe('SCSS Support', () => {
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should compile successfully', async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
})
;(process.env.TURBOPACK ? it.skip : it)(
'should compile successfully',
async () => {
const { code, stdout } = await nextBuild(appDir, [], {
stdout: true,
})
// eslint-disable-next-line
expect(code).toBe(0)
// eslint-disable-next-line
expect(stdout).toMatch(/Compiled successfully/)
}
)
it(`should've emitted expected files`, async () => {
const cssFolder = join(appDir, '.next/static/css')
@ -258,12 +282,15 @@ describe('SCSS Support', () => {
beforeAll(async () => {
await remove(join(appDir, '.next'))
})
it('should compile successfully', async () => {
const { stdout } = await nextBuild(appDir, [], {
stdout: true,
})
expect(stdout).toMatch(/Compiled successfully/)
})
;(process.env.TURBOPACK ? it.skip : it)(
'should compile successfully',
async () => {
const { stdout } = await nextBuild(appDir, [], {
stdout: true,
})
// eslint-disable-next-line
expect(stdout).toMatch(/Compiled successfully/)
}
)
})
})

View file

@ -20,63 +20,64 @@ jest.setTimeout(1000 * 60 * 2)
const appDir = join(__dirname, '../')
for (const dev of [false, true]) {
describe(`Handle new URL asset references in next ${
dev ? 'dev' : 'build'
}`, () => {
let appPort
let app
beforeAll(async () => {
await fs.remove(join(appDir, '.next'))
if (dev) {
appPort = await findPort()
app = await launchApp(appDir, appPort)
} else {
await nextBuild(appDir)
appPort = await findPort()
app = await nextStart(appDir, appPort)
}
})
afterAll(() => killApp(app))
const expectedServer =
/Hello <!-- -->\/_next\/static\/media\/vercel\.[0-9a-f]{8}\.png<!-- -->\+<!-- -->\/_next\/static\/media\/vercel\.[0-9a-f]{8}\.png/
const expectedClient = new RegExp(
expectedServer.source.replace(/<!-- -->/g, '')
)
for (const page of ['/static', '/ssr', '/ssg']) {
it(`should render the ${page} page`, async () => {
const html = await renderViaHTTP(appPort, page)
expect(html).toMatch(expectedServer)
})
it(`should client-render the ${page} page`, async () => {
let browser
try {
browser = await webdriver(appPort, page)
await check(() => getBrowserBodyText(browser), expectedClient)
} finally {
await browser.close()
;(process.env.TURBOPACK && !dev ? describe.skip : describe)(
`Handle new URL asset references in next ${dev ? 'dev' : 'build'}`,
() => {
let appPort
let app
beforeAll(async () => {
await fs.remove(join(appDir, '.next'))
if (dev) {
appPort = await findPort()
app = await launchApp(appDir, appPort)
} else {
await nextBuild(appDir)
appPort = await findPort()
app = await nextStart(appDir, appPort)
}
})
}
afterAll(() => killApp(app))
it('should respond on size api', async () => {
const data = await fetchViaHTTP(appPort, '/api/size').then(
(res) => res.ok && res.json()
const expectedServer =
/Hello <!-- -->\/_next\/static\/media\/vercel\.[0-9a-f]{8}\.png<!-- -->\+<!-- -->\/_next\/static\/media\/vercel\.[0-9a-f]{8}\.png/
const expectedClient = new RegExp(
expectedServer.source.replace(/<!-- -->/g, '')
)
expect(data).toEqual({ size: 30079 })
})
for (const page of ['/static', '/ssr', '/ssg']) {
it(`should render the ${page} page`, async () => {
const html = await renderViaHTTP(appPort, page)
expect(html).toMatch(expectedServer)
})
it('should respond on basename api', async () => {
const data = await fetchViaHTTP(appPort, '/api/basename').then(
(res) => res.ok && res.json()
)
it(`should client-render the ${page} page`, async () => {
let browser
try {
browser = await webdriver(appPort, page)
await check(() => getBrowserBodyText(browser), expectedClient)
} finally {
await browser.close()
}
})
}
expect(data).toEqual({
basename: expect.stringMatching(/^vercel\.[0-9a-f]{8}\.png$/),
it('should respond on size api', async () => {
const data = await fetchViaHTTP(appPort, '/api/size').then(
(res) => res.ok && res.json()
)
expect(data).toEqual({ size: 30079 })
})
})
})
it('should respond on basename api', async () => {
const data = await fetchViaHTTP(appPort, '/api/basename').then(
(res) => res.ok && res.json()
)
expect(data).toEqual({
basename: expect.stringMatching(/^vercel\.[0-9a-f]{8}\.png$/),
})
})
}
)
}