From b51a703d22edaedffa35ada2060019bb9031d5db Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 25 Mar 2024 11:15:58 +0100 Subject: [PATCH 1/2] Rename process.env.TURBOPACK -> process.env.TURBOPACK_DEV in test skips --- .../e2e/app-dir/ppr-errors/ppr-errors.test.ts | 73 +- .../404-page-app/test/index.test.js | 65 +- .../404-page-custom-error/test/index.test.js | 29 +- .../404-page-ssg/test/index.test.js | 67 +- test/integration/404-page/test/index.test.js | 206 ++-- .../500-page/test/gsp-gssp.test.js | 229 ++-- test/integration/500-page/test/index.test.js | 51 +- .../absolute-assetprefix/test/index.test.js | 185 +-- .../amp-export-validation/test/index.test.js | 171 +-- .../test/index.test.js | 81 +- .../test/index.test.js | 2 +- .../amphtml-fragment-style/test/index.test.js | 35 +- .../amphtml-ssg/test/index.test.js | 27 +- test/integration/amphtml/test/index.test.js | 375 +++--- .../api-catch-all/test/index.test.js | 21 +- .../api-support/test/index.test.js | 23 +- .../app-dir-export/test/config.test.ts | 135 +-- .../test/dynamic-missing-gsp-prod.test.ts | 39 +- .../test/dynamicapiroute-prod.test.ts | 37 +- .../test/dynamicpage-prod.test.ts | 37 +- .../app-dir-export/test/start.test.ts | 77 +- .../test/trailing-slash-start.test.ts | 19 +- .../test/index.test.js | 37 +- .../test/index.test.js | 43 +- .../app-dynamic-error/test/index.test.ts | 27 +- test/integration/app-tree/test/index.test.js | 21 +- test/integration/app-types/app-types.test.js | 201 ++-- .../async-modules/test/index.test.js | 25 +- .../auto-export-error-bail/test/index.test.js | 9 +- .../test/index.test.js | 25 +- .../auto-export/test/index.test.js | 25 +- .../test/index.test.js | 23 +- test/integration/bigint/test/index.test.js | 23 +- .../build-output/test/index.test.js | 481 ++++---- .../test/index.test.js | 159 +-- .../test/index.test.js | 207 ++-- .../build-warnings/test/index.test.js | 127 ++- .../test/index.test.js | 17 +- test/integration/chunking/test/index.test.js | 201 ++-- .../clean-distdir/test/index.test.js | 41 +- test/integration/cli/test/index.test.js | 461 ++++---- .../integration/client-404/test/index.test.js | 41 +- .../client-shallow-routing/test/index.test.js | 23 +- .../test/index.test.js | 95 +- .../config-promise-error/test/index.test.js | 33 +- .../config-syntax-error/test/index.test.js | 63 +- .../config-validation/test/index.test.ts | 97 +- .../test/index.test.js | 31 +- .../conflicting-ssg-paths/test/index.test.js | 167 +-- .../critical-css/test/index.test.js | 43 +- .../css-client-nav/test/index.test.js | 131 +-- .../css-customization/test/index.test.js | 516 +++++---- .../css-features/test/browserslist.test.js | 138 +-- .../css-features/test/css-modules.test.js | 223 ++-- .../css-features/test/index.test.js | 195 ++-- .../integration/css-minify/test/index.test.js | 25 +- .../css-modules/test/index.test.js | 937 +++++++-------- .../css/test/basic-global-support.test.js | 577 +++++----- .../css/test/css-and-styled-jsx.test.js | 61 +- .../css/test/css-compilation.test.js | 597 +++++----- test/integration/css/test/css-modules.test.js | 176 +-- .../css/test/css-rendering.test.js | 66 +- .../css/test/valid-invalid-css.test.js | 199 ++-- .../test/index.test.js | 43 +- .../custom-error/test/index.test.js | 37 +- .../custom-page-extension/test/index.test.js | 21 +- .../custom-routes-catchall/test/index.test.js | 23 +- .../test/index.test.js | 21 +- .../custom-routes-i18n/test/index.test.js | 21 +- .../custom-routes/test/index.test.js | 98 +- .../custom-server/test/index.test.js | 4 +- .../data-fetching-errors/test/index.test.js | 67 +- .../dedupes-scripts/test/index.test.js | 49 +- .../integration/disable-js/test/index.test.js | 59 +- test/integration/dist-dir/test/index.test.js | 47 +- .../test/index.test.js | 103 +- .../integration/draft-mode/test/index.test.ts | 219 ++-- .../test/index.test.js | 31 +- .../test/index.test.js | 29 +- .../test/index.test.js | 71 +- .../dynamic-routing/test/index.test.js | 25 +- .../test/index.test.js | 8 +- .../test/index.test.js | 2 +- .../test/index.test.js | 10 +- .../test/module-imports.test.js | 20 +- .../test/index.test.js | 2 +- .../test/index.test.ts | 33 +- .../test/index.test.ts | 47 +- .../integration/env-config/test/index.test.js | 39 +- .../error-in-error/test/index.test.js | 41 +- .../error-load-fail/test/index.test.js | 80 +- .../test/index.test.js | 49 +- .../test/index.test.js | 23 +- .../eslint/test/next-build.test.js | 303 ++--- .../integration/export-404/test/index.test.js | 62 +- .../export-default-map/test/index.test.js | 107 +- .../export-dynamic-pages/test/index.test.js | 59 +- .../test/index.test.js | 33 +- .../test/index.test.js | 19 +- .../export-image-default/test/index.test.js | 25 +- .../test/index.test.js | 238 ++-- .../export-image-loader/test/index.test.js | 307 ++--- .../test/index.test.ts | 19 +- .../export-intent/test/index.test.js | 67 +- .../export-subfolders/test/index.test.js | 49 +- .../externals-esm-loose/test/index.test.js | 49 +- .../externals-pages-bundle/test/index.test.js | 41 +- .../fallback-false-rewrite/test/index.test.js | 25 +- .../fallback-modules/test/index.test.js | 91 +- .../fallback-route-params/test/index.test.js | 23 +- .../test/index.test.js | 35 +- .../fetch-polyfill/test/index.test.js | 35 +- .../file-serving/test/index.test.js | 45 +- .../firebase-grpc/test/index.test.js | 59 +- .../font-optimization/test/index.test.js | 10 +- test/integration/future/test/index.test.js | 37 +- .../getinitialprops/test/index.test.js | 21 +- .../test/index.test.js | 17 +- .../test/index.test.js | 9 +- .../gip-identifier/test/index.test.js | 9 +- .../gsp-build-errors/test/index.test.js | 145 +-- .../gsp-extension/test/index.test.js | 84 +- .../gssp-pageProps-merge/test/index.test.js | 27 +- .../test/index.test.js | 55 +- .../gssp-redirect/test/index.test.js | 77 +- .../handles-export-errors/test/index.test.js | 41 +- test/integration/hashbang/test/index.test.js | 25 +- .../hydrate-then-render/test/index.test.js | 49 +- test/integration/hydration/test/index.test.js | 23 +- .../i18n-support-base-path/test/index.test.js | 37 +- .../i18n-support-catchall/test/index.test.js | 27 +- .../test/index.test.js | 21 +- .../test/index.test.js | 29 +- .../test/index.test.js | 29 +- .../test/index.test.js | 21 +- .../test/index.test.js | 21 +- .../i18n-support/test/index.test.js | 130 ++- .../image-generation/test/index.test.ts | 51 +- .../image-optimizer/test/index.test.ts | 4 +- test/integration/image-optimizer/test/util.ts | 4 +- .../index-index/test/index.test.js | 35 +- .../initial-ref/test/index.test.js | 21 +- .../invalid-config-values/test/index.test.js | 45 +- .../invalid-custom-routes/test/index.test.js | 23 +- .../test/index.test.js | 53 +- .../invalid-href/test/index.test.js | 97 +- .../test/index.test.js | 23 +- .../invalid-multi-match/test/index.test.js | 27 +- .../test/index.test.js | 79 +- .../jsconfig-baseurl/test/index.test.js | 2 +- .../jsconfig-empty/test/index.test.js | 19 +- .../jsconfig-paths/test/index.test.js | 2 +- test/integration/jsconfig/test/index.test.js | 47 +- .../test/index.test.js | 17 +- test/integration/link-ref/test/index.test.js | 47 +- .../link-without-router/test/index.test.js | 27 +- .../middleware-basic/test/index.test.js | 31 +- .../test/index.test.js | 117 +- .../middleware-prefetch/tests/index.test.js | 113 +- .../middleware-src/test/index.test.js | 41 +- .../test/index.test.js | 129 ++- .../next-dynamic-css/test/index.test.js | 23 +- .../test/index.test.js | 2 +- .../next-dynamic/test/index.test.js | 31 +- .../asset-prefix/test/index.test.ts | 47 +- .../base-path/test/index.test.ts | 21 +- .../base-path/test/static.test.ts | 62 +- .../basic/test/index.test.ts | 229 ++-- .../custom-resolver/test/index.test.ts | 55 +- .../default/test/index.test.ts | 25 +- .../default/test/static.test.ts | 66 +- .../test/index.test.ts | 25 +- .../test/index.test.ts | 95 +- .../noscript/test/index.test.ts | 49 +- .../react-virtualized/test/index.test.ts | 103 +- .../svgo-webpack/test/index.test.ts | 2 +- .../trailing-slash/test/index.test.ts | 57 +- .../typescript/test/index.test.ts | 57 +- .../unicode/test/index.test.ts | 33 +- .../unoptimized/test/index.test.ts | 25 +- .../test/index.test.ts | 25 +- .../next-image-new/app-dir/test/index.test.ts | 25 +- .../app-dir/test/static.test.ts | 68 +- .../asset-prefix/test/index.test.js | 65 +- .../base-path/test/index.test.js | 27 +- .../base-path/test/static.test.js | 68 +- .../test/index.test.ts | 21 +- .../next-image-new/default/test/index.test.ts | 25 +- .../default/test/static.test.ts | 68 +- .../test/index.test.ts | 25 +- .../invalid-image-import/test/index.test.ts | 29 +- .../test/index.test.ts | 4 +- .../test/index.test.ts | 33 +- .../loader-config/test/index.test.ts | 4 +- .../react-virtualized/test/index.test.ts | 103 +- .../svgo-webpack/test/index.test.ts | 2 +- .../trailing-slash/test/index.test.ts | 57 +- .../typescript/test/index.test.ts | 57 +- .../next-image-new/unicode/test/index.test.ts | 33 +- .../unoptimized/test/index.test.ts | 4 +- .../no-op-export/test/index.test.js | 75 +- .../no-page-props/test/index.test.js | 23 +- .../node-fetch-keep-alive/test/index.test.js | 47 +- .../non-next-dist-exclude/test/index.test.js | 21 +- .../test/index.test.js | 95 +- .../not-found-revalidate/test/index.test.js | 29 +- .../nullish-config/test/index.test.js | 21 +- .../numeric-sep/test/index.test.js | 25 +- .../test/index.test.js | 21 +- .../page-config/test/index.test.js | 181 +-- .../page-extensions/test/index.test.js | 98 +- .../polyfilling-minimal/test/index.test.js | 25 +- test/integration/polyfills/test/index.test.js | 85 +- .../port-env-var/test/index.test.js | 29 +- .../preload-viewport/test/index.test.js | 837 +++++++------- .../prerender-export/test/index.test.js | 73 +- .../test/index.test.js | 27 +- .../test/index.test.js | 21 +- .../test/index.test.js | 25 +- .../test/index.test.js | 41 +- .../prerender-preview/test/index.test.js | 9 +- .../prerender-revalidate/test/index.test.js | 59 +- .../preview-fallback/test/index.test.js | 23 +- .../test/index.test.js | 19 +- .../production-build-dir/test/index.test.js | 35 +- .../production-config/test/index.test.js | 97 +- .../production-nav/test/index.test.js | 45 +- .../query-with-encoding/test/index.test.js | 463 ++++---- .../test/index.test.js | 49 +- .../react-profiling-mode/test/index.test.js | 101 +- .../test/index.test.js | 103 +- .../relay-analytics/test/index.test.js | 13 +- .../test/index.test.js | 2 +- .../test/index.test.js | 23 +- .../test/index.test.js | 49 +- .../with-get-initial-props/test/index.test.js | 49 +- .../test/index.test.js | 49 +- .../repeated-slashes/test/index.test.js | 4 +- .../test/index.test.js | 1015 +++++++++-------- .../revalidate-as-path/test/index.test.js | 33 +- .../test/index.test.js | 21 +- .../test/index.test.js | 21 +- .../test/index.test.js | 21 +- .../rewrites-has-condition/test/index.test.js | 21 +- .../test/index.test.js | 23 +- .../test/index.test.js | 21 +- .../route-index/test/index.test.js | 21 +- .../route-indexes/test/index.test.js | 23 +- .../route-load-cancel-css/test/index.test.js | 33 +- .../route-load-cancel/test/index.test.js | 31 +- .../router-hash-navigation/test/index.test.js | 21 +- .../test/index.test.js | 21 +- .../router-is-ready/test/index.test.js | 25 +- .../router-prefetch/test/index.test.js | 25 +- .../router-rerender/test/index.test.js | 23 +- .../script-loader/test/index.test.js | 37 +- .../test/index.test.js | 21 +- .../test/index.test.js | 23 +- .../server-asset-modules/test/index.test.js | 25 +- .../test/index.test.js | 25 +- .../src-dir-support/test/index.test.js | 21 +- .../ssg-data-404/test/index.test.js | 59 +- .../test/index.test.js | 29 +- .../integration/static-404/test/index.test.js | 2 +- .../static-page-name/test/index.test.js | 21 +- .../styled-jsx-plugin/test/index.test.js | 31 +- .../integration/telemetry/test/config.test.js | 968 ++++++++-------- test/integration/telemetry/test/index.test.js | 519 ++++----- .../telemetry/test/page-features.test.js | 2 +- .../test/index.test.js | 23 +- .../test/index.test.js | 49 +- .../trailing-slashes/test/index.test.js | 6 +- .../tsconfig-verifier/test/index.test.js | 2 +- .../turborepo-access-trace/test/index.test.js | 51 +- .../test/index.test.js | 131 ++- .../typeof-window-replace/test/index.test.js | 99 +- .../test/index.test.js | 19 +- .../test/index.test.js | 24 +- .../test/index.test.js | 111 +- .../test/index.test.js | 2 +- .../integration/typescript/test/index.test.js | 83 +- .../test/index.test.js | 2 +- .../with-electron/test/index.test.js | 105 +- .../with-router/test/index.test.js | 139 +-- .../worker-webpack5/test/index.test.js | 2 +- test/lib/next-test-utils.ts | 9 +- 286 files changed, 11740 insertions(+), 10622 deletions(-) diff --git a/test/e2e/app-dir/ppr-errors/ppr-errors.test.ts b/test/e2e/app-dir/ppr-errors/ppr-errors.test.ts index 26623ca69f5a2..1815056f31163 100644 --- a/test/e2e/app-dir/ppr-errors/ppr-errors.test.ts +++ b/test/e2e/app-dir/ppr-errors/ppr-errors.test.ts @@ -1,47 +1,50 @@ import { nextBuild } from 'next-test-utils' describe('ppr build errors', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - let stderr: string - let stdout: string + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + let stderr: string + let stdout: string - beforeAll(async () => { - const output = await nextBuild(__dirname, [], { - stderr: true, - stdout: true, + beforeAll(async () => { + const output = await nextBuild(__dirname, [], { + stderr: true, + stdout: true, + }) + stderr = output.stderr + stdout = output.stdout }) - stderr = output.stderr - stdout = output.stdout - }) - describe('within a suspense boundary', () => { - it('should fail the build for uncaught prerender errors', async () => { - expect(stderr).toContain( - 'Error occurred prerendering page "/regular-error-suspense-boundary".' - ) - expect(stderr).toContain( - 'Error occurred prerendering page "/re-throwing-error".' - ) + describe('within a suspense boundary', () => { + it('should fail the build for uncaught prerender errors', async () => { + expect(stderr).toContain( + 'Error occurred prerendering page "/regular-error-suspense-boundary".' + ) + expect(stderr).toContain( + 'Error occurred prerendering page "/re-throwing-error".' + ) + }) }) - }) - describe('outside of a suspense boundary', () => { - it('should fail the build for uncaught errors', async () => { - expect(stderr).toContain( - 'Error occurred prerendering page "/regular-error".' - ) - expect(stderr).toContain( - 'Error occurred prerendering page "/no-suspense-boundary-re-throwing-error".' - ) + describe('outside of a suspense boundary', () => { + it('should fail the build for uncaught errors', async () => { + expect(stderr).toContain( + 'Error occurred prerendering page "/regular-error".' + ) + expect(stderr).toContain( + 'Error occurred prerendering page "/no-suspense-boundary-re-throwing-error".' + ) + }) }) - }) - describe('when a postpone call is caught and logged it should', () => { - it('should include a message telling why', async () => { - expect(stdout).toContain( - 'User land logged error: Route /logging-error needs to bail out of prerendering at this point because it used cookies.' - ) + describe('when a postpone call is caught and logged it should', () => { + it('should include a message telling why', async () => { + expect(stdout).toContain( + 'User land logged error: Route /logging-error needs to bail out of prerendering at this point because it used cookies.' + ) + }) }) - }) - }) + } + ) }) diff --git a/test/integration/404-page-app/test/index.test.js b/test/integration/404-page-app/test/index.test.js index 8d0ffa458428d..7a86c52b53288 100644 --- a/test/integration/404-page-app/test/index.test.js +++ b/test/integration/404-page-app/test/index.test.js @@ -21,43 +21,46 @@ let appPort let app describe('404 Page Support with _app', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - afterAll(() => killApp(app)) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + afterAll(() => killApp(app)) - it('should build successfully', async () => { - const { code, stderr, stdout } = await nextBuild(appDir, [], { - stderr: true, - stdout: true, - }) + it('should build successfully', async () => { + const { code, stderr, stdout } = await nextBuild(appDir, [], { + stderr: true, + stdout: true, + }) - expect(code).toBe(0) - expect(stderr).not.toMatch(gip404Err) - expect(stdout).not.toMatch(gip404Err) + expect(code).toBe(0) + expect(stderr).not.toMatch(gip404Err) + expect(stdout).not.toMatch(gip404Err) - appPort = await findPort() - app = await nextStart(appDir, appPort) - }) + appPort = await findPort() + app = await nextStart(appDir, appPort) + }) - it('should not output static 404 if _app has getInitialProps', async () => { - const browser = await webdriver(appPort, '/404') - const isAutoExported = await browser.eval('__NEXT_DATA__.autoExport') - expect(isAutoExported).toBeFalsy() - }) + it('should not output static 404 if _app has getInitialProps', async () => { + const browser = await webdriver(appPort, '/404') + const isAutoExported = await browser.eval('__NEXT_DATA__.autoExport') + expect(isAutoExported).toBeFalsy() + }) - it('specify to use the 404 page still in the routes-manifest', async () => { - const manifest = await fs.readJSON( - join(appDir, '.next/routes-manifest.json') - ) - expect(manifest.pages404).toBe(true) - }) + it('specify to use the 404 page still in the routes-manifest', async () => { + const manifest = await fs.readJSON( + join(appDir, '.next/routes-manifest.json') + ) + expect(manifest.pages404).toBe(true) + }) - it('should still use 404 page', async () => { - const res = await fetchViaHTTP(appPort, '/abc') - expect(res.status).toBe(404) - const $ = cheerio.load(await res.text()) - expect($('#404-title').text()).toBe('Hi There') - }) - }) + it('should still use 404 page', async () => { + const res = await fetchViaHTTP(appPort, '/abc') + expect(res.status).toBe(404) + const $ = cheerio.load(await res.text()) + expect($('#404-title').text()).toBe('Hi There') + }) + } + ) describe('dev mode', () => { let stderr = '' diff --git a/test/integration/404-page-custom-error/test/index.test.js b/test/integration/404-page-custom-error/test/index.test.js index 63895d57c2783..5a2a280bb64cf 100644 --- a/test/integration/404-page-custom-error/test/index.test.js +++ b/test/integration/404-page-custom-error/test/index.test.js @@ -51,24 +51,27 @@ const runTests = (mode) => { } describe('Default 404 Page with custom _error', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - afterAll(() => killApp(app)) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + afterAll(() => killApp(app)) - it('should build successfully', async () => { - const { code } = await nextBuild(appDir, [], { - stderr: true, - stdout: true, - }) + it('should build successfully', async () => { + const { code } = await nextBuild(appDir, [], { + stderr: true, + stdout: true, + }) - expect(code).toBe(0) + expect(code).toBe(0) - appPort = await findPort() + appPort = await findPort() - app = await nextStart(appDir, appPort) - }) + app = await nextStart(appDir, appPort) + }) - runTests('server') - }) + runTests('server') + } + ) describe('dev mode', () => { beforeAll(async () => { diff --git a/test/integration/404-page-ssg/test/index.test.js b/test/integration/404-page-ssg/test/index.test.js index 712b4389aaf01..69f1b43b4b56a 100644 --- a/test/integration/404-page-ssg/test/index.test.js +++ b/test/integration/404-page-ssg/test/index.test.js @@ -76,40 +76,43 @@ const runTests = (isDev) => { } describe('404 Page Support SSG', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - afterAll(() => killApp(app)) - - it('should build successfully', async () => { - const { - code, - stderr: buildStderr, - stdout: buildStdout, - } = await nextBuild(appDir, [], { - stderr: true, - stdout: true, + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + afterAll(() => killApp(app)) + + it('should build successfully', async () => { + const { + code, + stderr: buildStderr, + stdout: buildStdout, + } = await nextBuild(appDir, [], { + stderr: true, + stdout: true, + }) + + expect(code).toBe(0) + expect(buildStderr).not.toMatch(gip404Err) + expect(buildStdout).not.toMatch(gip404Err) + + appPort = await findPort() + stderr = '' + stdout = '' + + app = await nextStart(appDir, appPort, { + onStdout(msg) { + stdout += msg + }, + onStderr(msg) { + stderr += msg + }, + }) + buildId = await fs.readFile(join(appDir, '.next/BUILD_ID'), 'utf8') }) - expect(code).toBe(0) - expect(buildStderr).not.toMatch(gip404Err) - expect(buildStdout).not.toMatch(gip404Err) - - appPort = await findPort() - stderr = '' - stdout = '' - - app = await nextStart(appDir, appPort, { - onStdout(msg) { - stdout += msg - }, - onStderr(msg) { - stderr += msg - }, - }) - buildId = await fs.readFile(join(appDir, '.next/BUILD_ID'), 'utf8') - }) - - runTests() - }) + runTests() + } + ) describe('dev mode', () => { beforeAll(async () => { diff --git a/test/integration/404-page/test/index.test.js b/test/integration/404-page/test/index.test.js index 3c4fa80e2e560..477de4450975e 100644 --- a/test/integration/404-page/test/index.test.js +++ b/test/integration/404-page/test/index.test.js @@ -180,135 +180,141 @@ describe('404 Page Support', () => { expect(stderr).toMatch(gip404Err) }) }) - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - beforeAll(async () => { - await nextBuild(appDir) - appPort = await findPort() - app = await nextStart(appDir, appPort) - }) - afterAll(() => killApp(app)) - - runTests('server') - }) - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - it('should not cache for custom 404 page with gssp and revalidate disabled', async () => { - await fs.move(pages404, `${pages404}.bak`) - await fs.writeFile( - pages404, - ` + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + beforeAll(async () => { + await nextBuild(appDir) + appPort = await findPort() + app = await nextStart(appDir, appPort) + }) + afterAll(() => killApp(app)) + + runTests('server') + } + ) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + it('should not cache for custom 404 page with gssp and revalidate disabled', async () => { + await fs.move(pages404, `${pages404}.bak`) + await fs.writeFile( + pages404, + ` const page = () => 'custom 404 page' export async function getStaticProps() { return { props: {} } } export default page ` - ) - await nextBuild(appDir) - appPort = await findPort() - app = await nextStart(appDir, appPort) - const cache404 = await getCacheHeader(appPort, '/404') - const cacheNext = await getCacheHeader(appPort, '/_next/abc') - await fs.remove(pages404) - await fs.move(`${pages404}.bak`, pages404) - await killApp(app) + ) + await nextBuild(appDir) + appPort = await findPort() + app = await nextStart(appDir, appPort) + const cache404 = await getCacheHeader(appPort, '/404') + const cacheNext = await getCacheHeader(appPort, '/_next/abc') + await fs.remove(pages404) + await fs.move(`${pages404}.bak`, pages404) + await killApp(app) - expect(cache404).toBe( - 'private, no-cache, no-store, max-age=0, must-revalidate' - ) - expect(cacheNext).toBe( - 'private, no-cache, no-store, max-age=0, must-revalidate' - ) - }) + expect(cache404).toBe( + 'private, no-cache, no-store, max-age=0, must-revalidate' + ) + expect(cacheNext).toBe( + 'private, no-cache, no-store, max-age=0, must-revalidate' + ) + }) - it('should not cache for custom 404 page with gssp and revalidate enabled', async () => { - await fs.move(pages404, `${pages404}.bak`) - await fs.writeFile( - pages404, - ` + it('should not cache for custom 404 page with gssp and revalidate enabled', async () => { + await fs.move(pages404, `${pages404}.bak`) + await fs.writeFile( + pages404, + ` const page = () => 'custom 404 page' export async function getStaticProps() { return { props: {}, revalidate: 1 } } export default page ` - ) - await nextBuild(appDir) - appPort = await findPort() - app = await nextStart(appDir, appPort) - const cache404 = await getCacheHeader(appPort, '/404') - const cacheNext = await getCacheHeader(appPort, '/_next/abc') - await fs.remove(pages404) - await fs.move(`${pages404}.bak`, pages404) - await killApp(app) + ) + await nextBuild(appDir) + appPort = await findPort() + app = await nextStart(appDir, appPort) + const cache404 = await getCacheHeader(appPort, '/404') + const cacheNext = await getCacheHeader(appPort, '/_next/abc') + await fs.remove(pages404) + await fs.move(`${pages404}.bak`, pages404) + await killApp(app) - expect(cache404).toBe( - 'private, no-cache, no-store, max-age=0, must-revalidate' - ) - expect(cacheNext).toBe( - 'private, no-cache, no-store, max-age=0, must-revalidate' - ) - }) + expect(cache404).toBe( + 'private, no-cache, no-store, max-age=0, must-revalidate' + ) + expect(cacheNext).toBe( + 'private, no-cache, no-store, max-age=0, must-revalidate' + ) + }) - it('should not cache for custom 404 page without gssp', async () => { - await nextBuild(appDir) - appPort = await findPort() - app = await nextStart(appDir, appPort) - const cache404 = await getCacheHeader(appPort, '/404') - const cacheNext = await getCacheHeader(appPort, '/_next/abc') - await killApp(app) + it('should not cache for custom 404 page without gssp', async () => { + await nextBuild(appDir) + appPort = await findPort() + app = await nextStart(appDir, appPort) + const cache404 = await getCacheHeader(appPort, '/404') + const cacheNext = await getCacheHeader(appPort, '/_next/abc') + await killApp(app) - expect(cache404).toBe(null) - expect(cacheNext).toBe('no-cache, no-store, max-age=0, must-revalidate') - }) + expect(cache404).toBe(null) + expect(cacheNext).toBe('no-cache, no-store, max-age=0, must-revalidate') + }) - it('shows error with getInitialProps in pages/404 build', async () => { - await fs.move(pages404, `${pages404}.bak`) - await fs.writeFile( - pages404, - ` + it('shows error with getInitialProps in pages/404 build', async () => { + await fs.move(pages404, `${pages404}.bak`) + await fs.writeFile( + pages404, + ` const page = () => 'custom 404 page' page.getInitialProps = () => ({ a: 'b' }) export default page ` - ) - const { stderr, code } = await nextBuild(appDir, [], { stderr: true }) - await fs.remove(pages404) - await fs.move(`${pages404}.bak`, pages404) + ) + const { stderr, code } = await nextBuild(appDir, [], { stderr: true }) + await fs.remove(pages404) + await fs.move(`${pages404}.bak`, pages404) - expect(stderr).toMatch(gip404Err) - expect(code).toBe(1) - }) + expect(stderr).toMatch(gip404Err) + expect(code).toBe(1) + }) - it('does not show error with getStaticProps in pages/404 build', async () => { - await fs.move(pages404, `${pages404}.bak`) - await fs.writeFile( - pages404, - ` + it('does not show error with getStaticProps in pages/404 build', async () => { + await fs.move(pages404, `${pages404}.bak`) + await fs.writeFile( + pages404, + ` const page = () => 'custom 404 page' export const getStaticProps = () => ({ props: { a: 'b' } }) export default page ` - ) - const { stderr, code } = await nextBuild(appDir, [], { stderr: true }) - await fs.remove(pages404) - await fs.move(`${pages404}.bak`, pages404) + ) + const { stderr, code } = await nextBuild(appDir, [], { stderr: true }) + await fs.remove(pages404) + await fs.move(`${pages404}.bak`, pages404) - expect(stderr).not.toMatch(gip404Err) - expect(code).toBe(0) - }) + expect(stderr).not.toMatch(gip404Err) + expect(code).toBe(0) + }) - it('shows error with getServerSideProps in pages/404 build', async () => { - await fs.move(pages404, `${pages404}.bak`) - await fs.writeFile( - pages404, - ` + it('shows error with getServerSideProps in pages/404 build', async () => { + await fs.move(pages404, `${pages404}.bak`) + await fs.writeFile( + pages404, + ` const page = () => 'custom 404 page' export const getServerSideProps = () => ({ props: { a: 'b' } }) export default page ` - ) - const { stderr, code } = await nextBuild(appDir, [], { stderr: true }) - await fs.remove(pages404) - await fs.move(`${pages404}.bak`, pages404) + ) + const { stderr, code } = await nextBuild(appDir, [], { stderr: true }) + await fs.remove(pages404) + await fs.move(`${pages404}.bak`, pages404) - expect(stderr).toMatch(gip404Err) - expect(code).toBe(1) - }) - }) + expect(stderr).toMatch(gip404Err) + expect(code).toBe(1) + }) + } + ) }) diff --git a/test/integration/500-page/test/gsp-gssp.test.js b/test/integration/500-page/test/gsp-gssp.test.js index ac89b66c051d3..10ac6a3ffcd84 100644 --- a/test/integration/500-page/test/gsp-gssp.test.js +++ b/test/integration/500-page/test/gsp-gssp.test.js @@ -23,163 +23,166 @@ let appPort let app describe('gsp-gssp', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - it('does not show error with getStaticProps in pages/500 build', async () => { - await fs.move(pages500, `${pages500}.bak`) - await fs.writeFile( - pages500, - ` + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + it('does not show error with getStaticProps in pages/500 build', async () => { + await fs.move(pages500, `${pages500}.bak`) + await fs.writeFile( + pages500, + ` const page = () => 'custom 500 page' export const getStaticProps = () => ({ props: { a: 'b' } }) export default page ` - ) - await fs.remove(join(appDir, '.next')) - const { stderr, code } = await nextBuild(appDir, [], { stderr: true }) - await fs.remove(pages500) - await fs.move(`${pages500}.bak`, pages500) - - expect(stderr).not.toMatch(gip500Err) - expect(code).toBe(0) - }) - it('shows error with getServerSideProps in pages/500 build', async () => { - await fs.move(pages500, `${pages500}.bak`) - await fs.writeFile( - pages500, - ` + ) + await fs.remove(join(appDir, '.next')) + const { stderr, code } = await nextBuild(appDir, [], { stderr: true }) + await fs.remove(pages500) + await fs.move(`${pages500}.bak`, pages500) + + expect(stderr).not.toMatch(gip500Err) + expect(code).toBe(0) + }) + it('shows error with getServerSideProps in pages/500 build', async () => { + await fs.move(pages500, `${pages500}.bak`) + await fs.writeFile( + pages500, + ` const page = () => 'custom 500 page' export const getServerSideProps = () => ({ props: { a: 'b' } }) export default page ` - ) - await fs.remove(join(appDir, '.next')) - const { stderr, code } = await nextBuild(appDir, [], { stderr: true }) - await fs.remove(pages500) - await fs.move(`${pages500}.bak`, pages500) - - expect(stderr).toMatch(gip500Err) - expect(code).toBe(1) - }) + ) + await fs.remove(join(appDir, '.next')) + const { stderr, code } = await nextBuild(appDir, [], { stderr: true }) + await fs.remove(pages500) + await fs.move(`${pages500}.bak`, pages500) + + expect(stderr).toMatch(gip500Err) + expect(code).toBe(1) + }) - it('does build 500 statically with getInitialProps in _app and getStaticProps in pages/500', async () => { - await fs.writeFile( - pagesApp, - ` + it('does build 500 statically with getInitialProps in _app and getStaticProps in pages/500', async () => { + await fs.writeFile( + pagesApp, + ` import App from 'next/app' - + const page = ({ Component, pageProps }) => page.getInitialProps = (ctx) => App.getInitialProps(ctx) export default page ` - ) - await fs.rename(pages500, `${pages500}.bak`) - await fs.writeFile( - pages500, - ` + ) + await fs.rename(pages500, `${pages500}.bak`) + await fs.writeFile( + pages500, + ` const page = () => { console.log('rendered 500') return 'custom 500 page' } export default page - + export const getStaticProps = () => { return { props: {} } } ` - ) - await fs.remove(join(appDir, '.next')) - const { - stderr, - stdout: buildStdout, - code, - } = await nextBuild(appDir, [], { - stderr: true, - stdout: true, + ) + await fs.remove(join(appDir, '.next')) + const { + stderr, + stdout: buildStdout, + code, + } = await nextBuild(appDir, [], { + stderr: true, + stdout: true, + }) + + await fs.remove(pagesApp) + await fs.remove(pages500) + await fs.rename(`${pages500}.bak`, pages500) + + expect(stderr).not.toMatch(gip500Err) + expect(buildStdout).toContain('rendered 500') + expect(code).toBe(0) + expect( + await fs.pathExists(join(appDir, '.next/server/pages/500.html')) + ).toBe(true) + + let appStdout = '' + const appPort = await findPort() + const app = await nextStart(appDir, appPort, { + onStdout(msg) { + appStdout += msg || '' + }, + onStderr(msg) { + appStdout += msg || '' + }, + }) + + await renderViaHTTP(appPort, '/err') + await killApp(app) + + expect(appStdout).not.toContain('rendered 500') }) - await fs.remove(pagesApp) - await fs.remove(pages500) - await fs.rename(`${pages500}.bak`, pages500) - - expect(stderr).not.toMatch(gip500Err) - expect(buildStdout).toContain('rendered 500') - expect(code).toBe(0) - expect( - await fs.pathExists(join(appDir, '.next/server/pages/500.html')) - ).toBe(true) - - let appStdout = '' - const appPort = await findPort() - const app = await nextStart(appDir, appPort, { - onStdout(msg) { - appStdout += msg || '' - }, - onStderr(msg) { - appStdout += msg || '' - }, - }) - - await renderViaHTTP(appPort, '/err') - await killApp(app) - - expect(appStdout).not.toContain('rendered 500') - }) - - it('does not build 500 statically with no pages/500 and getServerSideProps in _error', async () => { - await fs.rename(pages500, `${pages500}.bak`) - await fs.writeFile( - pagesError, - ` + it('does not build 500 statically with no pages/500 and getServerSideProps in _error', async () => { + await fs.rename(pages500, `${pages500}.bak`) + await fs.writeFile( + pagesError, + ` function Error({ statusCode }) { return

Error status: {statusCode}

} - + export const getServerSideProps = ({ req, res, err }) => { console.error('called _error getServerSideProps') - + if (req.url === '/500') { throw new Error('should not export /500') } - + return { props: { statusCode: res && res.statusCode ? res.statusCode : err ? err.statusCode : 404 } } } - + export default Error ` - ) - await fs.remove(join(appDir, '.next')) - const { stderr: buildStderr, code } = await nextBuild(appDir, [], { - stderr: true, - }) - await fs.rename(`${pages500}.bak`, pages500) - await fs.remove(pagesError) - console.log(buildStderr) - expect(buildStderr).not.toMatch(gip500Err) - expect(code).toBe(0) - expect( - await fs.pathExists(join(appDir, '.next/server/pages/500.html')) - ).toBe(false) - - let appStderr = '' - const appPort = await findPort() - const app = await nextStart(appDir, appPort, { - onStderr(msg) { - appStderr += msg || '' - }, + ) + await fs.remove(join(appDir, '.next')) + const { stderr: buildStderr, code } = await nextBuild(appDir, [], { + stderr: true, + }) + await fs.rename(`${pages500}.bak`, pages500) + await fs.remove(pagesError) + console.log(buildStderr) + expect(buildStderr).not.toMatch(gip500Err) + expect(code).toBe(0) + expect( + await fs.pathExists(join(appDir, '.next/server/pages/500.html')) + ).toBe(false) + + let appStderr = '' + const appPort = await findPort() + const app = await nextStart(appDir, appPort, { + onStderr(msg) { + appStderr += msg || '' + }, + }) + + await renderViaHTTP(appPort, '/err') + await killApp(app) + + expect(appStderr).toContain('called _error getServerSideProps') }) - - await renderViaHTTP(appPort, '/err') - await killApp(app) - - expect(appStderr).toContain('called _error getServerSideProps') - }) - }) + } + ) describe('development mode', () => { it('does not show error with getStaticProps in pages/500 dev', async () => { diff --git a/test/integration/500-page/test/index.test.js b/test/integration/500-page/test/index.test.js index 8c8e3aa53f4d3..7d2d125ace186 100644 --- a/test/integration/500-page/test/index.test.js +++ b/test/integration/500-page/test/index.test.js @@ -100,18 +100,21 @@ describe('500 Page Support', () => { expect(stderr).toMatch(gip500Err) }) }) - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - beforeAll(async () => { - await fs.remove(join(appDir, '.next')) - await nextBuild(appDir) - appPort = await findPort() - app = await nextStart(appDir, appPort) - }) - afterAll(() => killApp(app)) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + beforeAll(async () => { + await fs.remove(join(appDir, '.next')) + await nextBuild(appDir) + appPort = await findPort() + app = await nextStart(appDir, appPort) + }) + afterAll(() => killApp(app)) - runTests('server') - }) - ;(process.env.TURBOPACK ? describe.skip : describe)( + runTests('server') + } + ) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( 'production mode 2', () => { it('does not build 500 statically with getInitialProps in _app', async () => { @@ -119,7 +122,7 @@ describe('500 Page Support', () => { pagesApp, ` import App from 'next/app' - + const page = ({ Component, pageProps }) => page.getInitialProps = (ctx) => App.getInitialProps(ctx) export default page @@ -233,19 +236,19 @@ describe('500 Page Support', () => { function Error({ statusCode }) { return

Error status: {statusCode}

} - + Error.getInitialProps = ({ req, res, err }) => { console.error('called _error.getInitialProps') - + if (req.url === '/500') { throw new Error('should not export /500') } - + return { statusCode: res && res.statusCode ? res.statusCode : err ? err.statusCode : 404 } } - + export default Error ` ) @@ -284,19 +287,19 @@ describe('500 Page Support', () => { function Error({ statusCode }) { return

Error status: {statusCode}

} - + Error.getInitialProps = ({ req, res, err }) => { console.error('called _error.getInitialProps') - + if (req.url === '/500') { throw new Error('should not export /500') } - + return { statusCode: res && res.statusCode ? res.statusCode : err ? err.statusCode : 404 } } - + export default Error ` ) @@ -306,18 +309,18 @@ describe('500 Page Support', () => { function App({ pageProps, Component }) { return } - + App.getInitialProps = async ({ Component, ctx }) => { // throw _app GIP err here let pageProps = {} - + if (Component.getInitialProps) { pageProps = await Component.getInitialProps(ctx) } - + return { pageProps } } - + export default App ` ) diff --git a/test/integration/absolute-assetprefix/test/index.test.js b/test/integration/absolute-assetprefix/test/index.test.js index d6b1ff4ad39fb..9a376455034cd 100644 --- a/test/integration/absolute-assetprefix/test/index.test.js +++ b/test/integration/absolute-assetprefix/test/index.test.js @@ -19,105 +19,108 @@ let cdnAccessLog = [] const nextConfig = new File(path.resolve(__dirname, '../next.config.js')) describe('absolute assetPrefix with path prefix', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - beforeAll(async () => { - cdnPort = await findPort() - // lightweight http proxy - cdn = http.createServer((clientReq, clientRes) => { - const proxyPath = clientReq.url.slice('/path-prefix'.length) - cdnAccessLog.push(proxyPath) - const proxyReq = http.request( - { - hostname: 'localhost', - port: appPort, - path: proxyPath, - method: clientReq.method, - headers: clientReq.headers, - }, - (proxyRes) => { - // cdn must be configured to allow requests from this origin - proxyRes.headers[ - 'Access-Control-Allow-Origin' - ] = `http://localhost:${appPort}` - clientRes.writeHead(proxyRes.statusCode, proxyRes.headers) - proxyRes.pipe(clientRes, { end: true }) - } + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + beforeAll(async () => { + cdnPort = await findPort() + // lightweight http proxy + cdn = http.createServer((clientReq, clientRes) => { + const proxyPath = clientReq.url.slice('/path-prefix'.length) + cdnAccessLog.push(proxyPath) + const proxyReq = http.request( + { + hostname: 'localhost', + port: appPort, + path: proxyPath, + method: clientReq.method, + headers: clientReq.headers, + }, + (proxyRes) => { + // cdn must be configured to allow requests from this origin + proxyRes.headers[ + 'Access-Control-Allow-Origin' + ] = `http://localhost:${appPort}` + clientRes.writeHead(proxyRes.statusCode, proxyRes.headers) + proxyRes.pipe(clientRes, { end: true }) + } + ) + + clientReq.pipe(proxyReq, { end: true }) + }) + await new Promise((resolve) => cdn.listen(cdnPort, resolve)) + nextConfig.replace('__CDN_PORT__', cdnPort) + await nextBuild(appDir) + buildId = await fs.readFile( + path.resolve(__dirname, '../.next/BUILD_ID'), + 'utf8' ) + appPort = await findPort() + app = await nextStart(appDir, appPort) + }) - clientReq.pipe(proxyReq, { end: true }) + afterEach(() => { + cdnAccessLog = [] }) - await new Promise((resolve) => cdn.listen(cdnPort, resolve)) - nextConfig.replace('__CDN_PORT__', cdnPort) - await nextBuild(appDir) - buildId = await fs.readFile( - path.resolve(__dirname, '../.next/BUILD_ID'), - 'utf8' - ) - appPort = await findPort() - app = await nextStart(appDir, appPort) - }) - afterEach(() => { - cdnAccessLog = [] - }) + afterAll(() => killApp(app)) + afterAll(() => cdn.close()) + afterAll(() => nextConfig.restore()) - afterAll(() => killApp(app)) - afterAll(() => cdn.close()) - afterAll(() => nextConfig.restore()) + it('should not fetch static data from a CDN', async () => { + const browser = await webdriver(appPort, '/') + await browser.waitForElementByCss('#about-link').click() + const prop = await browser.waitForElementByCss('#prop').text() + expect(prop).toBe('hello') + expect(cdnAccessLog).not.toContain(`/_next/data/${buildId}/about.json`) + }) - it('should not fetch static data from a CDN', async () => { - const browser = await webdriver(appPort, '/') - await browser.waitForElementByCss('#about-link').click() - const prop = await browser.waitForElementByCss('#prop').text() - expect(prop).toBe('hello') - expect(cdnAccessLog).not.toContain(`/_next/data/${buildId}/about.json`) - }) + it('should fetch from cache correctly', async () => { + const browser = await webdriver(appPort, '/') + await browser.eval('window.clientSideNavigated = true') + await browser.waitForElementByCss('#about-link').click() + await browser.waitForElementByCss('#prop') + await browser.back() + await browser.waitForElementByCss('#about-link').click() + const prop = await browser.waitForElementByCss('#prop').text() + expect(prop).toBe('hello') + expect(await browser.eval('window.clientSideNavigated')).toBe(true) + expect( + cdnAccessLog.filter( + (path) => path === `/_next/data/${buildId}/about.json` + ) + ).toHaveLength(0) + }) - it('should fetch from cache correctly', async () => { - const browser = await webdriver(appPort, '/') - await browser.eval('window.clientSideNavigated = true') - await browser.waitForElementByCss('#about-link').click() - await browser.waitForElementByCss('#prop') - await browser.back() - await browser.waitForElementByCss('#about-link').click() - const prop = await browser.waitForElementByCss('#prop').text() - expect(prop).toBe('hello') - expect(await browser.eval('window.clientSideNavigated')).toBe(true) - expect( - cdnAccessLog.filter( - (path) => path === `/_next/data/${buildId}/about.json` + it('should work with getStaticPaths prerendered', async () => { + const browser = await webdriver(appPort, '/') + await browser.waitForElementByCss('#gsp-prerender-link').click() + const prop = await browser.waitForElementByCss('#prop').text() + expect(prop).toBe('prerendered') + expect(cdnAccessLog).not.toContain( + `/_next/data/${buildId}/gsp-fallback/prerendered.json` ) - ).toHaveLength(0) - }) - - it('should work with getStaticPaths prerendered', async () => { - const browser = await webdriver(appPort, '/') - await browser.waitForElementByCss('#gsp-prerender-link').click() - const prop = await browser.waitForElementByCss('#prop').text() - expect(prop).toBe('prerendered') - expect(cdnAccessLog).not.toContain( - `/_next/data/${buildId}/gsp-fallback/prerendered.json` - ) - }) + }) - it('should work with getStaticPaths fallback', async () => { - const browser = await webdriver(appPort, '/') - await browser.waitForElementByCss('#gsp-fallback-link').click() - const prop = await browser.waitForElementByCss('#prop').text() - expect(prop).toBe('fallback') - expect(cdnAccessLog).not.toContain( - `/_next/data/${buildId}/gsp-fallback/fallback.json` - ) - }) + it('should work with getStaticPaths fallback', async () => { + const browser = await webdriver(appPort, '/') + await browser.waitForElementByCss('#gsp-fallback-link').click() + const prop = await browser.waitForElementByCss('#prop').text() + expect(prop).toBe('fallback') + expect(cdnAccessLog).not.toContain( + `/_next/data/${buildId}/gsp-fallback/fallback.json` + ) + }) - it('should work with getServerSideProps', async () => { - const browser = await webdriver(appPort, '/') - await browser.waitForElementByCss('#gssp-link').click() - const prop = await browser.waitForElementByCss('#prop').text() - expect(prop).toBe('foo') - expect(cdnAccessLog).not.toContain( - `/_next/data/${buildId}/gssp.json?prop=foo` - ) - }) - }) + it('should work with getServerSideProps', async () => { + const browser = await webdriver(appPort, '/') + await browser.waitForElementByCss('#gssp-link').click() + const prop = await browser.waitForElementByCss('#prop').text() + expect(prop).toBe('foo') + expect(cdnAccessLog).not.toContain( + `/_next/data/${buildId}/gssp.json?prop=foo` + ) + }) + } + ) }) diff --git a/test/integration/amp-export-validation/test/index.test.js b/test/integration/amp-export-validation/test/index.test.js index 531af66da1ab6..4f2864854616c 100644 --- a/test/integration/amp-export-validation/test/index.test.js +++ b/test/integration/amp-export-validation/test/index.test.js @@ -13,106 +13,113 @@ const nextConfig = new File(join(appDir, 'next.config.js')) let buildOutput describe('AMP Validation on Export', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - beforeAll(async () => { - const { stdout = '', stderr = '' } = await nextBuild(appDir, [], { - stdout: true, - stderr: true, + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + beforeAll(async () => { + const { stdout = '', stderr = '' } = await nextBuild(appDir, [], { + stdout: true, + stderr: true, + }) + buildOutput = stdout + stderr }) - buildOutput = stdout + stderr - }) - it('should have shown errors during build', async () => { - expect(buildOutput).toMatch( - /error.*The mandatory attribute 'height' is missing in tag 'amp-video'\./ - ) - expect(existsSync(outDir)).toBeFalse() - }) + it('should have shown errors during build', async () => { + expect(buildOutput).toMatch( + /error.*The mandatory attribute 'height' is missing in tag 'amp-video'\./ + ) + expect(existsSync(outDir)).toBeFalse() + }) - // this is now an error instead of a warning - it.skip('shows AMP warning without throwing error', async () => { - nextConfig.replace( - '// exportPathMap', - `exportPathMap: function(defaultMap) { + // this is now an error instead of a warning + it.skip('shows AMP warning without throwing error', async () => { + nextConfig.replace( + '// exportPathMap', + `exportPathMap: function(defaultMap) { return { '/cat': { page: '/cat' }, } },` - ) - - try { - const { stdout, stderr } = await runNextCommand(['export', appDir], { - stdout: true, - stderr: true, - }) - expect(stdout).toMatch( - /error.*The mandatory attribute 'height' is missing in tag 'amp-video'\./ - ) - await expect(access(join(outDir, 'cat.html'))).resolves.toBe(undefined) - await expect(stderr).not.toMatch( - /Found conflicting amp tag "meta" with conflicting prop name="viewport"/ ) - } finally { - nextConfig.restore() - } - }) - // img instead of amp-img no longer shows a warning - it.skip('throws error on AMP error', async () => { - nextConfig.replace( - '// exportPathMap', - `exportPathMap: function(defaultMap) { + try { + const { stdout, stderr } = await runNextCommand(['export', appDir], { + stdout: true, + stderr: true, + }) + expect(stdout).toMatch( + /error.*The mandatory attribute 'height' is missing in tag 'amp-video'\./ + ) + await expect(access(join(outDir, 'cat.html'))).resolves.toBe( + undefined + ) + await expect(stderr).not.toMatch( + /Found conflicting amp tag "meta" with conflicting prop name="viewport"/ + ) + } finally { + nextConfig.restore() + } + }) + + // img instead of amp-img no longer shows a warning + it.skip('throws error on AMP error', async () => { + nextConfig.replace( + '// exportPathMap', + `exportPathMap: function(defaultMap) { return { '/dog': { page: '/dog' }, } },` - ) - - try { - const { stdout, stderr } = await runNextCommand(['export', appDir], { - stdout: true, - stderr: true, - }) - expect(stdout).toMatch( - /error.*The parent tag of tag 'img' is 'div', but it can only be 'i-amphtml-sizer-intrinsic'\./ - ) - await expect(access(join(outDir, 'dog.html'))).resolves.toBe(undefined) - await expect(stderr).not.toMatch( - /Found conflicting amp tag "meta" with conflicting prop name="viewport"/ ) - } finally { - nextConfig.restore() - } - }) - // img instead of amp-img no longer shows a warning - it.skip('shows warning and error when throwing error', async () => { - nextConfig.replace( - '// exportPathMap', - `exportPathMap: function(defaultMap) { + try { + const { stdout, stderr } = await runNextCommand(['export', appDir], { + stdout: true, + stderr: true, + }) + expect(stdout).toMatch( + /error.*The parent tag of tag 'img' is 'div', but it can only be 'i-amphtml-sizer-intrinsic'\./ + ) + await expect(access(join(outDir, 'dog.html'))).resolves.toBe( + undefined + ) + await expect(stderr).not.toMatch( + /Found conflicting amp tag "meta" with conflicting prop name="viewport"/ + ) + } finally { + nextConfig.restore() + } + }) + + // img instead of amp-img no longer shows a warning + it.skip('shows warning and error when throwing error', async () => { + nextConfig.replace( + '// exportPathMap', + `exportPathMap: function(defaultMap) { return { '/dog-cat': { page: '/dog-cat' }, } },` - ) - - try { - const { stdout, stderr } = await runNextCommand(['export', appDir], { - stdout: true, - stderr: true, - }) - expect(stdout).toMatch( - /error.*The parent tag of tag 'img' is 'div', but it can only be 'i-amphtml-sizer-intrinsic'\./ - ) - await expect(access(join(outDir, 'dog-cat.html'))).resolves.toBe( - undefined ) - await expect(stderr).not.toMatch( - /Found conflicting amp tag "meta" with conflicting prop name="viewport"/ - ) - } finally { - nextConfig.restore() - } - }) - }) + + try { + const { stdout, stderr } = await runNextCommand(['export', appDir], { + stdout: true, + stderr: true, + }) + expect(stdout).toMatch( + /error.*The parent tag of tag 'img' is 'div', but it can only be 'i-amphtml-sizer-intrinsic'\./ + ) + await expect(access(join(outDir, 'dog-cat.html'))).resolves.toBe( + undefined + ) + await expect(stderr).not.toMatch( + /Found conflicting amp tag "meta" with conflicting prop name="viewport"/ + ) + } finally { + nextConfig.restore() + } + }) + } + ) }) diff --git a/test/integration/amphtml-custom-optimizer/test/index.test.js b/test/integration/amphtml-custom-optimizer/test/index.test.js index 3c2126676a5fd..e8becde45df95 100644 --- a/test/integration/amphtml-custom-optimizer/test/index.test.js +++ b/test/integration/amphtml-custom-optimizer/test/index.test.js @@ -14,43 +14,46 @@ let appPort const appDir = join(__dirname, '../') describe('AMP Custom Optimizer', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - it('should build and start for static page', async () => { - const { code } = await nextBuild(appDir) - expect(code).toBe(0) - - appPort = await findPort() - app = await nextStart(appDir, appPort) - - const html = await renderViaHTTP(appPort, '/') - await killApp(app) - - expect(html).toContain( - 'amp-twitter width="500" height="500" layout="responsive" data-tweetid="1159145442896166912"' - ) - expect(html).toContain('i-amphtml-version="001515617716922"') - expect(html).toContain( - 'script async src="https://cdn.ampproject.org/rtv/001515617716922/v0.mjs"' - ) - }) - - it('should build and start for dynamic page', async () => { - const { code } = await nextBuild(appDir) - expect(code).toBe(0) - - appPort = await findPort() - app = await nextStart(appDir, appPort) - - const html = await renderViaHTTP(appPort, '/dynamic') - await killApp(app) - - expect(html).toContain( - 'amp-img width="500" height="500" layout="responsive" src="https://amp.dev/static/samples/img/story_dog2_portrait.jpg"' - ) - expect(html).toContain('i-amphtml-version="001515617716922"') - expect(html).toContain( - 'script async src="https://cdn.ampproject.org/rtv/001515617716922/v0.mjs"' - ) - }) - }) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + it('should build and start for static page', async () => { + const { code } = await nextBuild(appDir) + expect(code).toBe(0) + + appPort = await findPort() + app = await nextStart(appDir, appPort) + + const html = await renderViaHTTP(appPort, '/') + await killApp(app) + + expect(html).toContain( + 'amp-twitter width="500" height="500" layout="responsive" data-tweetid="1159145442896166912"' + ) + expect(html).toContain('i-amphtml-version="001515617716922"') + expect(html).toContain( + 'script async src="https://cdn.ampproject.org/rtv/001515617716922/v0.mjs"' + ) + }) + + it('should build and start for dynamic page', async () => { + const { code } = await nextBuild(appDir) + expect(code).toBe(0) + + appPort = await findPort() + app = await nextStart(appDir, appPort) + + const html = await renderViaHTTP(appPort, '/dynamic') + await killApp(app) + + expect(html).toContain( + 'amp-img width="500" height="500" layout="responsive" src="https://amp.dev/static/samples/img/story_dog2_portrait.jpg"' + ) + expect(html).toContain('i-amphtml-version="001515617716922"') + expect(html).toContain( + 'script async src="https://cdn.ampproject.org/rtv/001515617716922/v0.mjs"' + ) + }) + } + ) }) diff --git a/test/integration/amphtml-custom-validator/test/index.test.js b/test/integration/amphtml-custom-validator/test/index.test.js index 80e5e3b41591b..d368d2721a9e6 100644 --- a/test/integration/amphtml-custom-validator/test/index.test.js +++ b/test/integration/amphtml-custom-validator/test/index.test.js @@ -18,7 +18,7 @@ const appDir = join(__dirname, '../') ;(process.env.TURBOPACK ? describe.skip : describe)( 'AMP Custom Validator', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)( + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( 'production mode', () => { it('should build and start successfully', async () => { diff --git a/test/integration/amphtml-fragment-style/test/index.test.js b/test/integration/amphtml-fragment-style/test/index.test.js index 817ac7655abbc..6807359766a48 100644 --- a/test/integration/amphtml-fragment-style/test/index.test.js +++ b/test/integration/amphtml-fragment-style/test/index.test.js @@ -16,21 +16,24 @@ let appPort let app describe('AMP Fragment Styles', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - beforeAll(async () => { - await nextBuild(appDir, []) - appPort = await findPort() - app = await nextStart(appDir, appPort) - }) - afterAll(() => killApp(app)) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + beforeAll(async () => { + await nextBuild(appDir, []) + appPort = await findPort() + app = await nextStart(appDir, appPort) + }) + afterAll(() => killApp(app)) - it('adds styles from fragment in AMP mode correctly', async () => { - const html = await renderViaHTTP(appPort, '/', { amp: 1 }) - await validateAMP(html) - const $ = cheerio.load(html) - const styles = $('style[amp-custom]').text() - expect(styles).toMatch(/background:(.*|)hotpink/) - expect(styles).toMatch(/font-size:(.*|)16\.4px/) - }) - }) + it('adds styles from fragment in AMP mode correctly', async () => { + const html = await renderViaHTTP(appPort, '/', { amp: 1 }) + await validateAMP(html) + const $ = cheerio.load(html) + const styles = $('style[amp-custom]').text() + expect(styles).toMatch(/background:(.*|)hotpink/) + expect(styles).toMatch(/font-size:(.*|)16\.4px/) + }) + } + ) }) diff --git a/test/integration/amphtml-ssg/test/index.test.js b/test/integration/amphtml-ssg/test/index.test.js index 1b11eb772be5c..a173e98ad09f2 100644 --- a/test/integration/amphtml-ssg/test/index.test.js +++ b/test/integration/amphtml-ssg/test/index.test.js @@ -99,17 +99,20 @@ const runTests = (isDev = false) => { } describe('AMP SSG Support', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - beforeAll(async () => { - await nextBuild(appDir) - appPort = await findPort() - app = await nextStart(appDir, appPort) - // TODO: use browser instead to do checks that now need filesystem access - builtServerPagesDir = join(appDir, '.next', 'server', 'pages') - }) - afterAll(() => killApp(app)) - runTests() - }) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + beforeAll(async () => { + await nextBuild(appDir) + appPort = await findPort() + app = await nextStart(appDir, appPort) + // TODO: use browser instead to do checks that now need filesystem access + builtServerPagesDir = join(appDir, '.next', 'server', 'pages') + }) + afterAll(() => killApp(app)) + runTests() + } + ) describe('dev mode', () => { beforeAll(async () => { appPort = await findPort() @@ -119,7 +122,7 @@ describe('AMP SSG Support', () => { runTests(true) }) describe('export mode', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)( + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( 'production mode', () => { let buildId diff --git a/test/integration/amphtml/test/index.test.js b/test/integration/amphtml/test/index.test.js index b8aacc95345cb..0367383a766f2 100644 --- a/test/integration/amphtml/test/index.test.js +++ b/test/integration/amphtml/test/index.test.js @@ -25,225 +25,228 @@ let app const context = {} describe('AMP Usage', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - let output = '' - - beforeAll(async () => { - await rename( - join(appDir, 'pages/invalid-amp.js'), - join(appDir, 'pages/invalid-amp.js.bak') - ) - const result = await nextBuild(appDir, undefined, { - stdout: true, - stderr: true, - }) - - output = stripAnsi(result.stdout + result.stderr) - - appPort = context.appPort = await findPort() - app = await nextStart(appDir, context.appPort) - }) - afterAll(async () => { - await rename( - join(appDir, 'pages/invalid-amp.js.bak'), - join(appDir, 'pages/invalid-amp.js') - ) - return killApp(app) - }) - - it('should have amp optimizer in trace', async () => { - const trace = JSON.parse( - readFileSync(join(appDir, '.next/next-server.js.nft.json'), 'utf8') - ) - expect( - trace.files.some((file) => - file.replace(/\\/g, '/').includes('@ampproject/toolbox-optimizer') + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + let output = '' + + beforeAll(async () => { + await rename( + join(appDir, 'pages/invalid-amp.js'), + join(appDir, 'pages/invalid-amp.js.bak') ) - ).toBe(true) - }) + const result = await nextBuild(appDir, undefined, { + stdout: true, + stderr: true, + }) - it('should not contain missing files warning', async () => { - expect(output).toContain('Compiled successfully') - expect(output).not.toContain('Could not find files for') - }) + output = stripAnsi(result.stdout + result.stderr) - describe('With basic usage', () => { - it('should render the page', async () => { - const html = await renderViaHTTP(appPort, '/') - expect(html).toMatch(/Hello World/) + appPort = context.appPort = await findPort() + app = await nextStart(appDir, context.appPort) }) - }) - - describe('With basic AMP usage', () => { - it('should render the page as valid AMP', async () => { - const html = await renderViaHTTP(appPort, '/?amp=1') - await validateAMP(html) - expect(html).toMatch(/Hello World/) - - const $ = cheerio.load(html) - expect($('.abc')).toHaveLength(1) - }) - - it('should render the page without leaving render target', async () => { - const html = await renderViaHTTP(appPort, '/special-chars') - await validateAMP(html) - expect(html).not.toContain('__NEXT_AMP_RENDER_TARGET__') - }) - - it('should not output client pages for AMP only', async () => { - const browser = await webdriver(appPort, '/nav') - await browser.elementByCss('#only-amp-link').click() - - const result = await browser.eval('window.NAV_PAGE_LOADED') - - expect(result).toBeFalsy() + afterAll(async () => { + await rename( + join(appDir, 'pages/invalid-amp.js.bak'), + join(appDir, 'pages/invalid-amp.js') + ) + return killApp(app) }) - it('should not output client pages for AMP only with config exported after declaration', async () => { - const browser = await webdriver(appPort, '/nav') - await browser.elementByCss('#var-before-export-link').click() - - const result = await browser.eval('window.NAV_PAGE_LOADED') - - expect(result).toBeFalsy() + it('should have amp optimizer in trace', async () => { + const trace = JSON.parse( + readFileSync(join(appDir, '.next/next-server.js.nft.json'), 'utf8') + ) + expect( + trace.files.some((file) => + file.replace(/\\/g, '/').includes('@ampproject/toolbox-optimizer') + ) + ).toBe(true) }) - it('should drop custom scripts', async () => { - const html = await renderViaHTTP(appPort, '/custom-scripts') - expect(html).not.toMatch(/src='\/im-not-allowed\.js'/) - expect(html).not.toMatch(/console\.log("I'm not either :p")'/) + it('should not contain missing files warning', async () => { + expect(output).toContain('Compiled successfully') + expect(output).not.toContain('Could not find files for') }) - it('should not drop custom amp scripts', async () => { - const html = await renderViaHTTP(appPort, '/amp-script?amp=1') - await validateAMP(html) + describe('With basic usage', () => { + it('should render the page', async () => { + const html = await renderViaHTTP(appPort, '/') + expect(html).toMatch(/Hello World/) + }) }) - it('should optimize clean', async () => { - const html = await renderViaHTTP(appPort, '/only-amp') - await validateAMP(html) - }) + describe('With basic AMP usage', () => { + it('should render the page as valid AMP', async () => { + const html = await renderViaHTTP(appPort, '/?amp=1') + await validateAMP(html) + expect(html).toMatch(/Hello World/) - it('should auto import extensions', async () => { - const html = await renderViaHTTP(appPort, '/auto-import') - await validateAMP(html) - }) - }) + const $ = cheerio.load(html) + expect($('.abc')).toHaveLength(1) + }) - describe('With AMP context', () => { - it('should render the normal page that uses the AMP hook', async () => { - const html = await renderViaHTTP(appPort, '/use-amp-hook') - expect(html).toMatch(/Hello others/) - expect(html).toMatch(/no AMP for you\.\.\./) - }) + it('should render the page without leaving render target', async () => { + const html = await renderViaHTTP(appPort, '/special-chars') + await validateAMP(html) + expect(html).not.toContain('__NEXT_AMP_RENDER_TARGET__') + }) - it('should render the AMP page that uses the AMP hook', async () => { - const html = await renderViaHTTP(appPort, '/use-amp-hook?amp=1') - await validateAMP(html) - expect(html).toMatch(/Hello AMP/) - expect(html).toMatch(/AMP Power!!!/) - }) + it('should not output client pages for AMP only', async () => { + const browser = await webdriver(appPort, '/nav') + await browser.elementByCss('#only-amp-link').click() - it('should render nested normal page with AMP hook', async () => { - const html = await renderViaHTTP(appPort, '/nested') - expect(html).toMatch(/Hello others/) - }) + const result = await browser.eval('window.NAV_PAGE_LOADED') - it('should render nested AMP page with AMP hook', async () => { - const html = await renderViaHTTP(appPort, '/nested?amp=1') - await validateAMP(html) - expect(html).toMatch(/Hello AMP/) - }) - }) + expect(result).toBeFalsy() + }) - describe('canonical amphtml', () => { - it('should render link rel amphtml', async () => { - const html = await renderViaHTTP(appPort, '/use-amp-hook') - const $ = cheerio.load(html) - expect($('link[rel=amphtml]').first().attr('href')).toBe( - 'http://localhost:1234/use-amp-hook.amp' - ) - }) + it('should not output client pages for AMP only with config exported after declaration', async () => { + const browser = await webdriver(appPort, '/nav') + await browser.elementByCss('#var-before-export-link').click() - it('should render amphtml from provided rel link', async () => { - const html = await renderViaHTTP(appPort, '/use-amp-hook.amp') - await validateAMP(html) - }) + const result = await browser.eval('window.NAV_PAGE_LOADED') - it('should render link rel amphtml with existing query', async () => { - const html = await renderViaHTTP(appPort, '/use-amp-hook?hello=1') - expect(html).not.toMatch(/&amp=1/) - }) + expect(result).toBeFalsy() + }) - it('should render the AMP page that uses the AMP hook', async () => { - const html = await renderViaHTTP(appPort, '/use-amp-hook?amp=1') - const $ = cheerio.load(html) - await validateAMP(html) - expect($('link[rel=canonical]').first().attr('href')).toBe( - 'http://localhost:1234/use-amp-hook' - ) - }) + it('should drop custom scripts', async () => { + const html = await renderViaHTTP(appPort, '/custom-scripts') + expect(html).not.toMatch(/src='\/im-not-allowed\.js'/) + expect(html).not.toMatch(/console\.log("I'm not either :p")'/) + }) - it('should render a canonical regardless of amp-only status (explicit)', async () => { - const html = await renderViaHTTP(appPort, '/only-amp') - const $ = cheerio.load(html) - await validateAMP(html) - expect($('link[rel=canonical]').first().attr('href')).toBe( - 'http://localhost:1234/only-amp' - ) - }) + it('should not drop custom amp scripts', async () => { + const html = await renderViaHTTP(appPort, '/amp-script?amp=1') + await validateAMP(html) + }) - it('should not render amphtml link tag with no AMP page', async () => { - const html = await renderViaHTTP(appPort, '/normal') - const $ = cheerio.load(html) - expect($('link[rel=amphtml]').first().attr('href')).not.toBeTruthy() - }) + it('should optimize clean', async () => { + const html = await renderViaHTTP(appPort, '/only-amp') + await validateAMP(html) + }) - it('should remove conflicting amp tags', async () => { - const html = await renderViaHTTP(appPort, '/conflicting-tag?amp=1') - const $ = cheerio.load(html) - await validateAMP(html) - expect($('meta[name=viewport]').attr('content')).not.toBe( - 'something :p' - ) + it('should auto import extensions', async () => { + const html = await renderViaHTTP(appPort, '/auto-import') + await validateAMP(html) + }) }) - it('should allow manually setting canonical', async () => { - const html = await renderViaHTTP(appPort, '/manual-rels?amp=1') - const $ = cheerio.load(html) - await validateAMP(html) - expect($('link[rel=canonical]').attr('href')).toBe( - '/my-custom-canonical' - ) + describe('With AMP context', () => { + it('should render the normal page that uses the AMP hook', async () => { + const html = await renderViaHTTP(appPort, '/use-amp-hook') + expect(html).toMatch(/Hello others/) + expect(html).toMatch(/no AMP for you\.\.\./) + }) + + it('should render the AMP page that uses the AMP hook', async () => { + const html = await renderViaHTTP(appPort, '/use-amp-hook?amp=1') + await validateAMP(html) + expect(html).toMatch(/Hello AMP/) + expect(html).toMatch(/AMP Power!!!/) + }) + + it('should render nested normal page with AMP hook', async () => { + const html = await renderViaHTTP(appPort, '/nested') + expect(html).toMatch(/Hello others/) + }) + + it('should render nested AMP page with AMP hook', async () => { + const html = await renderViaHTTP(appPort, '/nested?amp=1') + await validateAMP(html) + expect(html).toMatch(/Hello AMP/) + }) }) - it('should allow manually setting amphtml rel', async () => { - const html = await renderViaHTTP(appPort, '/manual-rels') - const $ = cheerio.load(html) - expect($('link[rel=amphtml]').attr('href')).toBe('/my-custom-amphtml') - expect($('link[rel=amphtml]')).toHaveLength(1) + describe('canonical amphtml', () => { + it('should render link rel amphtml', async () => { + const html = await renderViaHTTP(appPort, '/use-amp-hook') + const $ = cheerio.load(html) + expect($('link[rel=amphtml]').first().attr('href')).toBe( + 'http://localhost:1234/use-amp-hook.amp' + ) + }) + + it('should render amphtml from provided rel link', async () => { + const html = await renderViaHTTP(appPort, '/use-amp-hook.amp') + await validateAMP(html) + }) + + it('should render link rel amphtml with existing query', async () => { + const html = await renderViaHTTP(appPort, '/use-amp-hook?hello=1') + expect(html).not.toMatch(/&amp=1/) + }) + + it('should render the AMP page that uses the AMP hook', async () => { + const html = await renderViaHTTP(appPort, '/use-amp-hook?amp=1') + const $ = cheerio.load(html) + await validateAMP(html) + expect($('link[rel=canonical]').first().attr('href')).toBe( + 'http://localhost:1234/use-amp-hook' + ) + }) + + it('should render a canonical regardless of amp-only status (explicit)', async () => { + const html = await renderViaHTTP(appPort, '/only-amp') + const $ = cheerio.load(html) + await validateAMP(html) + expect($('link[rel=canonical]').first().attr('href')).toBe( + 'http://localhost:1234/only-amp' + ) + }) + + it('should not render amphtml link tag with no AMP page', async () => { + const html = await renderViaHTTP(appPort, '/normal') + const $ = cheerio.load(html) + expect($('link[rel=amphtml]').first().attr('href')).not.toBeTruthy() + }) + + it('should remove conflicting amp tags', async () => { + const html = await renderViaHTTP(appPort, '/conflicting-tag?amp=1') + const $ = cheerio.load(html) + await validateAMP(html) + expect($('meta[name=viewport]').attr('content')).not.toBe( + 'something :p' + ) + }) + + it('should allow manually setting canonical', async () => { + const html = await renderViaHTTP(appPort, '/manual-rels?amp=1') + const $ = cheerio.load(html) + await validateAMP(html) + expect($('link[rel=canonical]').attr('href')).toBe( + '/my-custom-canonical' + ) + }) + + it('should allow manually setting amphtml rel', async () => { + const html = await renderViaHTTP(appPort, '/manual-rels') + const $ = cheerio.load(html) + expect($('link[rel=amphtml]').attr('href')).toBe('/my-custom-amphtml') + expect($('link[rel=amphtml]')).toHaveLength(1) + }) }) - }) - describe('combined styles', () => { - it('should combine style tags', async () => { - const html = await renderViaHTTP(appPort, '/styled?amp=1') - const $ = cheerio.load(html) - expect($('style[amp-custom]').first().text()).toMatch( - /div.jsx-[a-zA-Z0-9]{1,}{color:red}span.jsx-[a-zA-Z0-9]{1,}{color:(?:blue|#00f)}body{background-color:green}/ - ) - }) + describe('combined styles', () => { + it('should combine style tags', async () => { + const html = await renderViaHTTP(appPort, '/styled?amp=1') + const $ = cheerio.load(html) + expect($('style[amp-custom]').first().text()).toMatch( + /div.jsx-[a-zA-Z0-9]{1,}{color:red}span.jsx-[a-zA-Z0-9]{1,}{color:(?:blue|#00f)}body{background-color:green}/ + ) + }) - it('should remove sourceMaps from styles', async () => { - const html = await renderViaHTTP(appPort, '/styled?amp=1') - const $ = cheerio.load(html) - const styles = $('style[amp-custom]').first().text() + it('should remove sourceMaps from styles', async () => { + const html = await renderViaHTTP(appPort, '/styled?amp=1') + const $ = cheerio.load(html) + const styles = $('style[amp-custom]').first().text() - expect(styles).not.toMatch(/\/\*@ sourceURL=.*?\*\//) - expect(styles).not.toMatch(/\/\*# sourceMappingURL=.*\*\//) + expect(styles).not.toMatch(/\/\*@ sourceURL=.*?\*\//) + expect(styles).not.toMatch(/\/\*# sourceMappingURL=.*\*\//) + }) }) - }) - }) + } + ) describe('AMP dev no-warn', () => { let dynamicAppPort diff --git a/test/integration/api-catch-all/test/index.test.js b/test/integration/api-catch-all/test/index.test.js index 90bc7e3d4ccab..5fa5829a06c92 100644 --- a/test/integration/api-catch-all/test/index.test.js +++ b/test/integration/api-catch-all/test/index.test.js @@ -59,14 +59,17 @@ describe('API routes', () => { runTests() }) - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - beforeAll(async () => { - await nextBuild(appDir) - appPort = await findPort() - app = await nextStart(appDir, appPort) - }) - afterAll(() => killApp(app)) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + beforeAll(async () => { + await nextBuild(appDir) + appPort = await findPort() + app = await nextStart(appDir, appPort) + }) + afterAll(() => killApp(app)) - runTests() - }) + runTests() + } + ) }) diff --git a/test/integration/api-support/test/index.test.js b/test/integration/api-support/test/index.test.js index fb27d6103f1b1..51491b65c3615 100644 --- a/test/integration/api-support/test/index.test.js +++ b/test/integration/api-support/test/index.test.js @@ -644,15 +644,18 @@ describe('API routes', () => { runTests(true) }) - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - beforeAll(async () => { - await nextBuild(appDir) - mode = 'server' - appPort = await findPort() - app = await nextStart(appDir, appPort) - }) - afterAll(() => killApp(app)) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + beforeAll(async () => { + await nextBuild(appDir) + mode = 'server' + appPort = await findPort() + app = await nextStart(appDir, appPort) + }) + afterAll(() => killApp(app)) - runTests() - }) + runTests() + } + ) }) diff --git a/test/integration/app-dir-export/test/config.test.ts b/test/integration/app-dir-export/test/config.test.ts index 36d5a4a2e513d..a450e982e2a2f 100644 --- a/test/integration/app-dir-export/test/config.test.ts +++ b/test/integration/app-dir-export/test/config.test.ts @@ -11,79 +11,84 @@ import { } from './utils' describe('app dir - with output export (next dev / next build)', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - it('should throw when exportPathMap configured', async () => { - nextConfig.replace( - 'trailingSlash: true,', - `trailingSlash: true, + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + it('should throw when exportPathMap configured', async () => { + nextConfig.replace( + 'trailingSlash: true,', + `trailingSlash: true, exportPathMap: async function (map) { return map },` - ) - await fs.remove(distDir) - await fs.remove(exportDir) - let result = { code: 0, stderr: '' } - try { - result = await nextBuild(appDir, [], { stderr: true }) - } finally { - nextConfig.restore() - } - expect(result.code).toBe(1) - expect(result.stderr).toContain( - 'The "exportPathMap" configuration cannot be used with the "app" directory. Please use generateStaticParams() instead.' - ) - }) - it('should error when running next export', async () => { - await fs.remove(distDir) - await fs.remove(exportDir) - nextConfig.delete() - try { - await nextBuild(appDir) - expect(await getFiles()).toEqual([]) - let stdout = '' - let stderr = '' - let error = undefined + ) + await fs.remove(distDir) + await fs.remove(exportDir) + let result = { code: 0, stderr: '' } try { - await runNextCommand(['export', appDir], { - onStdout(msg) { - stdout += msg - }, - onStderr(msg) { - stderr += msg - }, - }) - } catch (e) { - error = e + result = await nextBuild(appDir, [], { stderr: true }) + } finally { + nextConfig.restore() } - expect(error).toBeDefined() - expect(stderr).toContain( - `\`next export\` has been removed in favor of 'output: export' in next.config.js` + expect(result.code).toBe(1) + expect(result.stderr).toContain( + 'The "exportPathMap" configuration cannot be used with the "app" directory. Please use generateStaticParams() instead.' ) - expect(stdout).not.toContain('Export successful. Files written to') - expect(await getFiles()).toEqual([]) - } finally { - nextConfig.restore() + }) + it('should error when running next export', async () => { await fs.remove(distDir) await fs.remove(exportDir) - } - }) - it('should correctly emit exported assets to config.distDir', async () => { - const outputDir = join(appDir, 'output') - await fs.remove(distDir) - await fs.remove(outputDir) - nextConfig.replace( - 'trailingSlash: true,', - `trailingSlash: true, - distDir: 'output',` - ) - try { - await nextBuild(appDir) - expect(await getFiles(outputDir)).toEqual(expectedWhenTrailingSlashTrue) - } finally { - nextConfig.restore() + nextConfig.delete() + try { + await nextBuild(appDir) + expect(await getFiles()).toEqual([]) + let stdout = '' + let stderr = '' + let error = undefined + try { + await runNextCommand(['export', appDir], { + onStdout(msg) { + stdout += msg + }, + onStderr(msg) { + stderr += msg + }, + }) + } catch (e) { + error = e + } + expect(error).toBeDefined() + expect(stderr).toContain( + `\`next export\` has been removed in favor of 'output: export' in next.config.js` + ) + expect(stdout).not.toContain('Export successful. Files written to') + expect(await getFiles()).toEqual([]) + } finally { + nextConfig.restore() + await fs.remove(distDir) + await fs.remove(exportDir) + } + }) + it('should correctly emit exported assets to config.distDir', async () => { + const outputDir = join(appDir, 'output') await fs.remove(distDir) await fs.remove(outputDir) - } - }) - }) + nextConfig.replace( + 'trailingSlash: true,', + `trailingSlash: true, + distDir: 'output',` + ) + try { + await nextBuild(appDir) + expect(await getFiles(outputDir)).toEqual( + expectedWhenTrailingSlashTrue + ) + } finally { + nextConfig.restore() + await fs.remove(distDir) + await fs.remove(outputDir) + } + }) + } + ) }) diff --git a/test/integration/app-dir-export/test/dynamic-missing-gsp-prod.test.ts b/test/integration/app-dir-export/test/dynamic-missing-gsp-prod.test.ts index 0bca7526b3e3d..78267dd1e070f 100644 --- a/test/integration/app-dir-export/test/dynamic-missing-gsp-prod.test.ts +++ b/test/integration/app-dir-export/test/dynamic-missing-gsp-prod.test.ts @@ -1,25 +1,28 @@ import { runTests } from './utils' describe('app dir - with output export - dynamic missing gsp prod', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - it('should error when dynamic route is missing generateStaticParams', async () => { - await runTests({ - isDev: false, - dynamicPage: 'undefined', - generateStaticParamsOpt: 'set noop', - expectedErrMsg: - 'Page "/another/[slug]" is missing "generateStaticParams()" so it cannot be used with "output: export" config.', + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + it('should error when dynamic route is missing generateStaticParams', async () => { + await runTests({ + isDev: false, + dynamicPage: 'undefined', + generateStaticParamsOpt: 'set noop', + expectedErrMsg: + 'Page "/another/[slug]" is missing "generateStaticParams()" so it cannot be used with "output: export" config.', + }) }) - }) - it('should error when client component has generateStaticParams', async () => { - await runTests({ - isDev: false, - dynamicPage: 'undefined', - generateStaticParamsOpt: 'set client', - expectedErrMsg: - 'Page "/another/[slug]/page" cannot use both "use client" and export function "generateStaticParams()".', + it('should error when client component has generateStaticParams', async () => { + await runTests({ + isDev: false, + dynamicPage: 'undefined', + generateStaticParamsOpt: 'set client', + expectedErrMsg: + 'Page "/another/[slug]/page" cannot use both "use client" and export function "generateStaticParams()".', + }) }) - }) - }) + } + ) }) diff --git a/test/integration/app-dir-export/test/dynamicapiroute-prod.test.ts b/test/integration/app-dir-export/test/dynamicapiroute-prod.test.ts index d3ba2a327cad8..00b9ced8d5657 100644 --- a/test/integration/app-dir-export/test/dynamicapiroute-prod.test.ts +++ b/test/integration/app-dir-export/test/dynamicapiroute-prod.test.ts @@ -1,21 +1,24 @@ import { runTests } from './utils' describe('app dir - with output export - dynamic api route prod', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - it.each([ - { dynamicApiRoute: 'undefined' }, - { dynamicApiRoute: "'error'" }, - { dynamicApiRoute: "'force-static'" }, - { - dynamicApiRoute: "'force-dynamic'", - expectedErrMsg: - 'export const dynamic = "force-dynamic" on page "/api/json" cannot be used with "output: export".', - }, - ])( - 'should work in prod with dynamicApiRoute $dynamicApiRoute', - async ({ dynamicApiRoute, expectedErrMsg }) => { - await runTests({ isDev: false, dynamicApiRoute, expectedErrMsg }) - } - ) - }) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + it.each([ + { dynamicApiRoute: 'undefined' }, + { dynamicApiRoute: "'error'" }, + { dynamicApiRoute: "'force-static'" }, + { + dynamicApiRoute: "'force-dynamic'", + expectedErrMsg: + 'export const dynamic = "force-dynamic" on page "/api/json" cannot be used with "output: export".', + }, + ])( + 'should work in prod with dynamicApiRoute $dynamicApiRoute', + async ({ dynamicApiRoute, expectedErrMsg }) => { + await runTests({ isDev: false, dynamicApiRoute, expectedErrMsg }) + } + ) + } + ) }) diff --git a/test/integration/app-dir-export/test/dynamicpage-prod.test.ts b/test/integration/app-dir-export/test/dynamicpage-prod.test.ts index 58e507b84e189..4a04638cd42c8 100644 --- a/test/integration/app-dir-export/test/dynamicpage-prod.test.ts +++ b/test/integration/app-dir-export/test/dynamicpage-prod.test.ts @@ -1,21 +1,24 @@ import { runTests } from './utils' describe('app dir - with output export - dynamic api route prod', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - it.each([ - { dynamicPage: 'undefined' }, - { dynamicPage: "'error'" }, - { dynamicPage: "'force-static'" }, - { - dynamicPage: "'force-dynamic'", - expectedErrMsg: - 'Page with `dynamic = "force-dynamic"` couldn\'t be exported. `output: "export"` requires all pages be renderable statically', - }, - ])( - 'should work in prod with dynamicPage $dynamicPage', - async ({ dynamicPage, expectedErrMsg }) => { - await runTests({ isDev: false, dynamicPage, expectedErrMsg }) - } - ) - }) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + it.each([ + { dynamicPage: 'undefined' }, + { dynamicPage: "'error'" }, + { dynamicPage: "'force-static'" }, + { + dynamicPage: "'force-dynamic'", + expectedErrMsg: + 'Page with `dynamic = "force-dynamic"` couldn\'t be exported. `output: "export"` requires all pages be renderable statically', + }, + ])( + 'should work in prod with dynamicPage $dynamicPage', + async ({ dynamicPage, expectedErrMsg }) => { + await runTests({ isDev: false, dynamicPage, expectedErrMsg }) + } + ) + } + ) }) diff --git a/test/integration/app-dir-export/test/start.test.ts b/test/integration/app-dir-export/test/start.test.ts index a801470efd70a..21f1b142c58fb 100644 --- a/test/integration/app-dir-export/test/start.test.ts +++ b/test/integration/app-dir-export/test/start.test.ts @@ -18,45 +18,48 @@ const nextConfig = new File(join(appDir, 'next.config.js')) let app describe('app dir - with output export (next start)', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - afterEach(async () => { - await killApp(app) - nextConfig.restore() - await fs.remove(distDir) - await fs.remove(exportDir) - }) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + afterEach(async () => { + await killApp(app) + nextConfig.restore() + await fs.remove(distDir) + await fs.remove(exportDir) + }) - it('should error during next start with output export', async () => { - const { code } = await nextBuild(appDir) - expect(code).toBe(0) - const port = await findPort() - let stderr = '' - app = await nextStart(appDir, port, { - onStderr(msg: string) { - stderr += msg || '' - }, + it('should error during next start with output export', async () => { + const { code } = await nextBuild(appDir) + expect(code).toBe(0) + const port = await findPort() + let stderr = '' + app = await nextStart(appDir, port, { + onStderr(msg: string) { + stderr += msg || '' + }, + }) + await check(() => stderr, /error/i) + expect(stderr).toContain( + '"next start" does not work with "output: export" configuration. Use "npx serve@latest out" instead.' + ) }) - await check(() => stderr, /error/i) - expect(stderr).toContain( - '"next start" does not work with "output: export" configuration. Use "npx serve@latest out" instead.' - ) - }) - it('should warn during next start with output standalone', async () => { - nextConfig.replace(`output: 'export'`, `output: 'standalone'`) - const { code } = await nextBuild(appDir) - expect(code).toBe(0) - const port = await findPort() - let stderr = '' - app = await nextStart(appDir, port, { - onStderr(msg: string) { - stderr += msg || '' - }, + it('should warn during next start with output standalone', async () => { + nextConfig.replace(`output: 'export'`, `output: 'standalone'`) + const { code } = await nextBuild(appDir) + expect(code).toBe(0) + const port = await findPort() + let stderr = '' + app = await nextStart(appDir, port, { + onStderr(msg: string) { + stderr += msg || '' + }, + }) + await check(() => stderr, /⚠/i) + expect(stderr).toContain( + `"next start" does not work with "output: standalone" configuration. Use "node .next/standalone/server.js" instead.` + ) }) - await check(() => stderr, /⚠/i) - expect(stderr).toContain( - `"next start" does not work with "output: standalone" configuration. Use "node .next/standalone/server.js" instead.` - ) - }) - }) + } + ) }) diff --git a/test/integration/app-dir-export/test/trailing-slash-start.test.ts b/test/integration/app-dir-export/test/trailing-slash-start.test.ts index 02e63769ff3d2..fc3964600e7af 100644 --- a/test/integration/app-dir-export/test/trailing-slash-start.test.ts +++ b/test/integration/app-dir-export/test/trailing-slash-start.test.ts @@ -1,12 +1,15 @@ import { runTests } from './utils' describe('app dir - with output export - trailing slash prod', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - it.each([{ trailingSlash: false }, { trailingSlash: true }])( - "should work in prod with trailingSlash '$trailingSlash'", - async ({ trailingSlash }) => { - await runTests({ isDev: false, trailingSlash }) - } - ) - }) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + it.each([{ trailingSlash: false }, { trailingSlash: true }])( + "should work in prod with trailingSlash '$trailingSlash'", + async ({ trailingSlash }) => { + await runTests({ isDev: false, trailingSlash }) + } + ) + } + ) }) diff --git a/test/integration/app-document-import-order/test/index.test.js b/test/integration/app-document-import-order/test/index.test.js index b823f2bf3b7dd..103b3d561601a 100644 --- a/test/integration/app-document-import-order/test/index.test.js +++ b/test/integration/app-document-import-order/test/index.test.js @@ -51,23 +51,26 @@ const respectsChunkAttachmentOrder = async () => { } describe('Root components import order', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - beforeAll(async () => { - await nextBuild(appDir) - appPort = await findPort() - app = await nextStart(appDir, appPort) - }) - afterAll(() => killApp(app)) - - it( - '_app chunks should be attached to de dom before page chunks', - respectsChunkAttachmentOrder - ) - it( - 'root components should be imported in this order _document > _app > page in order to respect side effects', - respectsSideEffects - ) - }) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + beforeAll(async () => { + await nextBuild(appDir) + appPort = await findPort() + app = await nextStart(appDir, appPort) + }) + afterAll(() => killApp(app)) + + it( + '_app chunks should be attached to de dom before page chunks', + respectsChunkAttachmentOrder + ) + it( + 'root components should be imported in this order _document > _app > page in order to respect side effects', + respectsSideEffects + ) + } + ) }) describe('development mode', () => { diff --git a/test/integration/app-document-style-fragment/test/index.test.js b/test/integration/app-document-style-fragment/test/index.test.js index 3b81191139ab6..db6a60ef24393 100644 --- a/test/integration/app-document-style-fragment/test/index.test.js +++ b/test/integration/app-document-style-fragment/test/index.test.js @@ -16,27 +16,30 @@ let server let app describe('Custom Document Fragment Styles', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - beforeAll(async () => { - await nextBuild(appDir) - app = nextServer({ - dir: join(__dirname, '../'), - dev: false, - quiet: true, - }) + ;(process.env.TURBOPACK_DEV ? 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)) + server = await startApp(app) + appPort = server.address().port + }) + afterAll(() => stopApp(server)) - it('correctly adds styles from fragment styles key', async () => { - const html = await renderViaHTTP(appPort, '/') - const $ = cheerio.load(html) + it('correctly adds styles from fragment styles key', async () => { + const html = await renderViaHTTP(appPort, '/') + const $ = cheerio.load(html) - const styles = $('style').text() - expect(styles).toMatch(/background:(.*|)hotpink/) - expect(styles).toMatch(/font-size:(.*|)16\.4px/) - }) - }) + const styles = $('style').text() + expect(styles).toMatch(/background:(.*|)hotpink/) + expect(styles).toMatch(/font-size:(.*|)16\.4px/) + }) + } + ) }) diff --git a/test/integration/app-dynamic-error/test/index.test.ts b/test/integration/app-dynamic-error/test/index.test.ts index 1215ef263b3df..6def977333c7a 100644 --- a/test/integration/app-dynamic-error/test/index.test.ts +++ b/test/integration/app-dynamic-error/test/index.test.ts @@ -1,17 +1,20 @@ import { nextBuild } from 'next-test-utils' import { join } from 'path' describe('app-dynamic-error', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - it('throws an error when prerendering a page with config dynamic error', async () => { - const appDir = join(__dirname, '../../app-dynamic-error') - const { stderr, code } = await nextBuild(appDir, [], { - stderr: true, - stdout: true, + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + it('throws an error when prerendering a page with config dynamic error', async () => { + const appDir = join(__dirname, '../../app-dynamic-error') + const { stderr, code } = await nextBuild(appDir, [], { + stderr: true, + stdout: true, + }) + expect(stderr).toContain( + 'Error occurred prerendering page "/dynamic-error"' + ) + expect(code).toBe(1) }) - expect(stderr).toContain( - 'Error occurred prerendering page "/dynamic-error"' - ) - expect(code).toBe(1) - }) - }) + } + ) }) diff --git a/test/integration/app-tree/test/index.test.js b/test/integration/app-tree/test/index.test.js index d0945d49c8c36..c9582cb5f770e 100644 --- a/test/integration/app-tree/test/index.test.js +++ b/test/integration/app-tree/test/index.test.js @@ -56,13 +56,16 @@ describe('AppTree', () => { afterAll(() => killApp(app)) runTests() }) - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - beforeAll(async () => { - await nextBuild(appDir) - appPort = await findPort() - app = await nextStart(appDir, appPort) - }) - afterAll(() => killApp(app)) - runTests() - }) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + beforeAll(async () => { + await nextBuild(appDir) + appPort = await findPort() + app = await nextStart(appDir, appPort) + }) + afterAll(() => killApp(app)) + runTests() + } + ) }) diff --git a/test/integration/app-types/app-types.test.js b/test/integration/app-types/app-types.test.js index 4cc4ffe5236a2..901423279bbf3 100644 --- a/test/integration/app-types/app-types.test.js +++ b/test/integration/app-types/app-types.test.js @@ -7,103 +7,106 @@ import { nextBuild } from 'next-test-utils' const appDir = __dirname describe('app type checking', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - let stderr, errors - beforeAll(async () => { - stderr = (await nextBuild(appDir, [], { stderr: true })).stderr - - errors = stderr.match( - /===== TS errors =====(.+)===== TS errors =====/s - )?.[1] - }) - - it('should generate route types correctly and report link error', async () => { - // Make sure the d.ts file is generated - const dts = ( - await fs.readFile(path.join(appDir, '.next', 'types', 'link.d.ts')) - ).toString() - expect(dts.includes('`/dashboard/user/')).toBeTruthy() - expect(dts.includes('`/dashboard/another')).toBeTruthy() - - // Check type checking errors - expect(errors).toContain( - 'Type error: "/(newroot)/dashboard/another" is not an existing route. If it is intentional, please type it explicitly with `as Route`.' - ) - - // Make sure all errors were reported and other links passed type checking - const errorLines = [ - ...errors.matchAll( - /\.\/src\/app\/type-checks\/link\/page\.tsx:(\d+):/g - ), - ].map(([, line]) => +line) - - const ST = 17 - const ED = 34 - expect(errorLines).toEqual( - Array.from({ length: ED - ST + 1 }, (_, i) => i + ST) - ) - }) - - it('should generate route types correctly and report router API errors', async () => { - // Make sure all errors were reported and other links passed type checking - const errorLines = [ - ...errors.matchAll( - /\.\/src\/app\/type-checks\/router\/page\.tsx:(\d+):/g - ), - ].map(([, line]) => +line) - - const ST = 11 - const ED = 13 - expect(errorLines).toEqual( - Array.from({ length: ED - ST + 1 }, (_, i) => i + ST) - ) - }) - - it('should type check invalid entry exports', () => { - // Can't export arbitrary things. - expect(errors).toContain(`"foo" is not a valid Page export field.`) - - // Can't export invalid fields. - expect(errors).toMatch( - /Invalid configuration "revalidate":\s+Expected "false | number (>= 0)", got "-1"/ - ) - - // Avoid invalid argument types for exported functions. - expect(errors).toMatch( - /Page "src\/app\/type-checks\/config\/page\.tsx" has an invalid "default" export:\s+Type "{ foo: string; }" is not valid/ - ) - expect(errors).toMatch( - /Page "src\/app\/type-checks\/config\/page\.tsx" has an invalid "generateMetadata" export:\s+Type "{ s: number; }" is not valid/ - ) - expect(errors).toMatch( - /Page "src\/app\/type-checks\/config\/page\.tsx" has an invalid "generateStaticParams" export:\s+Type "string" is not valid/ - ) - - // Avoid invalid return types for exported functions. - expect(errors).toContain( - `"Promise" is not a valid generateStaticParams return type` - ) - - // Can't export arbitrary things. - expect(errors).toContain(`"bar" is not a valid Route export field.`) - - // Can't export invalid fields. - expect(errors).toMatch( - /Invalid configuration "revalidate":\s+Expected "false | number (>= 0)", got "-1"/ - ) - - // Avoid invalid argument types for exported functions. - expect(errors).toMatch( - /Route "src\/app\/type-checks\/route-handlers\/route\.ts" has an invalid "GET" export:\s+Type "boolean" is not a valid type for the function's first argument/ - ) - expect(errors).toMatch( - /Route "src\/app\/type-checks\/route-handlers\/route\.ts" has an invalid "generateStaticParams" export:\s+Type "string" is not valid/ - ) - - // Avoid invalid return types for exported functions. - expect(errors).toContain( - `"Promise" is not a valid generateStaticParams return type` - ) - }) - }) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + let stderr, errors + beforeAll(async () => { + stderr = (await nextBuild(appDir, [], { stderr: true })).stderr + + errors = stderr.match( + /===== TS errors =====(.+)===== TS errors =====/s + )?.[1] + }) + + it('should generate route types correctly and report link error', async () => { + // Make sure the d.ts file is generated + const dts = ( + await fs.readFile(path.join(appDir, '.next', 'types', 'link.d.ts')) + ).toString() + expect(dts.includes('`/dashboard/user/')).toBeTruthy() + expect(dts.includes('`/dashboard/another')).toBeTruthy() + + // Check type checking errors + expect(errors).toContain( + 'Type error: "/(newroot)/dashboard/another" is not an existing route. If it is intentional, please type it explicitly with `as Route`.' + ) + + // Make sure all errors were reported and other links passed type checking + const errorLines = [ + ...errors.matchAll( + /\.\/src\/app\/type-checks\/link\/page\.tsx:(\d+):/g + ), + ].map(([, line]) => +line) + + const ST = 17 + const ED = 34 + expect(errorLines).toEqual( + Array.from({ length: ED - ST + 1 }, (_, i) => i + ST) + ) + }) + + it('should generate route types correctly and report router API errors', async () => { + // Make sure all errors were reported and other links passed type checking + const errorLines = [ + ...errors.matchAll( + /\.\/src\/app\/type-checks\/router\/page\.tsx:(\d+):/g + ), + ].map(([, line]) => +line) + + const ST = 11 + const ED = 13 + expect(errorLines).toEqual( + Array.from({ length: ED - ST + 1 }, (_, i) => i + ST) + ) + }) + + it('should type check invalid entry exports', () => { + // Can't export arbitrary things. + expect(errors).toContain(`"foo" is not a valid Page export field.`) + + // Can't export invalid fields. + expect(errors).toMatch( + /Invalid configuration "revalidate":\s+Expected "false | number (>= 0)", got "-1"/ + ) + + // Avoid invalid argument types for exported functions. + expect(errors).toMatch( + /Page "src\/app\/type-checks\/config\/page\.tsx" has an invalid "default" export:\s+Type "{ foo: string; }" is not valid/ + ) + expect(errors).toMatch( + /Page "src\/app\/type-checks\/config\/page\.tsx" has an invalid "generateMetadata" export:\s+Type "{ s: number; }" is not valid/ + ) + expect(errors).toMatch( + /Page "src\/app\/type-checks\/config\/page\.tsx" has an invalid "generateStaticParams" export:\s+Type "string" is not valid/ + ) + + // Avoid invalid return types for exported functions. + expect(errors).toContain( + `"Promise" is not a valid generateStaticParams return type` + ) + + // Can't export arbitrary things. + expect(errors).toContain(`"bar" is not a valid Route export field.`) + + // Can't export invalid fields. + expect(errors).toMatch( + /Invalid configuration "revalidate":\s+Expected "false | number (>= 0)", got "-1"/ + ) + + // Avoid invalid argument types for exported functions. + expect(errors).toMatch( + /Route "src\/app\/type-checks\/route-handlers\/route\.ts" has an invalid "GET" export:\s+Type "boolean" is not a valid type for the function's first argument/ + ) + expect(errors).toMatch( + /Route "src\/app\/type-checks\/route-handlers\/route\.ts" has an invalid "generateStaticParams" export:\s+Type "string" is not valid/ + ) + + // Avoid invalid return types for exported functions. + expect(errors).toContain( + `"Promise" is not a valid generateStaticParams return type` + ) + }) + } + ) }) diff --git a/test/integration/async-modules/test/index.test.js b/test/integration/async-modules/test/index.test.js index 4daef2d611e42..22fce2bdf8f61 100644 --- a/test/integration/async-modules/test/index.test.js +++ b/test/integration/async-modules/test/index.test.js @@ -115,16 +115,19 @@ describe('Async modules', () => { runTests(true) }) - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - beforeAll(async () => { - await nextBuild(appDir) - appPort = await findPort() - app = await nextStart(appDir, appPort) - }) - afterAll(async () => { - await killApp(app) - }) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + beforeAll(async () => { + await nextBuild(appDir) + appPort = await findPort() + app = await nextStart(appDir, appPort) + }) + afterAll(async () => { + await killApp(app) + }) - runTests() - }) + runTests() + } + ) }) diff --git a/test/integration/auto-export-error-bail/test/index.test.js b/test/integration/auto-export-error-bail/test/index.test.js index 515dfb0823eee..f9d8c13369e4d 100644 --- a/test/integration/auto-export-error-bail/test/index.test.js +++ b/test/integration/auto-export-error-bail/test/index.test.js @@ -30,7 +30,10 @@ const runTests = () => { } describe('Auto Export _error bail', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - runTests() - }) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + runTests() + } + ) }) diff --git a/test/integration/auto-export-query-error/test/index.test.js b/test/integration/auto-export-query-error/test/index.test.js index 5964ee227fd96..dd10d248c5f81 100644 --- a/test/integration/auto-export-query-error/test/index.test.js +++ b/test/integration/auto-export-query-error/test/index.test.js @@ -21,15 +21,22 @@ const runTests = () => { } describe('Auto Export', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - beforeAll(async () => { - const { stderr: curStderr, code: curCode } = await nextBuild(appDir, [], { - stderr: true, + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + beforeAll(async () => { + const { stderr: curStderr, code: curCode } = await nextBuild( + appDir, + [], + { + stderr: true, + } + ) + stderr = curStderr + exitCode = curCode }) - stderr = curStderr - exitCode = curCode - }) - runTests() - }) + runTests() + } + ) }) diff --git a/test/integration/auto-export/test/index.test.js b/test/integration/auto-export/test/index.test.js index b1773dcc62ac3..8ae2cc8b8b656 100644 --- a/test/integration/auto-export/test/index.test.js +++ b/test/integration/auto-export/test/index.test.js @@ -57,19 +57,22 @@ const runTests = () => { } describe('Auto Export', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - beforeAll(async () => { - await nextBuild(appDir) - appPort = await findPort() - app = await nextStart(appDir, appPort) - }) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + beforeAll(async () => { + await nextBuild(appDir) + appPort = await findPort() + app = await nextStart(appDir, appPort) + }) - afterAll(async () => { - await killApp(app) - }) + afterAll(async () => { + await killApp(app) + }) - runTests() - }) + runTests() + } + ) describe('dev', () => { beforeAll(async () => { diff --git a/test/integration/basepath-root-catch-all/test/index.test.js b/test/integration/basepath-root-catch-all/test/index.test.js index 1e3d0d955fd7e..8ddb60e9c0b7b 100644 --- a/test/integration/basepath-root-catch-all/test/index.test.js +++ b/test/integration/basepath-root-catch-all/test/index.test.js @@ -39,13 +39,16 @@ const runTests = () => { afterAll(() => killApp(app)) runTests() }) -;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - beforeAll(async () => { - await nextBuild(appDir) - buildId = await fs.readFile(join(appDir, '.next/BUILD_ID'), 'utf8') - appPort = await findPort() - app = await nextStart(appDir, appPort) - }) - afterAll(() => killApp(app)) - runTests() -}) +;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + beforeAll(async () => { + await nextBuild(appDir) + buildId = await fs.readFile(join(appDir, '.next/BUILD_ID'), 'utf8') + appPort = await findPort() + app = await nextStart(appDir, appPort) + }) + afterAll(() => killApp(app)) + runTests() + } +) diff --git a/test/integration/bigint/test/index.test.js b/test/integration/bigint/test/index.test.js index cc8ae0ef22437..837a427336465 100644 --- a/test/integration/bigint/test/index.test.js +++ b/test/integration/bigint/test/index.test.js @@ -42,15 +42,18 @@ describe('bigint API route support', () => { runTests() }) - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - beforeAll(async () => { - await fs.remove(nextConfig) - await nextBuild(appDir) - appPort = await findPort() - app = await nextStart(appDir, appPort) - }) - afterAll(() => killApp(app)) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + beforeAll(async () => { + await fs.remove(nextConfig) + await nextBuild(appDir) + appPort = await findPort() + app = await nextStart(appDir, appPort) + }) + afterAll(() => killApp(app)) - runTests() - }) + runTests() + } + ) }) diff --git a/test/integration/build-output/test/index.test.js b/test/integration/build-output/test/index.test.js index 8ae924fed3bfb..6871742cd5ad7 100644 --- a/test/integration/build-output/test/index.test.js +++ b/test/integration/build-output/test/index.test.js @@ -10,300 +10,307 @@ const fixturesDir = join(__dirname, '..', 'fixtures') const nextConfig = new File(join(fixturesDir, 'basic-app/next.config.js')) describe('Build Output', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - const configs = [{}, { gzipSize: false }] - - for (const experimental of configs) { - describe(`Basic Application Output (experimental: ${JSON.stringify( - experimental - )})`, () => { - let stdout - const appDir = join(fixturesDir, 'basic-app') - - const hasExperimentalConfig = Object.keys(experimental).length > 0 + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + const configs = [{}, { gzipSize: false }] + + for (const experimental of configs) { + describe(`Basic Application Output (experimental: ${JSON.stringify( + experimental + )})`, () => { + let stdout + const appDir = join(fixturesDir, 'basic-app') + + const hasExperimentalConfig = Object.keys(experimental).length > 0 + + beforeAll(async () => { + await remove(join(appDir, '.next')) + if (hasExperimentalConfig) { + nextConfig.write( + `module.exports = { experimental: ${JSON.stringify( + experimental + )} };` + ) + } + ;({ stdout } = await nextBuild(appDir, [], { + stdout: true, + })) + }) - beforeAll(async () => { - await remove(join(appDir, '.next')) if (hasExperimentalConfig) { - nextConfig.write( - `module.exports = { experimental: ${JSON.stringify( - experimental - )} };` - ) + afterAll(async () => { + nextConfig.delete() + }) } - ;({ stdout } = await nextBuild(appDir, [], { - stdout: true, - })) - }) - if (hasExperimentalConfig) { - afterAll(async () => { - nextConfig.delete() - }) - } - - it('should not include internal pages', async () => { - expect(stdout).toMatch(/\/ (.* )?\d{1,} B/) - expect(stdout).toMatch(/\+ First Load JS shared by all [ 0-9.]* kB/) - expect(stdout).toMatch(/ chunks\/main-[0-9a-z]{16}\.js [ 0-9.]* kB/) - expect(stdout).toMatch( - / chunks\/framework-[0-9a-z]{16}\.js [ 0-9. ]* kB/ - ) - - expect(stdout).not.toContain(' /_document') - expect(stdout).not.toContain(' /_app') - expect(stdout).not.toContain(' /_error') - expect(stdout).not.toContain('') + it('should not include internal pages', async () => { + expect(stdout).toMatch(/\/ (.* )?\d{1,} B/) + expect(stdout).toMatch(/\+ First Load JS shared by all [ 0-9.]* kB/) + expect(stdout).toMatch(/ chunks\/main-[0-9a-z]{16}\.js [ 0-9.]* kB/) + expect(stdout).toMatch( + / chunks\/framework-[0-9a-z]{16}\.js [ 0-9. ]* kB/ + ) - expect(stdout).toContain('○ /') - }) + expect(stdout).not.toContain(' /_document') + expect(stdout).not.toContain(' /_app') + expect(stdout).not.toContain(' /_error') + expect(stdout).not.toContain('') - // TODO: change format of this test to be more reliable - it.skip('should not deviate from snapshot', async () => { - console.log(stdout) + expect(stdout).toContain('○ /') + }) - if (process.env.NEXT_PRIVATE_SKIP_SIZE_TESTS) { - return - } + // TODO: change format of this test to be more reliable + it.skip('should not deviate from snapshot', async () => { + console.log(stdout) - const parsePageSize = (page) => - stdout.match( - new RegExp(` ${page} .*?((?:\\d|\\.){1,} (?:\\w{1,})) `) - )[1] + if (process.env.NEXT_PRIVATE_SKIP_SIZE_TESTS) { + return + } - const parsePageFirstLoad = (page) => - stdout.match( - new RegExp( - ` ${page} .*?(?:(?:\\d|\\.){1,}) .*? ((?:\\d|\\.){1,} (?:\\w{1,}))` + const parsePageSize = (page) => + stdout.match( + new RegExp(` ${page} .*?((?:\\d|\\.){1,} (?:\\w{1,})) `) + )[1] + + const parsePageFirstLoad = (page) => + stdout.match( + new RegExp( + ` ${page} .*?(?:(?:\\d|\\.){1,}) .*? ((?:\\d|\\.){1,} (?:\\w{1,}))` + ) + )[1] + + const parseSharedSize = (sharedPartName) => { + const matches = stdout.match( + new RegExp( + `${sharedPartName} .*? ((?:\\d|\\.){1,} (?:\\w{1,}))` + ) ) - )[1] - const parseSharedSize = (sharedPartName) => { - const matches = stdout.match( - new RegExp(`${sharedPartName} .*? ((?:\\d|\\.){1,} (?:\\w{1,}))`) - ) + if (!matches) { + throw new Error(`Could not match ${sharedPartName}`) + } - if (!matches) { - throw new Error(`Could not match ${sharedPartName}`) + return matches[1] } - return matches[1] - } - - const indexSize = parsePageSize('/') - const indexFirstLoad = parsePageFirstLoad('/') - - const err404Size = parsePageSize('/404') - const err404FirstLoad = parsePageFirstLoad('/404') - - const sharedByAll = parseSharedSize('shared by all') - const _appSize = parseSharedSize('_app-.*?\\.js') - const webpackSize = parseSharedSize('webpack-.*?\\.js') - const mainSize = parseSharedSize('main-.*?\\.js') - const frameworkSize = parseSharedSize('framework-.*?\\.js') - - for (const size of [ - indexSize, - indexFirstLoad, - err404Size, - err404FirstLoad, - sharedByAll, - _appSize, - webpackSize, - mainSize, - frameworkSize, - ]) { - expect(parseFloat(size)).toBeGreaterThan(0) - } + const indexSize = parsePageSize('/') + const indexFirstLoad = parsePageFirstLoad('/') + + const err404Size = parsePageSize('/404') + const err404FirstLoad = parsePageFirstLoad('/404') + + const sharedByAll = parseSharedSize('shared by all') + const _appSize = parseSharedSize('_app-.*?\\.js') + const webpackSize = parseSharedSize('webpack-.*?\\.js') + const mainSize = parseSharedSize('main-.*?\\.js') + const frameworkSize = parseSharedSize('framework-.*?\\.js') + + for (const size of [ + indexSize, + indexFirstLoad, + err404Size, + err404FirstLoad, + sharedByAll, + _appSize, + webpackSize, + mainSize, + frameworkSize, + ]) { + expect(parseFloat(size)).toBeGreaterThan(0) + } - // const gz = experimental.gzipSize !== false + // const gz = experimental.gzipSize !== false - // expect(parseFloat(indexSize) / 1000).toBeCloseTo( - // gz ? 0.251 : 0.394, - // 2 - // ) - expect(indexSize.endsWith('B')).toBe(true) + // expect(parseFloat(indexSize) / 1000).toBeCloseTo( + // gz ? 0.251 : 0.394, + // 2 + // ) + expect(indexSize.endsWith('B')).toBe(true) - // expect(parseFloat(indexFirstLoad)).toBeCloseTo(gz ? 64 : 196, 1) - expect(indexFirstLoad.endsWith('kB')).toBe(true) + // expect(parseFloat(indexFirstLoad)).toBeCloseTo(gz ? 64 : 196, 1) + expect(indexFirstLoad.endsWith('kB')).toBe(true) - // expect(parseFloat(err404Size)).toBeCloseTo(gz ? 3.17 : 8.51, 1) - expect(err404Size.endsWith('B')).toBe(true) + // expect(parseFloat(err404Size)).toBeCloseTo(gz ? 3.17 : 8.51, 1) + expect(err404Size.endsWith('B')).toBe(true) - // expect(parseFloat(err404FirstLoad)).toBeCloseTo(gz ? 66.9 : 204, 1) - expect(err404FirstLoad.endsWith('kB')).toBe(true) + // expect(parseFloat(err404FirstLoad)).toBeCloseTo(gz ? 66.9 : 204, 1) + expect(err404FirstLoad.endsWith('kB')).toBe(true) - // expect(parseFloat(sharedByAll)).toBeCloseTo(gz ? 63.7 : 196, 1) - expect(sharedByAll.endsWith('kB')).toBe(true) + // expect(parseFloat(sharedByAll)).toBeCloseTo(gz ? 63.7 : 196, 1) + expect(sharedByAll.endsWith('kB')).toBe(true) - // const appSizeValue = _appSize.endsWith('kB') - // ? parseFloat(_appSize) - // : parseFloat(_appSize) / 1000 - // expect(appSizeValue).toBeCloseTo(gz ? 0.799 : 1.63, 1) - expect(_appSize.endsWith('kB') || _appSize.endsWith(' B')).toBe(true) + // const appSizeValue = _appSize.endsWith('kB') + // ? parseFloat(_appSize) + // : parseFloat(_appSize) / 1000 + // expect(appSizeValue).toBeCloseTo(gz ? 0.799 : 1.63, 1) + expect(_appSize.endsWith('kB') || _appSize.endsWith(' B')).toBe( + true + ) - // const webpackSizeValue = webpackSize.endsWith('kB') - // ? parseFloat(webpackSize) - // : parseFloat(webpackSize) / 1000 - // expect(webpackSizeValue).toBeCloseTo(gz ? 0.766 : 1.46, 2) - expect(webpackSize.endsWith('kB') || webpackSize.endsWith(' B')).toBe( - true - ) + // const webpackSizeValue = webpackSize.endsWith('kB') + // ? parseFloat(webpackSize) + // : parseFloat(webpackSize) / 1000 + // expect(webpackSizeValue).toBeCloseTo(gz ? 0.766 : 1.46, 2) + expect( + webpackSize.endsWith('kB') || webpackSize.endsWith(' B') + ).toBe(true) - // expect(parseFloat(mainSize)).toBeCloseTo(gz ? 20.1 : 62.7, 1) - expect(mainSize.endsWith('kB')).toBe(true) + // expect(parseFloat(mainSize)).toBeCloseTo(gz ? 20.1 : 62.7, 1) + expect(mainSize.endsWith('kB')).toBe(true) - // expect(parseFloat(frameworkSize)).toBeCloseTo(gz ? 42.0 : 130, 1) - expect(frameworkSize.endsWith('kB')).toBe(true) - }) + // expect(parseFloat(frameworkSize)).toBeCloseTo(gz ? 42.0 : 130, 1) + expect(frameworkSize.endsWith('kB')).toBe(true) + }) - it('should print duration when rendering or get static props takes long', () => { - const matches = stdout.match( - / \/slow-static\/.+\/.+(?: \(\d+ ms\))?| \[\+\d+ more paths\]/g - ) + it('should print duration when rendering or get static props takes long', () => { + const matches = stdout.match( + / \/slow-static\/.+\/.+(?: \(\d+ ms\))?| \[\+\d+ more paths\]/g + ) - for (const check of [ - // summary - expect.stringMatching( - /\/\[propsDuration\]\/\[renderDuration\] \(\d+ ms\)/ - ), - // ordered by duration, includes duration - expect.stringMatching(/\/2000\/10 \(\d+ ms\)$/), - expect.stringMatching(/\/10\/1000 \(\d+ ms\)$/), - expect.stringMatching(/\/300\/10 \(\d+ ms\)$/), - // max of 7 preview paths - ' [+2 more paths]', - ]) { - // the order isn't guaranteed on the timing tests as while() is being - // used in the render so can block the thread of other renders sharing - // the same worker - expect(matches).toContainEqual(check) - } - }) + for (const check of [ + // summary + expect.stringMatching( + /\/\[propsDuration\]\/\[renderDuration\] \(\d+ ms\)/ + ), + // ordered by duration, includes duration + expect.stringMatching(/\/2000\/10 \(\d+ ms\)$/), + expect.stringMatching(/\/10\/1000 \(\d+ ms\)$/), + expect.stringMatching(/\/300\/10 \(\d+ ms\)$/), + // max of 7 preview paths + ' [+2 more paths]', + ]) { + // the order isn't guaranteed on the timing tests as while() is being + // used in the render so can block the thread of other renders sharing + // the same worker + expect(matches).toContainEqual(check) + } + }) - it('should not emit extracted comments', async () => { - const files = await recursiveReadDir(join(appDir, '.next'), { - pathnameFilter: (f) => /\.txt|\.LICENSE\./.test(f), + it('should not emit extracted comments', async () => { + const files = await recursiveReadDir(join(appDir, '.next'), { + pathnameFilter: (f) => /\.txt|\.LICENSE\./.test(f), + }) + expect(files).toEqual([]) }) - expect(files).toEqual([]) }) - }) - } + } - describe('Custom App Output', () => { - const appDir = join(fixturesDir, 'with-app') + describe('Custom App Output', () => { + const appDir = join(fixturesDir, 'with-app') - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) - - it('should not include custom error', async () => { - const { stdout } = await nextBuild(appDir, [], { - stdout: true, + beforeAll(async () => { + await remove(join(appDir, '.next')) }) - expect(stdout).toMatch(/\/ (.* )?\d{1,} B/) - expect(stdout).toMatch(/\/_app (.* )?\d{1,} B/) - expect(stdout).toMatch(/\+ First Load JS shared by all \s*[0-9.]+ kB/) - expect(stdout).toMatch(/ chunks\/main-[0-9a-z]{16}\.js \s*[0-9.]+ kB/) - expect(stdout).toMatch( - / chunks\/framework-[0-9a-z]{16}\.js \s*[0-9.]+ kB/ - ) - - expect(stdout).not.toContain(' /_document') - expect(stdout).not.toContain(' /_error') - expect(stdout).not.toContain('') + it('should not include custom error', async () => { + const { stdout } = await nextBuild(appDir, [], { + stdout: true, + }) - expect(stdout).toContain(' /_app') - expect(stdout).toContain('○ /') - }) - }) + expect(stdout).toMatch(/\/ (.* )?\d{1,} B/) + expect(stdout).toMatch(/\/_app (.* )?\d{1,} B/) + expect(stdout).toMatch(/\+ First Load JS shared by all \s*[0-9.]+ kB/) + expect(stdout).toMatch(/ chunks\/main-[0-9a-z]{16}\.js \s*[0-9.]+ kB/) + expect(stdout).toMatch( + / chunks\/framework-[0-9a-z]{16}\.js \s*[0-9.]+ kB/ + ) - describe('With AMP Output', () => { - const appDir = join(fixturesDir, 'with-amp') + expect(stdout).not.toContain(' /_document') + expect(stdout).not.toContain(' /_error') + expect(stdout).not.toContain('') - beforeAll(async () => { - await remove(join(appDir, '.next')) + expect(stdout).toContain(' /_app') + expect(stdout).toContain('○ /') + }) }) - it('should not include custom error', async () => { - const { stdout } = await nextBuild(appDir, [], { - stdout: true, - }) + describe('With AMP Output', () => { + const appDir = join(fixturesDir, 'with-amp') - expect(stdout).toMatch(/\/ (.* )?[0-9.]+ B \s*[0-9.]+ kB/) - expect(stdout).toMatch(/\/amp (.* )?AMP/) - expect(stdout).toMatch(/\/hybrid (.* )?[0-9.]+ B/) - expect(stdout).toMatch(/\+ First Load JS shared by all \s*[0-9.]+ kB/) - expect(stdout).toMatch(/ chunks\/main-[0-9a-z]{16}\.js \s*[0-9.]+ kB/) - expect(stdout).toMatch( - / chunks\/framework-[0-9a-z]{16}\.js \s*[0-9.]+ kB/ - ) + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) - expect(stdout).not.toContain(' /_document') - expect(stdout).not.toContain(' /_error') - expect(stdout).not.toContain('') + it('should not include custom error', async () => { + const { stdout } = await nextBuild(appDir, [], { + stdout: true, + }) - expect(stdout).toContain('○ /') - }) - }) + expect(stdout).toMatch(/\/ (.* )?[0-9.]+ B \s*[0-9.]+ kB/) + expect(stdout).toMatch(/\/amp (.* )?AMP/) + expect(stdout).toMatch(/\/hybrid (.* )?[0-9.]+ B/) + expect(stdout).toMatch(/\+ First Load JS shared by all \s*[0-9.]+ kB/) + expect(stdout).toMatch(/ chunks\/main-[0-9a-z]{16}\.js \s*[0-9.]+ kB/) + expect(stdout).toMatch( + / chunks\/framework-[0-9a-z]{16}\.js \s*[0-9.]+ kB/ + ) - describe('Custom Error Output', () => { - const appDir = join(fixturesDir, 'with-error') + expect(stdout).not.toContain(' /_document') + expect(stdout).not.toContain(' /_error') + expect(stdout).not.toContain('') - beforeAll(async () => { - await remove(join(appDir, '.next')) + expect(stdout).toContain('○ /') + }) }) - it('should not include custom app', async () => { - const { stdout } = await nextBuild(appDir, [], { - stdout: true, + describe('Custom Error Output', () => { + const appDir = join(fixturesDir, 'with-error') + + beforeAll(async () => { + await remove(join(appDir, '.next')) }) - expect(stdout).toMatch(/\/ (.* )?\d{1,} B/) - expect(stdout).toMatch(/λ \/404 (.* )?\d{1,} B/) - expect(stdout).toMatch(/\+ First Load JS shared by all [ 0-9.]* kB/) - expect(stdout).toMatch(/ chunks\/main-[0-9a-z]{16}\.js [ 0-9.]* kB/) - expect(stdout).toMatch( - / chunks\/framework-[0-9a-z]{16}\.js [ 0-9. ]* kB/ - ) + it('should not include custom app', async () => { + const { stdout } = await nextBuild(appDir, [], { + stdout: true, + }) + + expect(stdout).toMatch(/\/ (.* )?\d{1,} B/) + expect(stdout).toMatch(/λ \/404 (.* )?\d{1,} B/) + expect(stdout).toMatch(/\+ First Load JS shared by all [ 0-9.]* kB/) + expect(stdout).toMatch(/ chunks\/main-[0-9a-z]{16}\.js [ 0-9.]* kB/) + expect(stdout).toMatch( + / chunks\/framework-[0-9a-z]{16}\.js [ 0-9. ]* kB/ + ) - expect(stdout).not.toContain(' /_document') - expect(stdout).not.toContain(' /_app') - expect(stdout).not.toContain('') + expect(stdout).not.toContain(' /_document') + expect(stdout).not.toContain(' /_app') + expect(stdout).not.toContain('') - expect(stdout).not.toContain(' /_error') - expect(stdout).toContain('○ /') + expect(stdout).not.toContain(' /_error') + expect(stdout).toContain('○ /') + }) }) - }) - describe('Custom Static Error Output', () => { - const appDir = join(fixturesDir, 'with-error-static') + describe('Custom Static Error Output', () => { + const appDir = join(fixturesDir, 'with-error-static') - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) - it('should not specify /404 as lambda when static', async () => { - const { stdout } = await nextBuild(appDir, [], { - stdout: true, + it('should not specify /404 as lambda when static', async () => { + const { stdout } = await nextBuild(appDir, [], { + stdout: true, + }) + expect(stdout).toContain('○ /404') + expect(stdout).not.toContain('λ /_error') + expect(stdout).not.toContain('') }) - expect(stdout).toContain('○ /404') - expect(stdout).not.toContain('λ /_error') - expect(stdout).not.toContain('') }) - }) - describe('With Parallel Routes', () => { - it('should not have duplicate paths that resolve to the same route', async () => { - const appDir = join(fixturesDir, 'with-parallel-routes') + describe('With Parallel Routes', () => { + it('should not have duplicate paths that resolve to the same route', async () => { + const appDir = join(fixturesDir, 'with-parallel-routes') - const { stdout } = await nextBuild(appDir, [], { - stdout: true, - }) + const { stdout } = await nextBuild(appDir, [], { + stdout: true, + }) - expect(stdout.match(/○ \/root-page /g).length).toBe(1) + expect(stdout.match(/○ \/root-page /g).length).toBe(1) + }) }) - }) - }) + } + ) }) diff --git a/test/integration/build-trace-extra-entries-turbo/test/index.test.js b/test/integration/build-trace-extra-entries-turbo/test/index.test.js index 486560cd3d680..90afadc8bcbb4 100644 --- a/test/integration/build-trace-extra-entries-turbo/test/index.test.js +++ b/test/integration/build-trace-extra-entries-turbo/test/index.test.js @@ -7,88 +7,93 @@ import { nextBuild } from 'next-test-utils' const appDir = join(__dirname, '../app') describe('build trace with extra entries', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - it('should build and trace correctly', async () => { - const result = await nextBuild(appDir, undefined, { - cwd: appDir, - stderr: true, - stdout: true, - }) - console.log(result) - expect(result.code).toBe(0) - - const appTrace = await fs.readJSON( - join(appDir, '.next/server/pages/_app.js.nft.json') - ) - const indexTrace = await fs.readJSON( - join(appDir, '.next/server/pages/index.js.nft.json') - ) - const anotherTrace = await fs.readJSON( - join(appDir, '.next/server/pages/another.js.nft.json') - ) - const imageTrace = await fs.readJSON( - join(appDir, '.next/server/pages/image-import.js.nft.json') - ) - const appDirRoute1Trace = await fs.readJSON( - join(appDir, '.next/server/app/route1/route.js.nft.json') - ) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + it('should build and trace correctly', async () => { + const result = await nextBuild(appDir, undefined, { + cwd: appDir, + stderr: true, + stdout: true, + }) + console.log(result) + expect(result.code).toBe(0) - expect( - appDirRoute1Trace.files.some( - (file) => file === '../../../../include-me/hello.txt' + const appTrace = await fs.readJSON( + join(appDir, '.next/server/pages/_app.js.nft.json') + ) + const indexTrace = await fs.readJSON( + join(appDir, '.next/server/pages/index.js.nft.json') + ) + const anotherTrace = await fs.readJSON( + join(appDir, '.next/server/pages/another.js.nft.json') + ) + const imageTrace = await fs.readJSON( + join(appDir, '.next/server/pages/image-import.js.nft.json') ) - ).toBe(true) - expect( - appDirRoute1Trace.files.some( - (file) => file === '../../../../include-me/second.txt' + const appDirRoute1Trace = await fs.readJSON( + join(appDir, '.next/server/app/route1/route.js.nft.json') ) - ).toBe(true) - expect( - appDirRoute1Trace.files.some((file) => file.includes('exclude-me')) - ).toBe(false) - const tracedFiles = [ - ...appTrace.files, - ...indexTrace.files, - ...anotherTrace.files, - ...imageTrace.files, - ] + expect( + appDirRoute1Trace.files.some( + (file) => file === '../../../../include-me/hello.txt' + ) + ).toBe(true) + expect( + appDirRoute1Trace.files.some( + (file) => file === '../../../../include-me/second.txt' + ) + ).toBe(true) + expect( + appDirRoute1Trace.files.some((file) => file.includes('exclude-me')) + ).toBe(false) - expect(tracedFiles.some((file) => file.endsWith('hello.json'))).toBe(true) - expect( - tracedFiles.some((file) => file.includes('some-cms/index.js')) - ).toBe(true) - expect( - tracedFiles.some((file) => file === '../../../include-me/hello.txt') - ).toBe(true) - expect( - tracedFiles.some((file) => file === '../../../include-me/second.txt') - ).toBe(true) - expect(indexTrace.files.some((file) => file.includes('exclude-me'))).toBe( - false - ) + const tracedFiles = [ + ...appTrace.files, + ...indexTrace.files, + ...anotherTrace.files, + ...imageTrace.files, + ] - expect( - tracedFiles.some((file) => - file.includes('nested-structure/constants/package.json') + expect(tracedFiles.some((file) => file.endsWith('hello.json'))).toBe( + true ) - ).toBe(true) - expect( - tracedFiles.some((file) => - file.includes('nested-structure/package.json') - ) - ).toBe(true) - expect( - tracedFiles.some((file) => - file.includes('nested-structure/dist/constants.js') - ) - ).toBe(true) - expect( - tracedFiles.some((file) => file.includes('public/another.jpg')) - ).toBe(true) - expect(tracedFiles.some((file) => file.includes('public/test.jpg'))).toBe( - false - ) - }) - }) + expect( + tracedFiles.some((file) => file.includes('some-cms/index.js')) + ).toBe(true) + expect( + tracedFiles.some((file) => file === '../../../include-me/hello.txt') + ).toBe(true) + expect( + tracedFiles.some((file) => file === '../../../include-me/second.txt') + ).toBe(true) + expect( + indexTrace.files.some((file) => file.includes('exclude-me')) + ).toBe(false) + + expect( + tracedFiles.some((file) => + file.includes('nested-structure/constants/package.json') + ) + ).toBe(true) + expect( + tracedFiles.some((file) => + file.includes('nested-structure/package.json') + ) + ).toBe(true) + expect( + tracedFiles.some((file) => + file.includes('nested-structure/dist/constants.js') + ) + ).toBe(true) + expect( + tracedFiles.some((file) => file.includes('public/another.jpg')) + ).toBe(true) + expect( + tracedFiles.some((file) => file.includes('public/test.jpg')) + ).toBe(false) + }) + } + ) }) diff --git a/test/integration/build-trace-extra-entries/test/index.test.js b/test/integration/build-trace-extra-entries/test/index.test.js index f4e1a7cb7e6dd..e2b3e79c1b524 100644 --- a/test/integration/build-trace-extra-entries/test/index.test.js +++ b/test/integration/build-trace-extra-entries/test/index.test.js @@ -7,115 +7,118 @@ import { nextBuild } from 'next-test-utils' const appDir = join(__dirname, '../app') describe('build trace with extra entries', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - it('should build and trace correctly', async () => { - const result = await nextBuild(appDir, undefined, { - cwd: appDir, - stderr: true, - stdout: true, - }) - console.log(result) - expect(result.code).toBe(0) - - const appTrace = await fs.readJSON( - join(appDir, '.next/server/pages/_app.js.nft.json') - ) - const indexTrace = await fs.readJSON( - join(appDir, '.next/server/pages/index.js.nft.json') - ) - const anotherTrace = await fs.readJSON( - join(appDir, '.next/server/pages/another.js.nft.json') - ) - const imageTrace = await fs.readJSON( - join(appDir, '.next/server/pages/image-import.js.nft.json') - ) - const appDirRoute1Trace = await fs.readJSON( - join(appDir, '.next/server/app/route1/route.js.nft.json') - ) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + it('should build and trace correctly', async () => { + const result = await nextBuild(appDir, undefined, { + cwd: appDir, + stderr: true, + stdout: true, + }) + console.log(result) + expect(result.code).toBe(0) - expect( - appDirRoute1Trace.files.some( - (file) => file === '../../../../include-me/hello.txt' + const appTrace = await fs.readJSON( + join(appDir, '.next/server/pages/_app.js.nft.json') ) - ).toBe(true) - expect( - appDirRoute1Trace.files.some( - (file) => file === '../../../../include-me/second.txt' + const indexTrace = await fs.readJSON( + join(appDir, '.next/server/pages/index.js.nft.json') ) - ).toBe(true) - expect( - appDirRoute1Trace.files.some((file) => file.includes('exclude-me')) - ).toBe(false) - - expect(appTrace.files.some((file) => file.endsWith('hello.json'))).toBe( - true - ) - - expect( - indexTrace.files.filter( - (file) => file.includes('chunks') && file.endsWith('.js') - ).length - ).toBeGreaterThan( - anotherTrace.files.filter( - (file) => file.includes('chunks') && file.endsWith('.js') - ).length - ) - - expect( - appTrace.files.some((file) => file.endsWith('lib/get-data.js')) - ).toBe(true) - expect( - indexTrace.files.some((file) => file.endsWith('hello.json')) - ).toBeFalsy() - expect( - indexTrace.files.some((file) => file.endsWith('some-dir')) - ).toBeFalsy() - expect( - indexTrace.files.some((file) => - file.endsWith('.dot-folder/another-file.txt') + const anotherTrace = await fs.readJSON( + join(appDir, '.next/server/pages/another.js.nft.json') ) - ).toBe(true) - expect( - indexTrace.files.some((file) => file.endsWith('some-dir/file.txt')) - ).toBe(true) - expect( - indexTrace.files.some((file) => file.includes('some-cms/index.js')) - ).toBe(true) - expect( - indexTrace.files.some( - (file) => file === '../../../include-me/hello.txt' + const imageTrace = await fs.readJSON( + join(appDir, '.next/server/pages/image-import.js.nft.json') ) - ).toBe(true) - expect( - indexTrace.files.some( - (file) => file === '../../../include-me/second.txt' + const appDirRoute1Trace = await fs.readJSON( + join(appDir, '.next/server/app/route1/route.js.nft.json') ) - ).toBe(true) - expect(indexTrace.files.some((file) => file.includes('exclude-me'))).toBe( - false - ) - expect( - anotherTrace.files.some((file) => - file.includes('nested-structure/constants/package.json') - ) - ).toBe(true) - expect( - anotherTrace.files.some((file) => - file.includes('nested-structure/package.json') + expect( + appDirRoute1Trace.files.some( + (file) => file === '../../../../include-me/hello.txt' + ) + ).toBe(true) + expect( + appDirRoute1Trace.files.some( + (file) => file === '../../../../include-me/second.txt' + ) + ).toBe(true) + expect( + appDirRoute1Trace.files.some((file) => file.includes('exclude-me')) + ).toBe(false) + + expect(appTrace.files.some((file) => file.endsWith('hello.json'))).toBe( + true ) - ).toBe(true) - expect( - anotherTrace.files.some((file) => - file.includes('nested-structure/dist/constants.js') + + expect( + indexTrace.files.filter( + (file) => file.includes('chunks') && file.endsWith('.js') + ).length + ).toBeGreaterThan( + anotherTrace.files.filter( + (file) => file.includes('chunks') && file.endsWith('.js') + ).length ) - ).toBe(true) - expect( - imageTrace.files.some((file) => file.includes('public/another.jpg')) - ).toBe(true) - expect( - imageTrace.files.some((file) => file.includes('public/test.jpg')) - ).toBe(false) - }) - }) + + expect( + appTrace.files.some((file) => file.endsWith('lib/get-data.js')) + ).toBe(true) + expect( + indexTrace.files.some((file) => file.endsWith('hello.json')) + ).toBeFalsy() + expect( + indexTrace.files.some((file) => file.endsWith('some-dir')) + ).toBeFalsy() + expect( + indexTrace.files.some((file) => + file.endsWith('.dot-folder/another-file.txt') + ) + ).toBe(true) + expect( + indexTrace.files.some((file) => file.endsWith('some-dir/file.txt')) + ).toBe(true) + expect( + indexTrace.files.some((file) => file.includes('some-cms/index.js')) + ).toBe(true) + expect( + indexTrace.files.some( + (file) => file === '../../../include-me/hello.txt' + ) + ).toBe(true) + expect( + indexTrace.files.some( + (file) => file === '../../../include-me/second.txt' + ) + ).toBe(true) + expect( + indexTrace.files.some((file) => file.includes('exclude-me')) + ).toBe(false) + + expect( + anotherTrace.files.some((file) => + file.includes('nested-structure/constants/package.json') + ) + ).toBe(true) + expect( + anotherTrace.files.some((file) => + file.includes('nested-structure/package.json') + ) + ).toBe(true) + expect( + anotherTrace.files.some((file) => + file.includes('nested-structure/dist/constants.js') + ) + ).toBe(true) + expect( + imageTrace.files.some((file) => file.includes('public/another.jpg')) + ).toBe(true) + expect( + imageTrace.files.some((file) => file.includes('public/test.jpg')) + ).toBe(false) + }) + } + ) }) diff --git a/test/integration/build-warnings/test/index.test.js b/test/integration/build-warnings/test/index.test.js index 8ea63d4207387..c3a54966833b1 100644 --- a/test/integration/build-warnings/test/index.test.js +++ b/test/integration/build-warnings/test/index.test.js @@ -7,85 +7,88 @@ import { join } from 'path' const appDir = join(__dirname, '../') describe('Build warnings', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - it('should not shown warning about minification without any modification', async () => { - const { stderr } = await nextBuild(appDir, undefined, { stderr: true }) - expect(stderr).not.toContain('optimization has been disabled') - }) - - it('should shown warning about minification for minimize', async () => { - const nextConfig = new File(join(appDir, 'next.config.js')) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + it('should not shown warning about minification without any modification', async () => { + const { stderr } = await nextBuild(appDir, undefined, { stderr: true }) + expect(stderr).not.toContain('optimization has been disabled') + }) - await waitFor(500) + it('should shown warning about minification for minimize', async () => { + const nextConfig = new File(join(appDir, 'next.config.js')) - nextConfig.replace('true', 'false') + await waitFor(500) - const { stderr } = await nextBuild(appDir, undefined, { stderr: true }) + nextConfig.replace('true', 'false') - expect(stderr).toContain('optimization has been disabled') + const { stderr } = await nextBuild(appDir, undefined, { stderr: true }) - nextConfig.restore() - }) + expect(stderr).toContain('optimization has been disabled') - it('should shown warning about minification for minimizer', async () => { - const nextConfig = new File(join(appDir, 'next.config.js')) + nextConfig.restore() + }) - await waitFor(500) + it('should shown warning about minification for minimizer', async () => { + const nextConfig = new File(join(appDir, 'next.config.js')) - nextConfig.replace( - 'config.optimization.minimize = true', - 'config.optimization.minimizer = []' - ) + await waitFor(500) - const { stderr } = await nextBuild(appDir, undefined, { stderr: true }) + nextConfig.replace( + 'config.optimization.minimize = true', + 'config.optimization.minimizer = []' + ) - expect(stderr).toContain('optimization has been disabled') + const { stderr } = await nextBuild(appDir, undefined, { stderr: true }) - nextConfig.restore() - }) + expect(stderr).toContain('optimization has been disabled') - it('should not warn about missing cache in non-CI', async () => { - await remove(join(appDir, '.next')) + nextConfig.restore() + }) - const { stdout } = await nextBuild(appDir, undefined, { - stdout: true, - env: { - CI: '', - CIRCLECI: '', - TRAVIS: '', - SYSTEM_TEAMFOUNDATIONCOLLECTIONURI: '', - GITHUB_ACTIONS: '', - GITHUB_EVENT_NAME: '', - }, + it('should not warn about missing cache in non-CI', async () => { + await remove(join(appDir, '.next')) + + const { stdout } = await nextBuild(appDir, undefined, { + stdout: true, + env: { + CI: '', + CIRCLECI: '', + TRAVIS: '', + SYSTEM_TEAMFOUNDATIONCOLLECTIONURI: '', + GITHUB_ACTIONS: '', + GITHUB_EVENT_NAME: '', + }, + }) + expect(stdout).not.toContain('no-cache') }) - expect(stdout).not.toContain('no-cache') - }) - it('should not warn about missing cache on supported platforms', async () => { - await remove(join(appDir, '.next')) + it('should not warn about missing cache on supported platforms', async () => { + await remove(join(appDir, '.next')) - const { stdout } = await nextBuild(appDir, undefined, { - stdout: true, - env: { CI: '1', NOW_BUILDER: '1' }, + const { stdout } = await nextBuild(appDir, undefined, { + stdout: true, + env: { CI: '1', NOW_BUILDER: '1' }, + }) + expect(stdout).not.toContain('no-cache') }) - expect(stdout).not.toContain('no-cache') - }) - - it('should warn about missing cache in CI', async () => { - await remove(join(appDir, '.next')) - let { stdout } = await nextBuild(appDir, undefined, { - stdout: true, - env: { CI: '1' }, + it('should warn about missing cache in CI', async () => { + await remove(join(appDir, '.next')) + + let { stdout } = await nextBuild(appDir, undefined, { + stdout: true, + env: { CI: '1' }, + }) + expect(stdout).toContain('no-cache') + + // Do not warn after cache is present + ;({ stdout } = await nextBuild(appDir, undefined, { + stdout: true, + env: { CI: '1' }, + })) + expect(stdout).not.toContain('no-cache') }) - expect(stdout).toContain('no-cache') - - // Do not warn after cache is present - ;({ stdout } = await nextBuild(appDir, undefined, { - stdout: true, - env: { CI: '1' }, - })) - expect(stdout).not.toContain('no-cache') - }) - }) + } + ) }) diff --git a/test/integration/catches-missing-getStaticProps/test/index.test.js b/test/integration/catches-missing-getStaticProps/test/index.test.js index fbbe018644ca1..65b6889a7fc17 100644 --- a/test/integration/catches-missing-getStaticProps/test/index.test.js +++ b/test/integration/catches-missing-getStaticProps/test/index.test.js @@ -23,12 +23,15 @@ describe('Catches Missing getStaticProps', () => { expect(html).toMatch(errorRegex) }) }) - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - it('should catch it in server build mode', async () => { - const { stderr } = await nextBuild(appDir, [], { - stderr: true, + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + it('should catch it in server build mode', async () => { + const { stderr } = await nextBuild(appDir, [], { + stderr: true, + }) + expect(stderr).toMatch(errorRegex) }) - expect(stderr).toMatch(errorRegex) - }) - }) + } + ) }) diff --git a/test/integration/chunking/test/index.test.js b/test/integration/chunking/test/index.test.js index e7e8aee57a79b..7c36f6454f82c 100644 --- a/test/integration/chunking/test/index.test.js +++ b/test/integration/chunking/test/index.test.js @@ -24,112 +24,117 @@ const existsChunkNamed = (name) => { // Skipped as it uses webpack internals / stats.json. ;(process.env.TURBOPACK ? describe.skip : describe)('Chunking', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - beforeAll(async () => { - try { - // If a previous build has left chunks behind, delete them - const oldChunks = await readdir( - join(appDir, '.next', 'static', 'chunks') - ) - await Promise.all( - oldChunks.map((chunk) => { - return unlink(join(appDir, '.next', 'static', 'chunks', chunk)) - }) - ) - } catch (e) { - // Error here means old chunks don't exist, so we don't need to do anything - } - await nextBuild(appDir, []) - - stats = (await readFile(join(appDir, '.next', 'stats.json'), 'utf8')) - // fixes backslashes in keyNames not being escaped on windows - .replace(/"static\\(.*?":?)/g, (match) => match.replace(/\\/g, '\\\\')) - - stats = JSON.parse(stats) - appPort = await findPort() - app = await nextStart(appDir, appPort) - chunks = await readdir(join(appDir, '.next', 'static', 'chunks')) - }) - - afterAll(() => killApp(app)) - - it('should use all url friendly names', () => { - expect(chunks).toEqual(chunks.map((name) => encodeURIComponent(name))) - }) - - it('should create a framework chunk', () => { - expect(existsChunkNamed('framework')).toBe(true) - }) - - it('should not create a commons chunk', () => { - // This app has no dependency that is required by ALL pages, and should - // therefore not have a commons chunk - expect(existsChunkNamed('commons')).toBe(false) - }) - - it('should not create a lib chunk for react or react-dom', () => { - // These large dependencies would become lib chunks, except that they - // are preemptively moved into the framework chunk. - expect(existsChunkNamed('react|react-dom')).toBe(false) - }) - - it('should not preload the build manifest', async () => { - const html = await renderViaHTTP(appPort, '/') - const $ = cheerio.load(html) - expect( - [].slice - .call($('link[rel="preload"][as="script"]')) - .map((e) => e.attribs.href) - .some((entry) => entry.includes('_buildManifest')) - ).toBe(false) - }) - - it('should execute the build manifest', async () => { - const html = await renderViaHTTP(appPort, '/') - const $ = cheerio.load(html) - expect( - Array.from($('script')) - .map((e) => e.attribs.src) - .some((entry) => entry && entry.includes('_buildManifest')) - ).toBe(true) - }) - - it('should not include more than one instance of react-dom', async () => { - const misplacedReactDom = stats.chunks.some((chunk) => { - if (chunk.names.includes('framework')) { - // disregard react-dom in framework--it's supposed to be there - return false + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + beforeAll(async () => { + try { + // If a previous build has left chunks behind, delete them + const oldChunks = await readdir( + join(appDir, '.next', 'static', 'chunks') + ) + await Promise.all( + oldChunks.map((chunk) => { + return unlink(join(appDir, '.next', 'static', 'chunks', chunk)) + }) + ) + } catch (e) { + // Error here means old chunks don't exist, so we don't need to do anything } - return chunk.modules.some((module) => { - return /react-dom/.test(module.name) - }) + await nextBuild(appDir, []) + + stats = (await readFile(join(appDir, '.next', 'stats.json'), 'utf8')) + // fixes backslashes in keyNames not being escaped on windows + .replace(/"static\\(.*?":?)/g, (match) => + match.replace(/\\/g, '\\\\') + ) + + stats = JSON.parse(stats) + appPort = await findPort() + app = await nextStart(appDir, appPort) + chunks = await readdir(join(appDir, '.next', 'static', 'chunks')) + }) + + afterAll(() => killApp(app)) + + it('should use all url friendly names', () => { + expect(chunks).toEqual(chunks.map((name) => encodeURIComponent(name))) + }) + + it('should create a framework chunk', () => { + expect(existsChunkNamed('framework')).toBe(true) + }) + + it('should not create a commons chunk', () => { + // This app has no dependency that is required by ALL pages, and should + // therefore not have a commons chunk + expect(existsChunkNamed('commons')).toBe(false) + }) + + it('should not create a lib chunk for react or react-dom', () => { + // These large dependencies would become lib chunks, except that they + // are preemptively moved into the framework chunk. + expect(existsChunkNamed('react|react-dom')).toBe(false) }) - expect(misplacedReactDom).toBe(false) - }) - describe('Serving', () => { - it('should hydrate with aggressive chunking', async () => { - const browser = await webdriver(appPort, '/page2') - const text = await browser.elementByCss('#padded-str').text() + it('should not preload the build manifest', async () => { + const html = await renderViaHTTP(appPort, '/') + const $ = cheerio.load(html) + expect( + [].slice + .call($('link[rel="preload"][as="script"]')) + .map((e) => e.attribs.href) + .some((entry) => entry.includes('_buildManifest')) + ).toBe(false) + }) - expect(text).toBe('__rad__') + it('should execute the build manifest', async () => { + const html = await renderViaHTTP(appPort, '/') + const $ = cheerio.load(html) + expect( + Array.from($('script')) + .map((e) => e.attribs.src) + .some((entry) => entry && entry.includes('_buildManifest')) + ).toBe(true) + }) - await browser.close() + it('should not include more than one instance of react-dom', async () => { + const misplacedReactDom = stats.chunks.some((chunk) => { + if (chunk.names.includes('framework')) { + // disregard react-dom in framework--it's supposed to be there + return false + } + return chunk.modules.some((module) => { + return /react-dom/.test(module.name) + }) + }) + expect(misplacedReactDom).toBe(false) }) - it('should load chunks when navigating', async () => { - const browser = await webdriver(appPort, '/page3') - const text = await browser - .elementByCss('#page2-link') - .click() - .waitForElementByCss('#padded-str') - .elementByCss('#padded-str') - .text() + describe('Serving', () => { + it('should hydrate with aggressive chunking', async () => { + const browser = await webdriver(appPort, '/page2') + const text = await browser.elementByCss('#padded-str').text() - expect(text).toBe('__rad__') + expect(text).toBe('__rad__') - await browser.close() + await browser.close() + }) + + it('should load chunks when navigating', async () => { + const browser = await webdriver(appPort, '/page3') + const text = await browser + .elementByCss('#page2-link') + .click() + .waitForElementByCss('#padded-str') + .elementByCss('#padded-str') + .text() + + expect(text).toBe('__rad__') + + await browser.close() + }) }) - }) - }) + } + ) }) diff --git a/test/integration/clean-distdir/test/index.test.js b/test/integration/clean-distdir/test/index.test.js index 8c2bb8b623f30..7859587df932c 100644 --- a/test/integration/clean-distdir/test/index.test.js +++ b/test/integration/clean-distdir/test/index.test.js @@ -29,28 +29,31 @@ const runTests = () => { } describe('Cleaning distDir', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - runTests() - - describe('disabled write', () => { - beforeAll(async () => { - nextConfigContent = await fs.readFile(nextConfig, 'utf8') - await fs.writeFile( - nextConfig, - ` + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + runTests() + + describe('disabled write', () => { + beforeAll(async () => { + nextConfigContent = await fs.readFile(nextConfig, 'utf8') + await fs.writeFile( + nextConfig, + ` module.exports = { cleanDistDir: false } ` - ) + ) + }) + afterAll(async () => { + await fs.writeFile(nextConfig, nextConfigContent) + }) + + it('should not clean up .next before build start', async () => { + await checkFileWrite(true) + }) }) - afterAll(async () => { - await fs.writeFile(nextConfig, nextConfigContent) - }) - - it('should not clean up .next before build start', async () => { - await checkFileWrite(true) - }) - }) - }) + } + ) }) diff --git a/test/integration/cli/test/index.test.js b/test/integration/cli/test/index.test.js index 16efa3ca70d44..cd9f74d18402e 100644 --- a/test/integration/cli/test/index.test.js +++ b/test/integration/cli/test/index.test.js @@ -80,279 +80,286 @@ const testExitSignal = async ( } describe('CLI Usage', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - describe('start', () => { - test('should exit when SIGINT is signalled', async () => { - require('console').log('before build') - await fs.remove(join(dirBasic, '.next')) - await nextBuild(dirBasic, undefined, { - onStdout(msg) { - console.log(msg) - }, - onStderr(msg) { - console.log(msg) - }, + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + describe('start', () => { + test('should exit when SIGINT is signalled', async () => { + require('console').log('before build') + await fs.remove(join(dirBasic, '.next')) + await nextBuild(dirBasic, undefined, { + onStdout(msg) { + console.log(msg) + }, + onStderr(msg) { + console.log(msg) + }, + }) + require('console').log('build finished') + + const port = await findPort() + await testExitSignal( + 'SIGINT', + ['start', dirBasic, '-p', port], + /- Local:/ + ) }) - require('console').log('build finished') - - const port = await findPort() - await testExitSignal( - 'SIGINT', - ['start', dirBasic, '-p', port], - /- Local:/ - ) - }) - test('should exit when SIGTERM is signalled', async () => { - await fs.remove(join(dirBasic, '.next')) - await nextBuild(dirBasic, undefined, { - onStdout(msg) { - console.log(msg) - }, - onStderr(msg) { - console.log(msg) - }, + test('should exit when SIGTERM is signalled', async () => { + await fs.remove(join(dirBasic, '.next')) + await nextBuild(dirBasic, undefined, { + onStdout(msg) { + console.log(msg) + }, + onStderr(msg) { + console.log(msg) + }, + }) + const port = await findPort() + await testExitSignal( + 'SIGTERM', + ['start', dirBasic, '-p', port], + /- Local:/ + ) }) - const port = await findPort() - await testExitSignal( - 'SIGTERM', - ['start', dirBasic, '-p', port], - /- Local:/ - ) - }) - test('--help', async () => { - const help = await runNextCommand(['start', '--help'], { - stdout: true, + test('--help', async () => { + const help = await runNextCommand(['start', '--help'], { + stdout: true, + }) + expect(help.stdout).toMatch(/Starts Next.js in production mode/) }) - expect(help.stdout).toMatch(/Starts Next.js in production mode/) - }) - test('-h', async () => { - const help = await runNextCommand(['start', '-h'], { - stdout: true, + test('-h', async () => { + const help = await runNextCommand(['start', '-h'], { + stdout: true, + }) + expect(help.stdout).toMatch(/Starts Next.js in production mode/) }) - expect(help.stdout).toMatch(/Starts Next.js in production mode/) - }) - - test('should format IPv6 addresses correctly', async () => { - await nextBuild(dirBasic) - const port = await findPort() - let stdout = '' - const app = await runNextCommandDev( - ['start', dirBasic, '--hostname', '::', '--port', port], - undefined, - { - nextStart: true, - onStdout(msg) { - stdout += msg - }, + test('should format IPv6 addresses correctly', async () => { + await nextBuild(dirBasic) + const port = await findPort() + + let stdout = '' + const app = await runNextCommandDev( + ['start', dirBasic, '--hostname', '::', '--port', port], + undefined, + { + nextStart: true, + onStdout(msg) { + stdout += msg + }, + } + ) + + try { + await check(() => { + // Only display when hostname is provided + expect(stdout).toMatch( + new RegExp(`Network:\\s*http://\\[::\\]:${port}`) + ) + expect(stdout).toMatch(new RegExp(`http://\\[::1\\]:${port}`)) + }) + } finally { + await killApp(app) } - ) + }) - try { - await check(() => { - // Only display when hostname is provided - expect(stdout).toMatch( - new RegExp(`Network:\\s*http://\\[::\\]:${port}`) - ) - expect(stdout).toMatch(new RegExp(`http://\\[::1\\]:${port}`)) + test('should warn when unknown argument provided', async () => { + const { stderr } = await runNextCommand(['start', '--random'], { + stderr: true, }) - } finally { - await killApp(app) - } - }) - - test('should warn when unknown argument provided', async () => { - const { stderr } = await runNextCommand(['start', '--random'], { - stderr: true, + expect(stderr).toEqual(`error: unknown option '--random'\n`) }) - expect(stderr).toEqual(`error: unknown option '--random'\n`) - }) - test('should not throw UnhandledPromiseRejectionWarning', async () => { - const { stderr } = await runNextCommand(['start', '--random'], { - stderr: true, + test('should not throw UnhandledPromiseRejectionWarning', async () => { + const { stderr } = await runNextCommand(['start', '--random'], { + stderr: true, + }) + expect(stderr).not.toContain('UnhandledPromiseRejectionWarning') }) - expect(stderr).not.toContain('UnhandledPromiseRejectionWarning') - }) - test('duplicate sass deps', async () => { - const port = await findPort() + test('duplicate sass deps', async () => { + const port = await findPort() - let stderr = '' - let instance = await launchApp(dirDuplicateSass, port, { - stderr: true, - onStderr(msg) { - stderr += msg - }, - }) - - try { - await check(() => stderr, /both `sass` and `node-sass` installed/) - } finally { - await killApp(instance).catch(() => {}) - } - }) + let stderr = '' + let instance = await launchApp(dirDuplicateSass, port, { + stderr: true, + onStderr(msg) { + stderr += msg + }, + }) - test('invalid directory', async () => { - const output = await runNextCommand(['start', 'non-existent'], { - stderr: true, + try { + await check(() => stderr, /both `sass` and `node-sass` installed/) + } finally { + await killApp(instance).catch(() => {}) + } }) - expect(output.stderr).toContain( - 'Invalid project directory provided, no such directory' - ) - }) - test('--keepAliveTimeout string arg', async () => { - const { stderr } = await runNextCommand( - ['start', '--keepAliveTimeout', 'string'], - { + test('invalid directory', async () => { + const output = await runNextCommand(['start', 'non-existent'], { stderr: true, - } - ) - expect(stderr).toContain( - `error: option '--keepAliveTimeout ' argument 'string' is invalid. 'string' is not a non-negative number.` - ) - }) + }) + expect(output.stderr).toContain( + 'Invalid project directory provided, no such directory' + ) + }) - test('--keepAliveTimeout negative number', async () => { - const { stderr } = await runNextCommand( - ['start', '--keepAliveTimeout=-100'], - { - stderr: true, - } - ) - expect(stderr).toContain( - `error: option '--keepAliveTimeout ' argument '-100' is invalid. '-100' is not a non-negative number.` - ) - }) + test('--keepAliveTimeout string arg', async () => { + const { stderr } = await runNextCommand( + ['start', '--keepAliveTimeout', 'string'], + { + stderr: true, + } + ) + expect(stderr).toContain( + `error: option '--keepAliveTimeout ' argument 'string' is invalid. 'string' is not a non-negative number.` + ) + }) - test('--keepAliveTimeout Infinity', async () => { - const { stderr } = await runNextCommand( - ['start', '--keepAliveTimeout', 'Infinity'], - { - stderr: true, - } - ) - expect(stderr).toContain( - `error: option '--keepAliveTimeout ' argument 'Infinity' is invalid. 'Infinity' is not a non-negative number.` - ) - }) + test('--keepAliveTimeout negative number', async () => { + const { stderr } = await runNextCommand( + ['start', '--keepAliveTimeout=-100'], + { + stderr: true, + } + ) + expect(stderr).toContain( + `error: option '--keepAliveTimeout ' argument '-100' is invalid. '-100' is not a non-negative number.` + ) + }) - test('--keepAliveTimeout happy path', async () => { - const { stderr } = await runNextCommand( - ['start', '--keepAliveTimeout', '100'], - { - stderr: true, - } - ) - expect(stderr).not.toContain( - `error: option '--keepAliveTimeout ' argument '100' is invalid. '100' is not a non-negative number.` - ) - }) + test('--keepAliveTimeout Infinity', async () => { + const { stderr } = await runNextCommand( + ['start', '--keepAliveTimeout', 'Infinity'], + { + stderr: true, + } + ) + expect(stderr).toContain( + `error: option '--keepAliveTimeout ' argument 'Infinity' is invalid. 'Infinity' is not a non-negative number.` + ) + }) - test('should not start on a port out of range', async () => { - const invalidPort = '300001' - const { stderr } = await runNextCommand( - ['start', '--port', invalidPort], - { - stderr: true, - } - ) + test('--keepAliveTimeout happy path', async () => { + const { stderr } = await runNextCommand( + ['start', '--keepAliveTimeout', '100'], + { + stderr: true, + } + ) + expect(stderr).not.toContain( + `error: option '--keepAliveTimeout ' argument '100' is invalid. '100' is not a non-negative number.` + ) + }) - expect(stderr).toContain(`options.port should be >= 0 and < 65536.`) - }) + test('should not start on a port out of range', async () => { + const invalidPort = '300001' + const { stderr } = await runNextCommand( + ['start', '--port', invalidPort], + { + stderr: true, + } + ) - test('should not start on a reserved port', async () => { - const reservedPort = '4045' - const { stderr } = await runNextCommand( - ['start', '--port', reservedPort], - { - stderr: true, - } - ) + expect(stderr).toContain(`options.port should be >= 0 and < 65536.`) + }) - expect(stderr).toContain( - `Bad port: "${reservedPort}" is reserved for npp` - ) + test('should not start on a reserved port', async () => { + const reservedPort = '4045' + const { stderr } = await runNextCommand( + ['start', '--port', reservedPort], + { + stderr: true, + } + ) + + expect(stderr).toContain( + `Bad port: "${reservedPort}" is reserved for npp` + ) + }) }) - }) - describe('telemetry', () => { - test('--help', async () => { - const help = await runNextCommand(['telemetry', '--help'], { - stdout: true, + describe('telemetry', () => { + test('--help', async () => { + const help = await runNextCommand(['telemetry', '--help'], { + stdout: true, + }) + expect(help.stdout).toMatch( + /Allows you to enable or disable Next\.js'/ + ) }) - expect(help.stdout).toMatch(/Allows you to enable or disable Next\.js'/) - }) - test('-h', async () => { - const help = await runNextCommand(['telemetry', '-h'], { - stdout: true, + test('-h', async () => { + const help = await runNextCommand(['telemetry', '-h'], { + stdout: true, + }) + expect(help.stdout).toMatch( + /Allows you to enable or disable Next\.js'/ + ) }) - expect(help.stdout).toMatch(/Allows you to enable or disable Next\.js'/) - }) - test('should warn when unknown argument provided', async () => { - const { stderr } = await runNextCommand(['telemetry', '--random'], { - stderr: true, + test('should warn when unknown argument provided', async () => { + const { stderr } = await runNextCommand(['telemetry', '--random'], { + stderr: true, + }) + expect(stderr).toEqual(`error: unknown option '--random'\n`) }) - expect(stderr).toEqual(`error: unknown option '--random'\n`) - }) - test('should not throw UnhandledPromiseRejectionWarning', async () => { - const { stderr } = await runNextCommand(['telemetry', '--random'], { - stderr: true, + test('should not throw UnhandledPromiseRejectionWarning', async () => { + const { stderr } = await runNextCommand(['telemetry', '--random'], { + stderr: true, + }) + expect(stderr).not.toContain('UnhandledPromiseRejectionWarning') }) - expect(stderr).not.toContain('UnhandledPromiseRejectionWarning') }) - }) - describe('build', () => { - test('--help', async () => { - const help = await runNextCommand(['build', '--help'], { - stdout: true, + describe('build', () => { + test('--help', async () => { + const help = await runNextCommand(['build', '--help'], { + stdout: true, + }) + expect(help.stdout).toMatch(/Creates an optimized production build/) }) - expect(help.stdout).toMatch(/Creates an optimized production build/) - }) - test('-h', async () => { - const help = await runNextCommand(['build', '-h'], { - stdout: true, + test('-h', async () => { + const help = await runNextCommand(['build', '-h'], { + stdout: true, + }) + expect(help.stdout).toMatch(/Creates an optimized production build/) }) - expect(help.stdout).toMatch(/Creates an optimized production build/) - }) - test('should warn when unknown argument provided', async () => { - const { stderr } = await runNextCommand(['build', '--random'], { - stderr: true, + test('should warn when unknown argument provided', async () => { + const { stderr } = await runNextCommand(['build', '--random'], { + stderr: true, + }) + expect(stderr).toEqual(`error: unknown option '--random'\n`) }) - expect(stderr).toEqual(`error: unknown option '--random'\n`) - }) - test('should not throw UnhandledPromiseRejectionWarning', async () => { - const { stderr } = await runNextCommand(['build', '--random'], { - stderr: true, + test('should not throw UnhandledPromiseRejectionWarning', async () => { + const { stderr } = await runNextCommand(['build', '--random'], { + stderr: true, + }) + expect(stderr).not.toContain('UnhandledPromiseRejectionWarning') }) - expect(stderr).not.toContain('UnhandledPromiseRejectionWarning') - }) - test('should exit when SIGINT is signalled', async () => { - await testExitSignal('SIGINT', ['build', dirBasic]) - }) + test('should exit when SIGINT is signalled', async () => { + await testExitSignal('SIGINT', ['build', dirBasic]) + }) - test('should exit when SIGTERM is signalled', async () => { - await testExitSignal('SIGTERM', ['build', dirBasic]) - }) + test('should exit when SIGTERM is signalled', async () => { + await testExitSignal('SIGTERM', ['build', dirBasic]) + }) - test('invalid directory', async () => { - const output = await runNextCommand(['build', 'non-existent'], { - stderr: true, + test('invalid directory', async () => { + const output = await runNextCommand(['build', 'non-existent'], { + stderr: true, + }) + expect(output.stderr).toContain( + 'Invalid project directory provided, no such directory' + ) }) - expect(output.stderr).toContain( - 'Invalid project directory provided, no such directory' - ) }) - }) - }) + } + ) describe('no command', () => { test('--help', async () => { diff --git a/test/integration/client-404/test/index.test.js b/test/integration/client-404/test/index.test.js index 6659846053cc4..291fbe2b47bb2 100644 --- a/test/integration/client-404/test/index.test.js +++ b/test/integration/client-404/test/index.test.js @@ -35,23 +35,26 @@ describe('Client 404', () => { runTests() }) - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - beforeAll(async () => { - await nextBuild(appDir) - context.appPort = await findPort() - context.server = await nextStart(appDir, context.appPort) - - const manifest = await getBuildManifest(appDir) - const files = manifest.pages['/missing'].filter((d) => - /static[\\/]chunks[\\/]pages/.test(d) - ) - if (files.length < 1) { - throw new Error('oops!') - } - await Promise.all(files.map((f) => fs.remove(join(appDir, '.next', f)))) - }) - afterAll(() => killApp(context.server)) - - runTests(true) - }) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + beforeAll(async () => { + await nextBuild(appDir) + context.appPort = await findPort() + context.server = await nextStart(appDir, context.appPort) + + const manifest = await getBuildManifest(appDir) + const files = manifest.pages['/missing'].filter((d) => + /static[\\/]chunks[\\/]pages/.test(d) + ) + if (files.length < 1) { + throw new Error('oops!') + } + await Promise.all(files.map((f) => fs.remove(join(appDir, '.next', f)))) + }) + afterAll(() => killApp(context.server)) + + runTests(true) + } + ) }) diff --git a/test/integration/client-shallow-routing/test/index.test.js b/test/integration/client-shallow-routing/test/index.test.js index 39cefb994d5b8..6e662a6639e08 100644 --- a/test/integration/client-shallow-routing/test/index.test.js +++ b/test/integration/client-shallow-routing/test/index.test.js @@ -97,14 +97,17 @@ describe('Client Shallow Routing', () => { runTests() }) - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - beforeAll(async () => { - await nextBuild(appDir) - appPort = await findPort() - app = await nextStart(appDir, appPort) - }) - afterAll(() => killApp(app)) - - runTests() - }) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + beforeAll(async () => { + await nextBuild(appDir) + appPort = await findPort() + app = await nextStart(appDir, appPort) + }) + afterAll(() => killApp(app)) + + runTests() + } + ) }) diff --git a/test/integration/config-experimental-warning/test/index.test.js b/test/integration/config-experimental-warning/test/index.test.js index a47ec86e28c6e..5cc95346eb601 100644 --- a/test/integration/config-experimental-warning/test/index.test.js +++ b/test/integration/config-experimental-warning/test/index.test.js @@ -130,9 +130,11 @@ describe('Config Experimental Warning', () => { expect(stdout).toContain(' · workerThreads') expect(stdout).toContain(' · scrollRestoration') }) - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - it('should not show next app info in next start', async () => { - configFile.write(` + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + it('should not show next app info in next start', async () => { + configFile.write(` module.exports = { experimental: { workerThreads: true, @@ -143,19 +145,19 @@ describe('Config Experimental Warning', () => { } `) - await collectStdoutFromBuild(appDir) - const port = await findPort() - let stdout = '' - app = await nextStart(appDir, port, { - onStdout(msg) { - stdout += msg - }, + await collectStdoutFromBuild(appDir) + const port = await findPort() + let stdout = '' + app = await nextStart(appDir, port, { + onStdout(msg) { + stdout += msg + }, + }) + expect(stdout).not.toMatch(experimentalHeader) }) - expect(stdout).not.toMatch(experimentalHeader) - }) - it('should show next app info with all experimental features in next build', async () => { - configFile.write(` + it('should show next app info with all experimental features in next build', async () => { + configFile.write(` module.exports = { experimental: { workerThreads: true, @@ -165,16 +167,16 @@ describe('Config Experimental Warning', () => { } } `) - const stdout = await collectStdoutFromBuild(appDir) - expect(stdout).toMatch(experimentalHeader) - expect(stdout).toMatch(' · cpus') - expect(stdout).toMatch(' · workerThreads') - expect(stdout).toMatch(' · scrollRestoration') - expect(stdout).toMatch(' · instrumentationHook') - }) - - it('should show unrecognized experimental features in warning but not in start log experiments section', async () => { - configFile.write(` + const stdout = await collectStdoutFromBuild(appDir) + expect(stdout).toMatch(experimentalHeader) + expect(stdout).toMatch(' · cpus') + expect(stdout).toMatch(' · workerThreads') + expect(stdout).toMatch(' · scrollRestoration') + expect(stdout).toMatch(' · instrumentationHook') + }) + + it('should show unrecognized experimental features in warning but not in start log experiments section', async () => { + configFile.write(` module.exports = { experimental: { appDir: true @@ -182,27 +184,28 @@ describe('Config Experimental Warning', () => { } `) - await collectStdoutFromBuild(appDir) - const port = await findPort() - let stdout = '' - let stderr = '' - app = await nextStart(appDir, port, { - onStdout(msg) { - stdout += msg - }, - onStderr(msg) { - stderr += msg - }, - }) - - await check(() => { - const cliOutput = stripAnsi(stdout) - const cliOutputErr = stripAnsi(stderr) - expect(cliOutput).not.toContain(experimentalHeader) - expect(cliOutputErr).toContain( - `Unrecognized key(s) in object: 'appDir' at "experimental"` - ) + await collectStdoutFromBuild(appDir) + const port = await findPort() + let stdout = '' + let stderr = '' + app = await nextStart(appDir, port, { + onStdout(msg) { + stdout += msg + }, + onStderr(msg) { + stderr += msg + }, + }) + + await check(() => { + const cliOutput = stripAnsi(stdout) + const cliOutputErr = stripAnsi(stderr) + expect(cliOutput).not.toContain(experimentalHeader) + expect(cliOutputErr).toContain( + `Unrecognized key(s) in object: 'appDir' at "experimental"` + ) + }) }) - }) - }) + } + ) }) diff --git a/test/integration/config-promise-error/test/index.test.js b/test/integration/config-promise-error/test/index.test.js index ae979a8e30f4b..86c128dd120bc 100644 --- a/test/integration/config-promise-error/test/index.test.js +++ b/test/integration/config-promise-error/test/index.test.js @@ -7,13 +7,15 @@ import { nextBuild } from 'next-test-utils' const appDir = join(__dirname, '..') describe('Promise in next config', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - afterEach(() => fs.remove(join(appDir, 'next.config.js'))) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + afterEach(() => fs.remove(join(appDir, 'next.config.js'))) - it('should warn when a promise is returned on webpack', async () => { - fs.writeFile( - join(appDir, 'next.config.js'), - ` + it('should warn when a promise is returned on webpack', async () => { + fs.writeFile( + join(appDir, 'next.config.js'), + ` module.exports = (phase, { isServer }) => { return { webpack: async (config) => { @@ -22,15 +24,16 @@ describe('Promise in next config', () => { } } ` - ) + ) - const { stderr, stdout } = await nextBuild(appDir, undefined, { - stderr: true, - stdout: true, + const { stderr, stdout } = await nextBuild(appDir, undefined, { + stderr: true, + stdout: true, + }) + expect(stderr + stdout).toMatch( + /> Promise returned in next config\. https:\/\// + ) }) - expect(stderr + stdout).toMatch( - /> Promise returned in next config\. https:\/\// - ) - }) - }) + } + ) }) diff --git a/test/integration/config-syntax-error/test/index.test.js b/test/integration/config-syntax-error/test/index.test.js index b82db8b657f96..6a02b3bd43ea4 100644 --- a/test/integration/config-syntax-error/test/index.test.js +++ b/test/integration/config-syntax-error/test/index.test.js @@ -8,46 +8,49 @@ const nextConfigJS = join(appDir, 'next.config.js') const nextConfigMJS = join(appDir, 'next.config.mjs') describe('Invalid config syntax', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - it('should error when next.config.js contains syntax error', async () => { - await fs.writeFile( - nextConfigJS, - ` + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + it('should error when next.config.js contains syntax error', async () => { + await fs.writeFile( + nextConfigJS, + ` module.exports = { reactStrictMode: true,, } ` - ) - const { stderr } = await nextBuild(appDir, undefined, { - stderr: true, - }) - await fs.remove(nextConfigJS) + ) + const { stderr } = await nextBuild(appDir, undefined, { + stderr: true, + }) + await fs.remove(nextConfigJS) - expect(stderr).toContain( - 'Failed to load next.config.js, see more info here https://nextjs.org/docs/messages/next-config-error' - ) - expect(stderr).toContain('SyntaxError') - }) + expect(stderr).toContain( + 'Failed to load next.config.js, see more info here https://nextjs.org/docs/messages/next-config-error' + ) + expect(stderr).toContain('SyntaxError') + }) - it('should error when next.config.mjs contains syntax error', async () => { - await fs.writeFile( - nextConfigMJS, - ` + it('should error when next.config.mjs contains syntax error', async () => { + await fs.writeFile( + nextConfigMJS, + ` const config = { reactStrictMode: true,, } export default config ` - ) - const { stderr } = await nextBuild(appDir, undefined, { - stderr: true, - }) - await fs.remove(nextConfigMJS) + ) + const { stderr } = await nextBuild(appDir, undefined, { + stderr: true, + }) + await fs.remove(nextConfigMJS) - expect(stderr).toContain( - 'Failed to load next.config.mjs, see more info here https://nextjs.org/docs/messages/next-config-error' - ) - expect(stderr).toContain('SyntaxError') - }) - }) + expect(stderr).toContain( + 'Failed to load next.config.mjs, see more info here https://nextjs.org/docs/messages/next-config-error' + ) + expect(stderr).toContain('SyntaxError') + }) + } + ) }) diff --git a/test/integration/config-validation/test/index.test.ts b/test/integration/config-validation/test/index.test.ts index 7e4e003242dbd..78ee328551ef7 100644 --- a/test/integration/config-validation/test/index.test.ts +++ b/test/integration/config-validation/test/index.test.ts @@ -5,11 +5,13 @@ import fs from 'fs-extra' const nextConfigPath = path.join(__dirname, '../next.config.js') describe('next.config.js validation', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - it.each([ - { - name: 'invalid config types', - configContent: ` + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + it.each([ + { + name: 'invalid config types', + configContent: ` module.exports = { swcMinify: 'hello', rewrites: true, @@ -18,15 +20,15 @@ describe('next.config.js validation', () => { } } `, - outputs: [ - `received 'something' at "images.loader"`, - 'Expected function, received boolean at "rewrites"', - 'Expected boolean, received string at "swcMinify"', - ], - }, - { - name: 'unexpected config fields', - configContent: ` + outputs: [ + `received 'something' at "images.loader"`, + 'Expected function, received boolean at "rewrites"', + 'Expected boolean, received string at "swcMinify"', + ], + }, + { + name: 'unexpected config fields', + configContent: ` module.exports = { nonExistent: true, experimental: { @@ -34,29 +36,33 @@ describe('next.config.js validation', () => { } } `, - outputs: [ - `Unrecognized key(s) in object: 'nonExistent'`, - `Unrecognized key(s) in object: 'anotherNonExistent' at "experimental"`, - ], - }, - ])( - 'it should validate correctly for $name', - async ({ outputs, configContent }) => { - await fs.writeFile(nextConfigPath, configContent) - const result = await nextBuild(path.join(__dirname, '../'), undefined, { - stderr: true, - stdout: true, - }) - await fs.remove(nextConfigPath) + outputs: [ + `Unrecognized key(s) in object: 'nonExistent'`, + `Unrecognized key(s) in object: 'anotherNonExistent' at "experimental"`, + ], + }, + ])( + 'it should validate correctly for $name', + async ({ outputs, configContent }) => { + await fs.writeFile(nextConfigPath, configContent) + const result = await nextBuild( + path.join(__dirname, '../'), + undefined, + { + stderr: true, + stdout: true, + } + ) + await fs.remove(nextConfigPath) - for (const output of outputs) { - expect(result.stdout + result.stderr).toContain(output) + for (const output of outputs) { + expect(result.stdout + result.stderr).toContain(output) + } } - } - ) + ) - it('should allow undefined environment variables', async () => { - const configContent = ` + it('should allow undefined environment variables', async () => { + const configContent = ` module.exports = { env: { FOO: 'bar', @@ -65,17 +71,18 @@ describe('next.config.js validation', () => { } ` - await fs.writeFile(nextConfigPath, configContent) - const result = await nextBuild(path.join(__dirname, '../'), undefined, { - stderr: true, - stdout: true, - }) + await fs.writeFile(nextConfigPath, configContent) + const result = await nextBuild(path.join(__dirname, '../'), undefined, { + stderr: true, + stdout: true, + }) - await fs.remove(nextConfigPath) + await fs.remove(nextConfigPath) - expect(result.stdout + result.stderr).not.toContain( - '"env.QUX" is missing' - ) - }) - }) + expect(result.stdout + result.stderr).not.toContain( + '"env.QUX" is missing' + ) + }) + } + ) }) diff --git a/test/integration/conflicting-public-file-page/test/index.test.js b/test/integration/conflicting-public-file-page/test/index.test.js index a15c161e78ba2..fed51224e51de 100644 --- a/test/integration/conflicting-public-file-page/test/index.test.js +++ b/test/integration/conflicting-public-file-page/test/index.test.js @@ -27,19 +27,22 @@ describe('Errors on conflict between public file and page file', () => { await killApp(app) }) }) - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - it('Throws error during build', async () => { - const conflicts = ['/another/conflict', '/another', '/hello'] - const results = await nextBuild(appDir, [], { - stdout: true, - stderr: true, - }) - const output = results.stdout + results.stderr - expect(output).toMatch(/Conflicting public and page files were found/) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + it('Throws error during build', async () => { + const conflicts = ['/another/conflict', '/another', '/hello'] + const results = await nextBuild(appDir, [], { + stdout: true, + stderr: true, + }) + const output = results.stdout + results.stderr + expect(output).toMatch(/Conflicting public and page files were found/) - for (const conflict of conflicts) { - expect(output.indexOf(conflict) > 0).toBe(true) - } - }) - }) + for (const conflict of conflicts) { + expect(output.indexOf(conflict) > 0).toBe(true) + } + }) + } + ) }) diff --git a/test/integration/conflicting-ssg-paths/test/index.test.js b/test/integration/conflicting-ssg-paths/test/index.test.js index 086dab1a22d75..a3e43a83ccbb2 100644 --- a/test/integration/conflicting-ssg-paths/test/index.test.js +++ b/test/integration/conflicting-ssg-paths/test/index.test.js @@ -8,14 +8,16 @@ const appDir = join(__dirname, '../') const pagesDir = join(appDir, 'pages') describe('Conflicting SSG paths', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - afterEach(() => fs.remove(pagesDir)) - - it('should show proper error when two dynamic SSG routes have conflicting paths', async () => { - await fs.ensureDir(join(pagesDir, 'blog')) - await fs.writeFile( - join(pagesDir, 'blog/[slug].js'), - ` + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + afterEach(() => fs.remove(pagesDir)) + + it('should show proper error when two dynamic SSG routes have conflicting paths', async () => { + await fs.ensureDir(join(pagesDir, 'blog')) + await fs.writeFile( + join(pagesDir, 'blog/[slug].js'), + ` export const getStaticProps = () => { return { props: {} @@ -36,11 +38,11 @@ describe('Conflicting SSG paths', () => { return '/blog/[slug]' } ` - ) + ) - await fs.writeFile( - join(pagesDir, '[...catchAll].js'), - ` + await fs.writeFile( + join(pagesDir, '[...catchAll].js'), + ` export const getStaticProps = () => { return { props: {} @@ -61,39 +63,39 @@ describe('Conflicting SSG paths', () => { return '/[catchAll]' } ` - ) - - const result = await nextBuild(appDir, undefined, { - stdout: true, - stderr: true, + ) + + const result = await nextBuild(appDir, undefined, { + stdout: true, + stderr: true, + }) + const output = result.stdout + result.stderr + expect(output).toContain( + 'Conflicting paths returned from getStaticPaths, paths must be unique per page' + ) + expect(output).toContain( + 'https://nextjs.org/docs/messages/conflicting-ssg-paths' + ) + expect(output).toContain( + `path: "/blog/conflicting" from page: "/[...catchAll]"` + ) + expect(output).toContain(`conflicts with path: "/blog/conflicting"`) }) - const output = result.stdout + result.stderr - expect(output).toContain( - 'Conflicting paths returned from getStaticPaths, paths must be unique per page' - ) - expect(output).toContain( - 'https://nextjs.org/docs/messages/conflicting-ssg-paths' - ) - expect(output).toContain( - `path: "/blog/conflicting" from page: "/[...catchAll]"` - ) - expect(output).toContain(`conflicts with path: "/blog/conflicting"`) - }) - - it('should show proper error when a dynamic SSG route conflicts with normal route', async () => { - await fs.ensureDir(join(pagesDir, 'hello')) - await fs.writeFile( - join(pagesDir, 'hello/world.js'), - ` + + it('should show proper error when a dynamic SSG route conflicts with normal route', async () => { + await fs.ensureDir(join(pagesDir, 'hello')) + await fs.writeFile( + join(pagesDir, 'hello/world.js'), + ` export default function Page() { return '/hello/world' } ` - ) + ) - await fs.writeFile( - join(pagesDir, '[...catchAll].js'), - ` + await fs.writeFile( + join(pagesDir, '[...catchAll].js'), + ` export const getStaticProps = () => { return { props: {} @@ -114,40 +116,40 @@ describe('Conflicting SSG paths', () => { return '/[catchAll]' } ` - ) - - const result = await nextBuild(appDir, undefined, { - stdout: true, - stderr: true, + ) + + const result = await nextBuild(appDir, undefined, { + stdout: true, + stderr: true, + }) + const output = result.stdout + result.stderr + expect(output).toContain( + 'Conflicting paths returned from getStaticPaths, paths must be unique per page' + ) + expect(output).toContain( + 'https://nextjs.org/docs/messages/conflicting-ssg-paths' + ) + expect(output).toContain( + `path: "/hellO/world" from page: "/[...catchAll]" conflicts with path: "/hello/world"` + ) }) - const output = result.stdout + result.stderr - expect(output).toContain( - 'Conflicting paths returned from getStaticPaths, paths must be unique per page' - ) - expect(output).toContain( - 'https://nextjs.org/docs/messages/conflicting-ssg-paths' - ) - expect(output).toContain( - `path: "/hellO/world" from page: "/[...catchAll]" conflicts with path: "/hello/world"` - ) - }) - - it('should show proper error when a dynamic SSG route conflicts with SSR route', async () => { - await fs.ensureDir(join(pagesDir, 'hello')) - await fs.writeFile( - join(pagesDir, 'hello/world.js'), - ` + + it('should show proper error when a dynamic SSG route conflicts with SSR route', async () => { + await fs.ensureDir(join(pagesDir, 'hello')) + await fs.writeFile( + join(pagesDir, 'hello/world.js'), + ` export const getServerSideProps = () => ({ props: {} }) export default function Page() { return '/hello/world' } ` - ) + ) - await fs.writeFile( - join(pagesDir, '[...catchAll].js'), - ` + await fs.writeFile( + join(pagesDir, '[...catchAll].js'), + ` export const getStaticProps = () => { return { props: {} @@ -168,22 +170,23 @@ describe('Conflicting SSG paths', () => { return '/[catchAll]' } ` - ) - - const result = await nextBuild(appDir, undefined, { - stdout: true, - stderr: true, + ) + + const result = await nextBuild(appDir, undefined, { + stdout: true, + stderr: true, + }) + const output = result.stdout + result.stderr + expect(output).toContain( + 'Conflicting paths returned from getStaticPaths, paths must be unique per page' + ) + expect(output).toContain( + 'https://nextjs.org/docs/messages/conflicting-ssg-paths' + ) + expect(output).toContain( + `path: "/hellO/world" from page: "/[...catchAll]" conflicts with path: "/hello/world"` + ) }) - const output = result.stdout + result.stderr - expect(output).toContain( - 'Conflicting paths returned from getStaticPaths, paths must be unique per page' - ) - expect(output).toContain( - 'https://nextjs.org/docs/messages/conflicting-ssg-paths' - ) - expect(output).toContain( - `path: "/hellO/world" from page: "/[...catchAll]" conflicts with path: "/hello/world"` - ) - }) - }) + } + ) }) diff --git a/test/integration/critical-css/test/index.test.js b/test/integration/critical-css/test/index.test.js index 70bc40996c3f5..ceb58c2711431 100644 --- a/test/integration/critical-css/test/index.test.js +++ b/test/integration/critical-css/test/index.test.js @@ -57,25 +57,28 @@ function runTests() { } describe('CSS optimization for SSR apps', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - beforeAll(async () => { - await fs.writeFile( - nextConfig, - `module.exports = { experimental: {optimizeCss: true} }`, - 'utf8' - ) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + beforeAll(async () => { + await fs.writeFile( + nextConfig, + `module.exports = { experimental: {optimizeCss: true} }`, + 'utf8' + ) - if (fs.pathExistsSync(join(appDir, '.next'))) { - await fs.remove(join(appDir, '.next')) - } - await nextBuild(appDir) - appPort = await findPort() - app = await nextStart(appDir, appPort) - }) - afterAll(async () => { - await killApp(app) - await fs.remove(nextConfig) - }) - runTests() - }) + if (fs.pathExistsSync(join(appDir, '.next'))) { + await fs.remove(join(appDir, '.next')) + } + await nextBuild(appDir) + appPort = await findPort() + app = await nextStart(appDir, appPort) + }) + afterAll(async () => { + await killApp(app) + await fs.remove(nextConfig) + }) + runTests() + } + ) }) diff --git a/test/integration/css-client-nav/test/index.test.js b/test/integration/css-client-nav/test/index.test.js index b2f61541f1b29..8903cbc17aed0 100644 --- a/test/integration/css-client-nav/test/index.test.js +++ b/test/integration/css-client-nav/test/index.test.js @@ -150,75 +150,78 @@ function runTests(dev) { } describe('CSS Module client-side navigation', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - beforeAll(async () => { - await remove(join(appDir, '.next')) - await nextBuild(appDir) - const port = await findPort() - app = await nextStart(appDir, port) - appPort = await findPort() - - const proxy = httpProxy.createProxyServer({ - target: `http://localhost:${port}`, + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + beforeAll(async () => { + await remove(join(appDir, '.next')) + await nextBuild(appDir) + const port = await findPort() + app = await nextStart(appDir, port) + appPort = await findPort() + + const proxy = httpProxy.createProxyServer({ + target: `http://localhost:${port}`, + }) + + proxyServer = http.createServer(async (req, res) => { + if (stallCss && req.url.endsWith('.css')) { + console.log('stalling request for', req.url) + await new Promise((resolve) => setTimeout(resolve, 5 * 1000)) + } + proxy.web(req, res) + }) + + proxy.on('error', (err) => { + console.warn('Failed to proxy', err) + }) + + await new Promise((resolve) => { + proxyServer.listen(appPort, () => resolve()) + }) }) - - proxyServer = http.createServer(async (req, res) => { - if (stallCss && req.url.endsWith('.css')) { - console.log('stalling request for', req.url) - await new Promise((resolve) => setTimeout(resolve, 5 * 1000)) - } - proxy.web(req, res) + afterAll(async () => { + proxyServer.close() + await killApp(app) }) - proxy.on('error', (err) => { - console.warn('Failed to proxy', err) - }) - - await new Promise((resolve) => { - proxyServer.listen(appPort, () => resolve()) - }) - }) - afterAll(async () => { - proxyServer.close() - await killApp(app) - }) - - it('should time out and hard navigate for stalled CSS request', async () => { - let browser - stallCss = true - - try { - browser = await webdriver(appPort, '/red') - await browser.eval('window.beforeNav = "hello"') - - const redColor = await browser.eval( - `window.getComputedStyle(document.querySelector('#verify-red')).color` - ) - expect(redColor).toMatchInlineSnapshot(`"rgb(255, 0, 0)"`) - expect(await browser.eval('window.beforeNav')).toBe('hello') - - await browser.elementByCss('#link-blue').click() - - await browser.waitForElementByCss('#verify-blue') - - const blueColor = await browser.eval( - `window.getComputedStyle(document.querySelector('#verify-blue')).color` - ) - expect(blueColor).toMatchInlineSnapshot(`"rgb(0, 0, 255)"`) - - // the timeout should have been reached and we did a hard - // navigation - expect(await browser.eval('window.beforeNav')).toBeFalsy() - } finally { - stallCss = false - if (browser) { - await browser.close() + it('should time out and hard navigate for stalled CSS request', async () => { + let browser + stallCss = true + + try { + browser = await webdriver(appPort, '/red') + await browser.eval('window.beforeNav = "hello"') + + const redColor = await browser.eval( + `window.getComputedStyle(document.querySelector('#verify-red')).color` + ) + expect(redColor).toMatchInlineSnapshot(`"rgb(255, 0, 0)"`) + expect(await browser.eval('window.beforeNav')).toBe('hello') + + await browser.elementByCss('#link-blue').click() + + await browser.waitForElementByCss('#verify-blue') + + const blueColor = await browser.eval( + `window.getComputedStyle(document.querySelector('#verify-blue')).color` + ) + expect(blueColor).toMatchInlineSnapshot(`"rgb(0, 0, 255)"`) + + // the timeout should have been reached and we did a hard + // navigation + expect(await browser.eval('window.beforeNav')).toBeFalsy() + } finally { + stallCss = false + if (browser) { + await browser.close() + } } - } - }) + }) - runTests() - }) + runTests() + } + ) describe('dev', () => { beforeAll(async () => { diff --git a/test/integration/css-customization/test/index.test.js b/test/integration/css-customization/test/index.test.js index 6a2fc992201fc..f5d5b6047f9bc 100644 --- a/test/integration/css-customization/test/index.test.js +++ b/test/integration/css-customization/test/index.test.js @@ -8,53 +8,61 @@ import escapeStringRegexp from 'escape-string-regexp' const fixturesDir = join(__dirname, '../..', 'css-fixtures') describe('CSS Customization', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - const appDir = join(fixturesDir, 'custom-configuration') + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + const appDir = join(fixturesDir, 'custom-configuration') - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) - describe('Basic CSS', () => { - it('should compile successfully', async () => { - const { code, stdout } = await nextBuild(appDir, [], { - stdout: true, + 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/) }) - expect(code).toBe(0) - expect(stdout).toMatch(/Compiled successfully/) - }) - it(`should've compiled and prefixed`, async () => { - const cssFolder = join(appDir, '.next/static/css') + 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)) + 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( - `"@media (480px <= width < 768px){::placeholder{color:green}}.video{max-width:400px;max-height:300px}"` - ) + 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}"` + ) - // Contains a source map - expect(cssContent).toMatch(/\/\*#\s*sourceMappingURL=(.+\.map)\s*\*\//) - }) + // 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') + 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)) + const files = await readdir(cssFolder) + const cssMapFiles = files.filter((f) => /\.css\.map$/.test(f)) - expect(cssMapFiles.length).toBe(1) - const cssMapContent = ( - await readFile(join(cssFolder, cssMapFiles[0]), 'utf8') - ).trim() + expect(cssMapFiles.length).toBe(1) + const cssMapContent = ( + await readFile(join(cssFolder, cssMapFiles[0]), 'utf8') + ).trim() - const { version, mappings, sourcesContent } = JSON.parse(cssMapContent) - expect({ version, mappings, sourcesContent }).toMatchInlineSnapshot(` + const { version, mappings, sourcesContent } = + JSON.parse(cssMapContent) + expect({ version, mappings, sourcesContent }).toMatchInlineSnapshot(` { "mappings": "AACA,gCACE,cACE,WACF,CACF,CAGA,OACE,eAA0B,CAA1B,gBACF", "sourcesContent": [ @@ -74,55 +82,61 @@ describe('CSS Customization', () => { "version": 3, } `) + }) }) - }) - describe('Correct CSS Customization Array', () => { - const appDir = join(fixturesDir, 'custom-configuration-arr') + describe('Correct CSS Customization Array', () => { + const appDir = join(fixturesDir, 'custom-configuration-arr') - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) - it('should compile successfully', async () => { - const { code, stdout } = await nextBuild(appDir, [], { - stdout: true, + it('should compile successfully', async () => { + const { code, stdout } = await nextBuild(appDir, [], { + stdout: true, + }) + expect(code).toBe(0) + expect(stdout).toMatch(/Compiled successfully/) }) - expect(code).toBe(0) - expect(stdout).toMatch(/Compiled successfully/) - }) - it(`should've compiled and prefixed`, async () => { - const cssFolder = join(appDir, '.next/static/css') + 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)) + 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( - `"@media (480px <= width < 768px){a:before{content:""}::placeholder{color:green}}.video{max-width:6400px;max-height:4800px;max-width:400rem;max-height:300rem}"` - ) + 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}"` + ) - // Contains a source map - expect(cssContent).toMatch(/\/\*#\s*sourceMappingURL=(.+\.map)\s*\*\//) - }) + // 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') + 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)) + const files = await readdir(cssFolder) + const cssMapFiles = files.filter((f) => /\.css\.map$/.test(f)) - expect(cssMapFiles.length).toBe(1) - const cssMapContent = ( - await readFile(join(cssFolder, cssMapFiles[0]), 'utf8') - ).trim() + expect(cssMapFiles.length).toBe(1) + const cssMapContent = ( + await readFile(join(cssFolder, cssMapFiles[0]), 'utf8') + ).trim() - const { version, mappings, sourcesContent } = JSON.parse(cssMapContent) - expect({ version, mappings, sourcesContent }).toMatchInlineSnapshot(` + const { version, mappings, sourcesContent } = + JSON.parse(cssMapContent) + expect({ version, mappings, sourcesContent }).toMatchInlineSnapshot(` { "mappings": "AACA,gCACE,SACE,UACF,CACA,cACE,WACF,CACF,CAGA,OACE,gBAA4B,CAA5B,iBAA4B,CAA5B,gBAA4B,CAA5B,iBACF", "sourcesContent": [ @@ -145,246 +159,252 @@ describe('CSS Customization', () => { "version": 3, } `) + }) }) - }) - describe('Correct CSS Customization custom loader', () => { - const appDir = join(fixturesDir, 'custom-configuration-loader') + describe('Correct CSS Customization custom loader', () => { + const appDir = join(fixturesDir, 'custom-configuration-loader') - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) - it('should compile successfully', async () => { - const { code, stdout, stderr } = await nextBuild(appDir, [], { - stdout: true, - stderr: true, + 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/) }) - 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') + it(`should've applied style`, async () => { + const pagesFolder = join(appDir, '.next/static/chunks/pages') - const files = await readdir(pagesFolder) - const indexFiles = files.filter((f) => /^index.+\.js$/.test(f)) + const files = await readdir(pagesFolder) + const indexFiles = files.filter((f) => /^index.+\.js$/.test(f)) - 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(indexFiles.length).toBe(1) + const indexContent = await readFile( + join(pagesFolder, indexFiles[0]), + 'utf8' + ) + expect(indexContent).toMatch(/\.my-text\.jsx-[0-9a-z]+{color:red}/) + }) }) - }) - describe('Bad CSS Customization', () => { - const appDir = join(fixturesDir, 'bad-custom-configuration') + describe('Bad CSS Customization', () => { + const appDir = join(fixturesDir, 'bad-custom-configuration') - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) + 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 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') + 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)) + 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}"`) + 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*\*\//) - }) + // 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') + 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)) + const files = await readdir(cssFolder) + const cssMapFiles = files.filter((f) => /\.css\.map$/.test(f)) - expect(cssMapFiles.length).toBe(1) + expect(cssMapFiles.length).toBe(1) + }) }) - }) - describe('Bad CSS Customization Array (1)', () => { - const appDir = join(fixturesDir, 'bad-custom-configuration-arr-1') + describe('Bad CSS Customization Array (1)', () => { + const appDir = join(fixturesDir, 'bad-custom-configuration-arr-1') - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) - it('should fail the build', async () => { - const { stderr } = await nextBuild(appDir, [], { stderr: true }) + 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/) + 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') + describe('Bad CSS Customization Array (2)', () => { + const appDir = join(fixturesDir, 'bad-custom-configuration-arr-2') - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) - it('should fail the build', async () => { - const { stderr } = await nextBuild(appDir, [], { stderr: true }) + 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/) + 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') + describe('Bad CSS Customization Array (3)', () => { + const appDir = join(fixturesDir, 'bad-custom-configuration-arr-3') - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) - it('should fail the build', async () => { - const { stderr } = await nextBuild(appDir, [], { stderr: true }) + 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/) + 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') + describe('Bad CSS Customization Array (4)', () => { + const appDir = join(fixturesDir, 'bad-custom-configuration-arr-4') - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) - it('should fail the build', async () => { - const { stderr } = await nextBuild(appDir, [], { stderr: true }) + 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/) + 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') + describe('Bad CSS Customization Array (5)', () => { + const appDir = join(fixturesDir, 'bad-custom-configuration-arr-5') - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) - it('should fail the build', async () => { - const { stderr } = await nextBuild(appDir, [], { stderr: true }) + 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/) + 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') + describe('Bad CSS Customization Array (6)', () => { + const appDir = join(fixturesDir, 'bad-custom-configuration-arr-6') - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) - it('should fail the build', async () => { - const { stderr } = await nextBuild(appDir, [], { stderr: true }) + 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/) + 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') + describe('Bad CSS Customization Array (7)', () => { + const appDir = join(fixturesDir, 'bad-custom-configuration-arr-7') - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) - it('should fail the build', async () => { - const { stderr } = await nextBuild(appDir, [], { stderr: true }) + 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/) + 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') + describe('Bad CSS Customization Array (8)', () => { + const appDir = join(fixturesDir, 'bad-custom-configuration-arr-8') - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) - it('should fail the build', async () => { - const { stderr } = await nextBuild(appDir, [], { stderr: true }) + 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/) + 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') + describe('Bad CSS Customization Function', () => { + const appDir = join(fixturesDir, 'bad-custom-configuration-func') - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) - it('should fail the build', async () => { - const { stderr } = await nextBuild(appDir, [], { stderr: true }) + 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/) + expect(stderr).toMatch( + /Your custom PostCSS configuration may not export a function/ + ) + expect(stderr).toMatch(/Build failed because of webpack errors/) + }) }) - }) - }) + } + ) }) diff --git a/test/integration/css-features/test/browserslist.test.js b/test/integration/css-features/test/browserslist.test.js index 6966c72ebae7b..551808626f039 100644 --- a/test/integration/css-features/test/browserslist.test.js +++ b/test/integration/css-features/test/browserslist.test.js @@ -7,73 +7,79 @@ import { join } from 'path' const fixturesDir = join(__dirname, '../fixtures') describe('Browserslist: Old', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - const appDir = join(fixturesDir, 'browsers-old') - - 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'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)) - - expect(cssFiles.length).toBe(1) - const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8') - - expect( - cssContent.replace(/\/\*.*?\*\//g, '').trim() - ).toMatchInlineSnapshot( - `"a{-webkit-animation:none 0s ease 0s 1 normal none running;animation:none 0s ease 0s 1 normal none running;-webkit-backface-visibility:visible;backface-visibility:visible;background:transparent none repeat 0 0/auto auto padding-box border-box scroll;border:none;border-collapse:separate;-webkit-border-image:none;border-image:none;-webkit-border-radius:0;border-radius:0;border-spacing:0;bottom:auto;-webkit-box-shadow:none;box-shadow:none;-webkit-box-sizing:content-box;box-sizing:content-box;caption-side:top;clear:none;clip:auto;color:#000;-webkit-columns:auto;-webkit-column-count:auto;-webkit-column-fill:balance;column-fill:balance;-webkit-column-gap:normal;column-gap:normal;-webkit-column-rule:medium none currentColor;column-rule:medium none currentColor;-webkit-column-span:1;column-span:1;-webkit-column-width:auto;columns:auto;content:normal;counter-increment:none;counter-reset:none;cursor:auto;direction:ltr;display:inline;empty-cells:show;float:none;font-family:serif;font-size:medium;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;line-height:normal;height:auto;-ms-hyphens:none;hyphens:none;left:auto;letter-spacing:normal;list-style:disc none outside;margin:0;max-height:none;max-width:none;min-height:0;min-width:0;opacity:1;orphans:2;outline:medium none invert;overflow:visible;overflow-x:visible;overflow-y:visible;padding:0;page-break-after:auto;page-break-before:auto;page-break-inside:auto;-webkit-perspective:none;perspective:none;-webkit-perspective-origin:50% 50%;perspective-origin:50% 50%;position:static;right:auto;tab-size:8;table-layout:auto;text-align:left;text-align-last:auto;text-decoration:none;text-indent:0;text-shadow:none;text-transform:none;top:auto;-webkit-transform:none;transform:none;-webkit-transform-origin:50% 50% 0;transform-origin:50% 50% 0;-webkit-transform-style:flat;transform-style:flat;-webkit-transition:none 0s ease 0s;transition:none 0s ease 0s;unicode-bidi:normal;vertical-align:baseline;visibility:visible;white-space:normal;widows:2;width:auto;word-spacing:normal;z-index:auto;all:initial}@media (-webkit-min-device-pixel-ratio:2),(min-resolution:2dppx){.image{background-image:url(data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==)}}"` - ) - }) - }) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + const appDir = join(fixturesDir, 'browsers-old') + + 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'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)) + + expect(cssFiles.length).toBe(1) + const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8') + + expect( + cssContent.replace(/\/\*.*?\*\//g, '').trim() + ).toMatchInlineSnapshot( + `"a{-webkit-animation:none 0s ease 0s 1 normal none running;animation:none 0s ease 0s 1 normal none running;-webkit-backface-visibility:visible;backface-visibility:visible;background:transparent none repeat 0 0/auto auto padding-box border-box scroll;border:none;border-collapse:separate;-webkit-border-image:none;border-image:none;-webkit-border-radius:0;border-radius:0;border-spacing:0;bottom:auto;-webkit-box-shadow:none;box-shadow:none;-webkit-box-sizing:content-box;box-sizing:content-box;caption-side:top;clear:none;clip:auto;color:#000;-webkit-columns:auto;-webkit-column-count:auto;-webkit-column-fill:balance;column-fill:balance;-webkit-column-gap:normal;column-gap:normal;-webkit-column-rule:medium none currentColor;column-rule:medium none currentColor;-webkit-column-span:1;column-span:1;-webkit-column-width:auto;columns:auto;content:normal;counter-increment:none;counter-reset:none;cursor:auto;direction:ltr;display:inline;empty-cells:show;float:none;font-family:serif;font-size:medium;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;line-height:normal;height:auto;-ms-hyphens:none;hyphens:none;left:auto;letter-spacing:normal;list-style:disc none outside;margin:0;max-height:none;max-width:none;min-height:0;min-width:0;opacity:1;orphans:2;outline:medium none invert;overflow:visible;overflow-x:visible;overflow-y:visible;padding:0;page-break-after:auto;page-break-before:auto;page-break-inside:auto;-webkit-perspective:none;perspective:none;-webkit-perspective-origin:50% 50%;perspective-origin:50% 50%;position:static;right:auto;tab-size:8;table-layout:auto;text-align:left;text-align-last:auto;text-decoration:none;text-indent:0;text-shadow:none;text-transform:none;top:auto;-webkit-transform:none;transform:none;-webkit-transform-origin:50% 50% 0;transform-origin:50% 50% 0;-webkit-transform-style:flat;transform-style:flat;-webkit-transition:none 0s ease 0s;transition:none 0s ease 0s;unicode-bidi:normal;vertical-align:baseline;visibility:visible;white-space:normal;widows:2;width:auto;word-spacing:normal;z-index:auto;all:initial}@media (-webkit-min-device-pixel-ratio:2),(min-resolution:2dppx){.image{background-image:url(data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==)}}"` + ) + }) + } + ) }) describe('Browserslist: New', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - const appDir = join(fixturesDir, 'browsers-new') - - 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'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)) - - expect(cssFiles.length).toBe(1) - const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8') - - expect( - cssContent.replace(/\/\*.*?\*\//g, '').trim() - ).toMatchInlineSnapshot( - `"a{all:initial}@media (min-resolution:2dppx){.image{background-image:url(data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==)}}"` - ) - }) - }) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + const appDir = join(fixturesDir, 'browsers-new') + + 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'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)) + + expect(cssFiles.length).toBe(1) + const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8') + + expect( + cssContent.replace(/\/\*.*?\*\//g, '').trim() + ).toMatchInlineSnapshot( + `"a{all:initial}@media (min-resolution:2dppx){.image{background-image:url(data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==)}}"` + ) + }) + } + ) }) diff --git a/test/integration/css-features/test/css-modules.test.js b/test/integration/css-features/test/css-modules.test.js index c22a3a78913ca..f86ea21a2e062 100644 --- a/test/integration/css-features/test/css-modules.test.js +++ b/test/integration/css-features/test/css-modules.test.js @@ -7,129 +7,144 @@ import { join } from 'path' const fixturesDir = join(__dirname, '../fixtures') describe('Custom Properties: Fail for :root {} in CSS Modules', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - const appDir = join(fixturesDir, 'cp-global-modules') + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + const appDir = join(fixturesDir, 'cp-global-modules') - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) - it('should fail to build', async () => { - const { code, stderr } = await nextBuild(appDir, [], { - stderr: true, + it('should fail to build', async () => { + const { code, stderr } = await nextBuild(appDir, [], { + stderr: true, + }) + expect(code).not.toBe(0) + expect(stderr).toContain('Failed to compile') + expect(stderr).toContain('pages/styles.module.css') + expect(stderr).toContain('Selector ":root" is not pure') }) - expect(code).not.toBe(0) - expect(stderr).toContain('Failed to compile') - expect(stderr).toContain('pages/styles.module.css') - expect(stderr).toContain('Selector ":root" is not pure') - }) - }) + } + ) }) describe('Custom Properties: Fail for global element in CSS Modules', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - const appDir = join(fixturesDir, 'cp-el-modules') + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + const appDir = join(fixturesDir, 'cp-el-modules') - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) - it('should fail to build', async () => { - const { code, stderr } = await nextBuild(appDir, [], { - stderr: true, + it('should fail to build', async () => { + const { code, stderr } = await nextBuild(appDir, [], { + stderr: true, + }) + expect(code).not.toBe(0) + expect(stderr).toContain('Failed to compile') + expect(stderr).toContain('pages/styles.module.css') + expect(stderr).toContain('Selector "h1" is not pure') }) - expect(code).not.toBe(0) - expect(stderr).toContain('Failed to compile') - expect(stderr).toContain('pages/styles.module.css') - expect(stderr).toContain('Selector "h1" is not pure') - }) - }) + } + ) }) describe('CSS Modules: Import Global CSS', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - const appDir = join(fixturesDir, 'module-import-global') - - 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'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)) - - expect(cssFiles.length).toBe(1) - const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8') - - expect( - cssContent.replace(/\/\*.*?\*\//g, '').trim() - ).toMatchInlineSnapshot(`"a .styles_foo__G5630{all:initial}"`) - }) - }) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + const appDir = join(fixturesDir, 'module-import-global') + + 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'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)) + + expect(cssFiles.length).toBe(1) + const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8') + + expect( + cssContent.replace(/\/\*.*?\*\//g, '').trim() + ).toMatchInlineSnapshot(`"a .styles_foo__G5630{all:initial}"`) + }) + } + ) }) describe('CSS Modules: Importing Invalid Global CSS', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - const appDir = join(fixturesDir, 'module-import-global-invalid') + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + const appDir = join(fixturesDir, 'module-import-global-invalid') - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) - it('should fail to build', async () => { - const { code, stderr } = await nextBuild(appDir, [], { - stderr: true, + it('should fail to build', async () => { + const { code, stderr } = await nextBuild(appDir, [], { + stderr: true, + }) + expect(code).not.toBe(0) + expect(stderr).toContain('Failed to compile') + expect(stderr).toContain('pages/styles.css') + expect(stderr).toContain('Selector "a" is not pure') }) - expect(code).not.toBe(0) - expect(stderr).toContain('Failed to compile') - expect(stderr).toContain('pages/styles.css') - expect(stderr).toContain('Selector "a" is not pure') - }) - }) + } + ) }) describe('CSS Modules: Import Exports', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - const appDir = join(fixturesDir, 'module-import-exports') - - 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'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)) - - expect(cssFiles.length).toBe(1) - const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8') - - expect( - cssContent.replace(/\/\*.*?\*\//g, '').trim() - ).toMatchInlineSnapshot(`".styles_blk__480DC{color:#000}"`) - }) - }) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + const appDir = join(fixturesDir, 'module-import-exports') + + 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'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)) + + expect(cssFiles.length).toBe(1) + const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8') + + expect( + cssContent.replace(/\/\*.*?\*\//g, '').trim() + ).toMatchInlineSnapshot(`".styles_blk__480DC{color:#000}"`) + }) + } + ) }) diff --git a/test/integration/css-features/test/index.test.js b/test/integration/css-features/test/index.test.js index a5c2982e3577f..861dc76863822 100644 --- a/test/integration/css-features/test/index.test.js +++ b/test/integration/css-features/test/index.test.js @@ -7,103 +7,112 @@ import { join } from 'path' const fixturesDir = join(__dirname, '../fixtures') describe('Custom Properties: Pass-Through IE11', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - const appDir = join(fixturesDir, 'cp-ie-11') - - 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'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)) - - expect(cssFiles.length).toBe(1) - const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8') - - expect( - cssContent.replace(/\/\*.*?\*\//g, '').trim() - ).toMatchInlineSnapshot(`":root{--color:red}h1{color:var(--color)}"`) - }) - }) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + const appDir = join(fixturesDir, 'cp-ie-11') + + 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'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)) + + expect(cssFiles.length).toBe(1) + const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8') + + expect( + cssContent.replace(/\/\*.*?\*\//g, '').trim() + ).toMatchInlineSnapshot(`":root{--color:red}h1{color:var(--color)}"`) + }) + } + ) }) describe('Custom Properties: Pass-Through Modern', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - const appDir = join(fixturesDir, 'cp-modern') - - 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'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)) - - expect(cssFiles.length).toBe(1) - const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8') - - expect( - cssContent.replace(/\/\*.*?\*\//g, '').trim() - ).toMatchInlineSnapshot(`":root{--color:red}h1{color:var(--color)}"`) - }) - }) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + const appDir = join(fixturesDir, 'cp-modern') + + 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'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)) + + expect(cssFiles.length).toBe(1) + const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8') + + expect( + cssContent.replace(/\/\*.*?\*\//g, '').trim() + ).toMatchInlineSnapshot(`":root{--color:red}h1{color:var(--color)}"`) + }) + } + ) }) describe('Inline Comments: Minify', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - const appDir = join(fixturesDir, 'inline-comments') - - 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'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)) - - expect(cssFiles.length).toBe(1) - const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8') - - expect( - cssContent.replace(/\/\*.*?\*\//g, '').trim() - ).toMatchInlineSnapshot(`"*{box-sizing:border-box}"`) - }) - }) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + const appDir = join(fixturesDir, 'inline-comments') + + 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'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)) + + expect(cssFiles.length).toBe(1) + const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8') + + expect( + cssContent.replace(/\/\*.*?\*\//g, '').trim() + ).toMatchInlineSnapshot(`"*{box-sizing:border-box}"`) + }) + } + ) }) diff --git a/test/integration/css-minify/test/index.test.js b/test/integration/css-minify/test/index.test.js index 4a57d1163ca7c..4b9cea564e86d 100644 --- a/test/integration/css-minify/test/index.test.js +++ b/test/integration/css-minify/test/index.test.js @@ -28,15 +28,18 @@ function runTests() { } describe('css-minify', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - beforeAll(async () => { - await nextBuild(appDir) - appPort = await findPort() - app = await nextStart(appDir, appPort) - }) - afterAll(async () => { - await killApp(app) - }) - runTests() - }) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + beforeAll(async () => { + await nextBuild(appDir) + appPort = await findPort() + app = await nextStart(appDir, appPort) + }) + afterAll(async () => { + await killApp(app) + }) + runTests() + } + ) }) diff --git a/test/integration/css-modules/test/index.test.js b/test/integration/css-modules/test/index.test.js index 7e3de4ed28c1d..a18bf6811b7cc 100644 --- a/test/integration/css-modules/test/index.test.js +++ b/test/integration/css-modules/test/index.test.js @@ -18,122 +18,132 @@ import { join } from 'path' const fixturesDir = join(__dirname, '../../css-fixtures') describe('Basic CSS Module Support', () => { - ;(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) - }) - - 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') - - 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(`".index_redText__honUV{color:red}"`) - }) - - 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 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"` - ) - }) - }) + ;(process.env.TURBOPACK_DEV ? 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) + }) + + 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') + + 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(`".index_redText__honUV{color:red}"`) + }) + + 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 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"` + ) + }) + } + ) }) describe('3rd Party CSS Module Support', () => { - ;(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) - }) - - 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') - - 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( - `".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%}"` - ) - }) + ;(process.env.TURBOPACK_DEV ? 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) + }) - it(`should've injected the CSS on server render`, async () => { - const content = await renderViaHTTP(appPort, '/') - const $ = cheerio.load(content) + it('should have compiled successfully', () => { + expect(code).toBe(0) + expect(stdout).toMatch(/Compiled successfully/) + }) - const cssPreload = $('link[rel="preload"][as="style"]') - expect(cssPreload.length).toBe(1) - expect(cssPreload.attr('href')).toMatch(/^\/_next\/static\/css\/.*\.css$/) + it(`should've emitted a single CSS file`, async () => { + const cssFolder = join(appDir, '.next/static/css') - const cssSheet = $('link[rel="stylesheet"]') - expect(cssSheet.length).toBe(1) - expect(cssSheet.attr('href')).toMatch(/^\/_next\/static\/css\/.*\.css$/) + const files = await readdir(cssFolder) + const cssFiles = files.filter((f) => /\.css$/.test(f)) - expect($('#verify-div').attr('class')).toMatchInlineSnapshot( - `"index_foo__6TgnK"` - ) - }) - }) + 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%}"` + ) + }) + + 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 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"` + ) + }) + } + ) }) describe('Has CSS Module in computed styles in Development', () => { @@ -161,39 +171,42 @@ describe('Has CSS Module in computed styles in Development', () => { }) describe('Has CSS Module in computed styles in Production', () => { - ;(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) - }) - - 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, '/') - - const currentColor = await browser.eval( - `window.getComputedStyle(document.querySelector('#verify-red')).color` - ) - expect(currentColor).toMatchInlineSnapshot(`"rgb(255, 0, 0)"`) - }) - }) + ;(process.env.TURBOPACK_DEV ? 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) + }) + + 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, '/') + + const currentColor = await browser.eval( + `window.getComputedStyle(document.querySelector('#verify-red')).color` + ) + expect(currentColor).toMatchInlineSnapshot(`"rgb(255, 0, 0)"`) + }) + } + ) }) describe('Can hot reload CSS Module without losing state', () => { @@ -243,341 +256,365 @@ describe('Can hot reload CSS Module without losing state', () => { }) describe.skip('Invalid CSS Module Usage in node_modules', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - const appDir = join(fixturesDir, 'invalid-module') - - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) - - it('should fail to build', async () => { - const { code, stderr } = await nextBuild(appDir, [], { - stderr: true, - }) - expect(code).not.toBe(0) - expect(stderr).toContain('Failed to compile') - expect(stderr).toContain('node_modules/example/index.module.css') - expect(stderr).toMatch( - /CSS Modules.*cannot.*be imported from within.*node_modules/ - ) - expect(stderr).toMatch( - /Location:.*node_modules[\\/]example[\\/]index\.mjs/ - ) - }) - }) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + const appDir = join(fixturesDir, 'invalid-module') + + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) + + it('should fail to build', async () => { + const { code, stderr } = await nextBuild(appDir, [], { + stderr: true, + }) + expect(code).not.toBe(0) + expect(stderr).toContain('Failed to compile') + expect(stderr).toContain('node_modules/example/index.module.css') + expect(stderr).toMatch( + /CSS Modules.*cannot.*be imported from within.*node_modules/ + ) + expect(stderr).toMatch( + /Location:.*node_modules[\\/]example[\\/]index\.mjs/ + ) + }) + } + ) }) describe.skip('Invalid Global CSS Module Usage in node_modules', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - const appDir = join(fixturesDir, 'invalid-global-module') - - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) - - it('should fail to build', async () => { - const { code, stderr } = await nextBuild(appDir, [], { - stderr: true, - }) - expect(code).not.toBe(0) - expect(stderr).toContain('Failed to compile') - expect(stderr).toContain('node_modules/example/index.css') - expect(stderr).toMatch( - /Global CSS.*cannot.*be imported from within.*node_modules/ - ) - expect(stderr).toMatch( - /Location:.*node_modules[\\/]example[\\/]index\.mjs/ - ) - }) - }) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + const appDir = join(fixturesDir, 'invalid-global-module') + + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) + + it('should fail to build', async () => { + const { code, stderr } = await nextBuild(appDir, [], { + stderr: true, + }) + expect(code).not.toBe(0) + expect(stderr).toContain('Failed to compile') + expect(stderr).toContain('node_modules/example/index.css') + expect(stderr).toMatch( + /Global CSS.*cannot.*be imported from within.*node_modules/ + ) + expect(stderr).toMatch( + /Location:.*node_modules[\\/]example[\\/]index\.mjs/ + ) + }) + } + ) }) describe('Valid CSS Module Usage from within node_modules', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - const appDir = join(fixturesDir, 'nm-module') - - 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) - }) - - 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) - - const cssPreload = $('#nm-div') - expect(cssPreload.text()).toMatchInlineSnapshot( - `"{"message":"Why hello there"} {"redText":"example_redText__0ctGB"}"` - ) - }) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + const appDir = join(fixturesDir, 'nm-module') - it(`should've emitted a single CSS file`, async () => { - const cssFolder = join(appDir, '.next/static/css') + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) - const files = await readdir(cssFolder) - const cssFiles = files.filter((f) => /\.css$/.test(f)) + 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(cssFiles.length).toBe(1) - const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8') + it(`should've prerendered with relevant data`, async () => { + const content = await renderViaHTTP(appPort, '/') + const $ = cheerio.load(content) - expect( - cssContent.replace(/\/\*.*?\*\//g, '').trim() - ).toMatchInlineSnapshot(`".example_redText__0ctGB{color:red}"`) - }) - }) + 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') + + 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(`".example_redText__0ctGB{color:red}"`) + }) + } + ) }) describe('Valid Nested CSS Module Usage from within node_modules', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - const appDir = join(fixturesDir, 'nm-module-nested') - - 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) - }) - - 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) - - const cssPreload = $('#nm-div') - expect(cssPreload.text()).toMatchInlineSnapshot( - `"{"message":"Why hello there"} {"subClass":"example_subClass__m6Tyy other_className__OA8dV"}"` - ) - }) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + const appDir = join(fixturesDir, 'nm-module-nested') - it(`should've emitted a single CSS file`, async () => { - const cssFolder = join(appDir, '.next/static/css') + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) - const files = await readdir(cssFolder) - const cssFiles = files.filter((f) => /\.css$/.test(f)) + 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) + }) - expect(cssFiles.length).toBe(1) - const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8') + it('should have compiled successfully', () => { + expect(code).toBe(0) + expect(stdout).toMatch(/Compiled successfully/) + }) - 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}"` - ) - }) - }) + 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"}"` + ) + }) + + 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)) + + 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}"` + ) + }) + } + ) }) describe('CSS Module Composes Usage (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, - })) - }) - - 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') - - 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( - `".index_className__jjcZ1{background:red;color:#ff0}.index_subClass__eDzaW{background:blue}"` - ) - }) - }) + ;(process.env.TURBOPACK_DEV ? 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, + })) + }) + + 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') + + 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( + `".index_className__jjcZ1{background:red;color:#ff0}.index_subClass__eDzaW{background:blue}"` + ) + }) + } + ) }) describe('CSS Module Composes Usage (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, - })) - }) - - 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') - - 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_className__eZV4M{background:red;color:#ff0}.index_subClass__eDzaW{background:blue}"` - ) - }) - }) + ;(process.env.TURBOPACK_DEV ? 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, + })) + }) + + 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') + + 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_className__eZV4M{background:red;color:#ff0}.index_subClass__eDzaW{background:blue}"` + ) + }) + } + ) }) describe('Dynamic Route CSS Module Usage', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - const appDir = join(fixturesDir, 'dynamic-route-module') - - 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)) - - 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') - - const background = await browser - .elementByCss('#my-div') - .getComputedCss('background-color') - - expect(background).toMatch(/rgb(a|)\(255, 0, 0/) - }) - - it(`should've emitted a single CSS file`, async () => { - const 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(`"._post__home__yRmHz{background:red}"`) - }) - }) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + const appDir = join(fixturesDir, 'dynamic-route-module') + + 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)) + + 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') + + const background = await browser + .elementByCss('#my-div') + .getComputedCss('background-color') + + expect(background).toMatch(/rgb(a|)\(255, 0, 0/) + }) + + it(`should've emitted a single CSS file`, async () => { + const 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(`"._post__home__yRmHz{background:red}"`) + }) + } + ) }) describe('Catch-all Route CSS Module Usage', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - const appDir = join(fixturesDir, 'catch-all-module') - - 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)) - - 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') - - const bg = await browser - .elementByCss('#my-div') - .getComputedCss('background-color') - expect(bg).toMatch(/rgb(a|)\(255, 0, 0/) - - const fg = await browser.elementByCss('#my-div').getComputedCss('color') - expect(fg).toMatch(/rgb(a|)\(0, 128, 0/) - }) - - it(`should've emitted a single CSS file`, async () => { - const 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( - `".___post__home__e4zfx{background:red}.__55css_home__r8Rnq{color:green}"` - ) - }) - }) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + const appDir = join(fixturesDir, 'catch-all-module') + + 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)) + + 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') + + const bg = await browser + .elementByCss('#my-div') + .getComputedCss('background-color') + expect(bg).toMatch(/rgb(a|)\(255, 0, 0/) + + const fg = await browser.elementByCss('#my-div').getComputedCss('color') + expect(fg).toMatch(/rgb(a|)\(0, 128, 0/) + }) + + it(`should've emitted a single CSS file`, async () => { + const 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( + `".___post__home__e4zfx{background:red}.__55css_home__r8Rnq{color:green}"` + ) + }) + } + ) }) diff --git a/test/integration/css/test/basic-global-support.test.js b/test/integration/css/test/basic-global-support.test.js index fbbff6dc4cfc9..501af8474a7ed 100644 --- a/test/integration/css/test/basic-global-support.test.js +++ b/test/integration/css/test/basic-global-support.test.js @@ -6,14 +6,16 @@ import { join } from 'path' const fixturesDir = join(__dirname, '../..', 'css-fixtures') describe('Basic Global Support', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - const appDir = join(fixturesDir, 'single-global') - const nextConfig = new File(join(appDir, 'next.config.js')) - - describe.each([true, false])(`useLightnincsss(%s)`, (useLightningcss) => { - beforeAll(async () => { - nextConfig.write( - ` + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + const appDir = join(fixturesDir, 'single-global') + const nextConfig = new File(join(appDir, 'next.config.js')) + + describe.each([true, false])(`useLightnincsss(%s)`, (useLightningcss) => { + beforeAll(async () => { + nextConfig.write( + ` const config = require('../next.config.js'); module.exports = { ...config, @@ -21,45 +23,52 @@ module.exports = { useLightningcss: ${useLightningcss} } }` - ) - }) + ) + }) - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) - it('should compile successfully', async () => { - const { code, stdout } = await nextBuild(appDir, [], { - stdout: true, + it('should compile successfully', async () => { + const { code, stdout } = await nextBuild(appDir, [], { + stdout: true, + }) + expect(code).toBe(0) + expect(stdout).toMatch(/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) - expect(await readFile(join(cssFolder, cssFiles[0]), 'utf8')).toContain( - 'color:red' - ) + 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', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - const appDir = join(fixturesDir, 'single-global-special-characters', 'a+b') - const nextConfig = new File(join(appDir, 'next.config.js')) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + const appDir = join( + fixturesDir, + 'single-global-special-characters', + 'a+b' + ) + const nextConfig = new File(join(appDir, 'next.config.js')) - describe.each([true, false])(`useLightnincsss(%s)`, (useLightningcss) => { - beforeAll(async () => { - nextConfig.write( - ` + describe.each([true, false])(`useLightnincsss(%s)`, (useLightningcss) => { + beforeAll(async () => { + nextConfig.write( + ` const config = require('../../next.config.js'); module.exports = { ...config, @@ -67,45 +76,48 @@ module.exports = { useLightningcss: ${useLightningcss} } }` - ) - }) + ) + }) - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) - it('should compile successfully', async () => { - const { code, stdout } = await nextBuild(appDir, [], { - stdout: true, + it('should compile successfully', async () => { + const { code, stdout } = await nextBuild(appDir, [], { + stdout: true, + }) + expect(code).toBe(0) + expect(stdout).toMatch(/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) - expect(await readFile(join(cssFolder, cssFiles[0]), 'utf8')).toContain( - 'color:red' - ) + expect(cssFiles.length).toBe(1) + expect( + await readFile(join(cssFolder, cssFiles[0]), 'utf8') + ).toContain('color:red') + }) }) - }) - }) + } + ) }) describe('Basic Global Support with src/ dir', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - const appDir = join(fixturesDir, 'single-global-src') - const nextConfig = new File(join(appDir, 'next.config.js')) - - describe.each([true, false])(`useLightnincsss(%s)`, (useLightningcss) => { - beforeAll(async () => { - nextConfig.write( - ` + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + const appDir = join(fixturesDir, 'single-global-src') + const nextConfig = new File(join(appDir, 'next.config.js')) + + describe.each([true, false])(`useLightnincsss(%s)`, (useLightningcss) => { + beforeAll(async () => { + nextConfig.write( + ` const config = require('../next.config.js'); module.exports = { ...config, @@ -113,45 +125,48 @@ module.exports = { useLightningcss: ${useLightningcss} } }` - ) - }) + ) + }) - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) - it('should compile successfully', async () => { - const { code, stdout } = await nextBuild(appDir, [], { - stdout: true, + it('should compile successfully', async () => { + const { code, stdout } = await nextBuild(appDir, [], { + stdout: true, + }) + expect(code).toBe(0) + expect(stdout).toMatch(/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) - expect(await readFile(join(cssFolder, cssFiles[0]), 'utf8')).toContain( - 'color:red' - ) + expect(cssFiles.length).toBe(1) + expect( + await readFile(join(cssFolder, cssFiles[0]), 'utf8') + ).toContain('color:red') + }) }) - }) - }) + } + ) }) describe('Multi Global Support', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - const appDir = join(fixturesDir, 'multi-global') - const nextConfig = new File(join(appDir, 'next.config.js')) - - describe.each([true, false])(`useLightnincsss(%s)`, (useLightningcss) => { - beforeAll(async () => { - nextConfig.write( - ` + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + const appDir = join(fixturesDir, 'multi-global') + const nextConfig = new File(join(appDir, 'next.config.js')) + + describe.each([true, false])(`useLightnincsss(%s)`, (useLightningcss) => { + beforeAll(async () => { + nextConfig.write( + ` const config = require('../next.config.js'); module.exports = { ...config, @@ -159,44 +174,52 @@ module.exports = { useLightningcss: ${useLightningcss} } }` - ) - }) + ) + }) - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) - it('should compile successfully', async () => { - const { code, stdout } = await nextBuild(appDir, [], { - stdout: true, + it('should compile successfully', async () => { + const { code, stdout } = await nextBuild(appDir, [], { + stdout: true, + }) + expect(code).toBe(0) + expect(stdout).toMatch(/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(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchSnapshot() + expect(cssFiles.length).toBe(1) + const cssContent = await readFile( + join(cssFolder, cssFiles[0]), + 'utf8' + ) + expect( + cssContent.replace(/\/\*.*?\*\//g, '').trim() + ).toMatchSnapshot() + }) }) - }) - }) + } + ) }) describe('Nested @import() Global Support', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - const appDir = join(fixturesDir, 'nested-global') - const nextConfig = new File(join(appDir, 'next.config.js')) - - describe.each([true, false])(`useLightnincsss(%s)`, (useLightningcss) => { - beforeAll(async () => { - nextConfig.write( - ` + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + const appDir = join(fixturesDir, 'nested-global') + const nextConfig = new File(join(appDir, 'next.config.js')) + + describe.each([true, false])(`useLightnincsss(%s)`, (useLightningcss) => { + beforeAll(async () => { + nextConfig.write( + ` const config = require('../next.config.js'); module.exports = { ...config, @@ -204,45 +227,53 @@ module.exports = { useLightningcss: ${useLightningcss} } }` - ) - }) + ) + }) - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) - it('should compile successfully', async () => { - const { code, stdout } = await nextBuild(appDir, [], { - stdout: true, + it('should compile successfully', async () => { + const { code, stdout } = await nextBuild(appDir, [], { + stdout: true, + }) + expect(code).toBe(0) + expect(stdout).toMatch(/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(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchSnapshot() + expect(cssFiles.length).toBe(1) + const cssContent = await readFile( + join(cssFolder, cssFiles[0]), + 'utf8' + ) + expect( + cssContent.replace(/\/\*.*?\*\//g, '').trim() + ).toMatchSnapshot() + }) }) - }) - }) + } + ) }) // Tests css ordering describe('Multi Global Support (reversed)', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - const appDir = join(fixturesDir, 'multi-global-reversed') - const nextConfig = new File(join(appDir, 'next.config.js')) - - describe.each([true, false])(`useLightnincsss(%s)`, (useLightningcss) => { - beforeAll(async () => { - nextConfig.write( - ` + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + const appDir = join(fixturesDir, 'multi-global-reversed') + const nextConfig = new File(join(appDir, 'next.config.js')) + + describe.each([true, false])(`useLightnincsss(%s)`, (useLightningcss) => { + beforeAll(async () => { + nextConfig.write( + ` const config = require('../next.config.js'); module.exports = { ...config, @@ -250,44 +281,52 @@ module.exports = { useLightningcss: ${useLightningcss} } }` - ) - }) + ) + }) - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) - it('should compile successfully', async () => { - const { code, stdout } = await nextBuild(appDir, [], { - stdout: true, + it('should compile successfully', async () => { + const { code, stdout } = await nextBuild(appDir, [], { + stdout: true, + }) + expect(code).toBe(0) + expect(stdout).toMatch(/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(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchSnapshot() + expect(cssFiles.length).toBe(1) + const cssContent = await readFile( + join(cssFolder, cssFiles[0]), + 'utf8' + ) + expect( + cssContent.replace(/\/\*.*?\*\//g, '').trim() + ).toMatchSnapshot() + }) }) - }) - }) + } + ) }) describe('CSS URL via `file-loader`', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - const appDir = join(fixturesDir, 'url-global') - const nextConfig = new File(join(appDir, 'next.config.js')) - - describe.each([true, false])(`useLightnincsss(%s)`, (useLightningcss) => { - beforeAll(async () => { - nextConfig.write( - ` + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + const appDir = join(fixturesDir, 'url-global') + const nextConfig = new File(join(appDir, 'next.config.js')) + + describe.each([true, false])(`useLightnincsss(%s)`, (useLightningcss) => { + beforeAll(async () => { + nextConfig.write( + ` const config = require('../next.config.js'); module.exports = { ...config, @@ -295,8 +334,63 @@ module.exports = { useLightningcss: ${useLightningcss} } }` - ) + ) + }) + + 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/) + }) + + it(`should've emitted expected files`, async () => { + const cssFolder = join(appDir, '.next/static/css') + const mediaFolder = join(appDir, '.next/static/media') + + 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() + ).toMatchSnapshot() + + const mediaFiles = await readdir(mediaFolder) + expect(mediaFiles.length).toBe(3) + expect( + mediaFiles + .map((fileName) => + /^(.+?)\..{8}\.(.+?)$/.exec(fileName).slice(1).join('.') + ) + .sort() + ).toMatchInlineSnapshot(` + [ + "dark.svg", + "dark2.svg", + "light.svg", + ] + `) + }) }) + } + ) +}) + +describe('CSS URL via `file-loader` and asset prefix (1)', () => { + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + const appDir = join(fixturesDir, 'url-global-asset-prefix-1') beforeAll(async () => { await remove(join(appDir, '.next')) @@ -319,7 +413,9 @@ module.exports = { expect(cssFiles.length).toBe(1) const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8') - expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatchSnapshot() + 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) @@ -330,109 +426,64 @@ module.exports = { ) .sort() ).toMatchInlineSnapshot(` - [ - "dark.svg", - "dark2.svg", - "light.svg", - ] - `) - }) - }) - }) -}) - -describe('CSS URL via `file-loader` and 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, - }) - 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') - - 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( - /^\.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(` [ "dark.svg", "dark2.svg", "light.svg", ] `) - }) - }) + }) + } + ) }) describe('CSS URL via `file-loader` and asset prefix (2)', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - const appDir = join(fixturesDir, 'url-global-asset-prefix-2') + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + const appDir = join(fixturesDir, 'url-global-asset-prefix-2') - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) - it('should compile successfully', async () => { - const { code, stdout } = await nextBuild(appDir, [], { - stdout: true, + it('should compile successfully', async () => { + const { code, stdout } = await nextBuild(appDir, [], { + stdout: true, + }) + expect(code).toBe(0) + expect(stdout).toMatch(/Compiled successfully/) }) - 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've emitted expected files`, async () => { + const cssFolder = join(appDir, '.next/static/css') + const mediaFolder = join(appDir, '.next/static/media') - 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(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\}$/ - ) + 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(` + const mediaFiles = await readdir(mediaFolder) + expect(mediaFiles.length).toBe(3) + expect( + mediaFiles + .map((fileName) => + /^(.+?)\..{8}\.(.+?)$/.exec(fileName).slice(1).join('.') + ) + .sort() + ).toMatchInlineSnapshot(` [ "dark.svg", "dark2.svg", "light.svg", ] `) - }) - }) + }) + } + ) }) diff --git a/test/integration/css/test/css-and-styled-jsx.test.js b/test/integration/css/test/css-and-styled-jsx.test.js index c2959aab05aa4..041dbbafbe152 100644 --- a/test/integration/css/test/css-and-styled-jsx.test.js +++ b/test/integration/css/test/css-and-styled-jsx.test.js @@ -37,37 +37,40 @@ describe('Ordering with styled-jsx (dev)', () => { }) describe('Ordering with styled-jsx (prod)', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - const appDir = join(fixturesDir, 'with-styled-jsx') + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + const appDir = join(fixturesDir, 'with-styled-jsx') - 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('.my-text')).color` - ) - expect(currentColor).toMatchInlineSnapshot(`"rgb(0, 128, 0)"`) - }) - }) + const currentColor = await browser.eval( + `window.getComputedStyle(document.querySelector('.my-text')).color` + ) + expect(currentColor).toMatchInlineSnapshot(`"rgb(0, 128, 0)"`) + }) + } + ) }) diff --git a/test/integration/css/test/css-compilation.test.js b/test/integration/css/test/css-compilation.test.js index 264161cc4fd16..3998a6299dd78 100644 --- a/test/integration/css/test/css-compilation.test.js +++ b/test/integration/css/test/css-compilation.test.js @@ -15,19 +15,23 @@ import { join } from 'path' const fixturesDir = join(__dirname, '../..', 'css-fixtures') describe('CSS Support', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - describe('CSS Compilation and Prefixing', () => { - const appDir = join(fixturesDir, 'compilation-and-prefixing') - const nextConfig = new File(join(appDir, 'next.config.js')) - - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + describe('CSS Compilation and Prefixing', () => { + const appDir = join(fixturesDir, 'compilation-and-prefixing') + const nextConfig = new File(join(appDir, 'next.config.js')) - describe.each([true, false])(`useLightnincsss(%s)`, (useLightningcss) => { beforeAll(async () => { - nextConfig.write( - ` + await remove(join(appDir, '.next')) + }) + + describe.each([true, false])( + `useLightnincsss(%s)`, + (useLightningcss) => { + beforeAll(async () => { + nextConfig.write( + ` const config = require('../next.config.js'); module.exports = { ...config, @@ -35,71 +39,135 @@ module.exports = { useLightningcss: ${useLightningcss} } }` - ) - }) - - afterAll(async () => { - nextConfig.delete() - }) - - it('should compile successfully', async () => { - const { code, stdout } = await nextBuild(appDir, [], { - stdout: true, - }) - expect(code).toBe(0) - expect(stdout).toMatch(/Compiled successfully/) - }) - - 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() - ).toMatchSnapshot() + ) + }) + + afterAll(async () => { + nextConfig.delete() + }) + + it('should compile successfully', async () => { + const { code, stdout } = await nextBuild(appDir, [], { + stdout: true, + }) + expect(code).toBe(0) + expect(stdout).toMatch(/Compiled successfully/) + }) + + 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() + ).toMatchSnapshot() + + // 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) + const cssMapContent = ( + await readFile(join(cssFolder, cssMapFiles[0]), 'utf8') + ).trim() + + const { version, mappings, sourcesContent } = + JSON.parse(cssMapContent) + expect({ version, mappings, sourcesContent }).toMatchSnapshot() + }) + } + ) + }) - // Contains a source map - expect(cssContent).toMatch( - /\/\*#\s*sourceMappingURL=(.+\.map)\s*\*\// - ) + describe('React Lifecyce Order (production)', () => { + const appDir = join(fixturesDir, 'transition-react') + const nextConfig = new File(join(appDir, 'next.config.js')) + beforeAll(async () => { + await remove(join(appDir, '.next')) }) - 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) - const cssMapContent = ( - await readFile(join(cssFolder, cssMapFiles[0]), 'utf8') - ).trim() - - const { version, mappings, sourcesContent } = - JSON.parse(cssMapContent) - expect({ version, mappings, sourcesContent }).toMatchSnapshot() - }) + describe.each([true, false])( + `useLightnincsss(%s)`, + (useLightningcss) => { + beforeAll(async () => { + nextConfig.write( + ` +const config = require('../next.config.js'); +module.exports = { + ...config, + experimental: { + useLightningcss: ${useLightningcss} + } +}` + ) + }) + + let appPort + let app + let code + let stdout + beforeAll(async () => { + ;({ 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 the correct color on mount after navigation', async () => { + let browser + try { + browser = await webdriver(appPort, '/') + + // Navigate to other: + await browser.waitForElementByCss('#link-other').click() + const text = await browser + .waitForElementByCss('#red-title') + .text() + expect(text).toMatchInlineSnapshot(`"rgb(255, 0, 0)"`) + } finally { + if (browser) { + await browser.close() + } + } + }) + } + ) }) - }) - describe('React Lifecyce Order (production)', () => { - const appDir = join(fixturesDir, 'transition-react') - const nextConfig = new File(join(appDir, 'next.config.js')) - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) + describe('Has CSS in computed styles in Production', () => { + const appDir = join(fixturesDir, 'multi-page') + const nextConfig = new File(join(appDir, 'next.config.js')) - describe.each([true, false])(`useLightnincsss(%s)`, (useLightningcss) => { - beforeAll(async () => { - nextConfig.write( - ` + describe.each([true, false])( + `useLightnincsss(%s)`, + (useLightningcss) => { + beforeAll(async () => { + nextConfig.write( + ` const config = require('../next.config.js'); module.exports = { ...config, @@ -107,55 +175,76 @@ module.exports = { useLightningcss: ${useLightningcss} } }` - ) - }) - - let appPort - let app - let code - let stdout - beforeAll(async () => { - ;({ 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 the correct color on mount after navigation', async () => { - let browser - try { - browser = await webdriver(appPort, '/') - - // Navigate to other: - await browser.waitForElementByCss('#link-other').click() - const text = await browser.waitForElementByCss('#red-title').text() - expect(text).toMatchInlineSnapshot(`"rgb(255, 0, 0)"`) - } finally { - if (browser) { - await browser.close() - } + ) + }) + + 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 CSS for page', async () => { + const browser = await webdriver(appPort, '/page2') + + const currentColor = await browser.eval( + `window.getComputedStyle(document.querySelector('.blue-text')).color` + ) + expect(currentColor).toMatchInlineSnapshot(`"rgb(0, 0, 255)"`) + }) + + it(`should've preloaded the CSS file and injected it in `, async () => { + const content = await renderViaHTTP(appPort, '/page2') + 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 cssSheet = $('link[rel="stylesheet"]') + expect(cssSheet.length).toBe(1) + expect(cssSheet.attr('href')).toMatch( + /^\/_next\/static\/css\/.*\.css$/ + ) + + /* ensure CSS preloaded first */ + const allPreloads = [].slice.call($('link[rel="preload"]')) + const styleIndexes = allPreloads.flatMap((p, i) => + p.attribs.as === 'style' ? i : [] + ) + expect(styleIndexes).toEqual([0]) + }) } - }) + ) }) - }) - describe('Has CSS in computed styles in Production', () => { - const appDir = join(fixturesDir, 'multi-page') - const nextConfig = new File(join(appDir, 'next.config.js')) + describe('Good CSS Import from node_modules', () => { + const appDir = join(fixturesDir, 'npm-import') + const nextConfig = new File(join(appDir, 'next.config.js')) - describe.each([true, false])(`useLightnincsss(%s)`, (useLightningcss) => { - beforeAll(async () => { - nextConfig.write( - ` + describe.each([true, false])( + `useLightnincsss(%s)`, + (useLightningcss) => { + beforeAll(async () => { + nextConfig.write( + ` const config = require('../next.config.js'); module.exports = { ...config, @@ -163,73 +252,50 @@ module.exports = { useLightningcss: ${useLightningcss} } }` - ) - }) - - 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 CSS for page', async () => { - const browser = await webdriver(appPort, '/page2') - - const currentColor = await browser.eval( - `window.getComputedStyle(document.querySelector('.blue-text')).color` - ) - expect(currentColor).toMatchInlineSnapshot(`"rgb(0, 0, 255)"`) - }) - - it(`should've preloaded the CSS file and injected it in `, async () => { - const content = await renderViaHTTP(appPort, '/page2') - 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 cssSheet = $('link[rel="stylesheet"]') - expect(cssSheet.length).toBe(1) - expect(cssSheet.attr('href')).toMatch( - /^\/_next\/static\/css\/.*\.css$/ - ) - - /* ensure CSS preloaded first */ - const allPreloads = [].slice.call($('link[rel="preload"]')) - const styleIndexes = allPreloads.flatMap((p, i) => - p.attribs.as === 'style' ? i : [] - ) - expect(styleIndexes).toEqual([0]) - }) + ) + }) + + 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/) + }) + + 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)) + + expect(cssFiles.length).toBe(1) + const cssContent = await readFile( + join(cssFolder, cssFiles[0]), + 'utf8' + ) + expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatch( + /nprogress/ + ) + }) + } + ) }) - }) - describe('Good CSS Import from node_modules', () => { - const appDir = join(fixturesDir, 'npm-import') - const nextConfig = new File(join(appDir, 'next.config.js')) + describe('Good Nested CSS Import from node_modules', () => { + const appDir = join(fixturesDir, 'npm-import-nested') + const nextConfig = new File(join(appDir, 'next.config.js')) - describe.each([true, false])(`useLightnincsss(%s)`, (useLightningcss) => { - beforeAll(async () => { - nextConfig.write( - ` + describe.each([true, false])( + `useLightnincsss(%s)`, + (useLightningcss) => { + beforeAll(async () => { + nextConfig.write( + ` const config = require('../next.config.js'); module.exports = { ...config, @@ -237,41 +303,49 @@ module.exports = { useLightningcss: ${useLightningcss} } }` - ) - }) - - 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/) - }) - - 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)) - - expect(cssFiles.length).toBe(1) - const cssContent = await readFile( - join(cssFolder, cssFiles[0]), - 'utf8' - ) - expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatch( - /nprogress/ - ) - }) + ) + }) + + 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/) + }) + + 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)) + + expect(cssFiles.length).toBe(1) + const cssContent = await readFile( + join(cssFolder, cssFiles[0]), + 'utf8' + ) + expect( + cssContent.replace(/\/\*.*?\*\//g, '').trim() + ).toMatchSnapshot() + }) + } + ) }) - }) + } + ) +}) - describe('Good Nested CSS Import from node_modules', () => { - const appDir = join(fixturesDir, 'npm-import-nested') +// https://github.com/vercel/next.js/issues/15468 +describe('CSS Property Ordering', () => { + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + const appDir = join(fixturesDir, 'next-issue-15468') const nextConfig = new File(join(appDir, 'next.config.js')) describe.each([true, false])(`useLightnincsss(%s)`, (useLightningcss) => { @@ -288,92 +362,41 @@ module.exports = { ) }) + 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 compile successfully', async () => { - const { code, stdout } = await nextBuild(appDir, [], { - stdout: true, - }) + 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 have the border width (property ordering)', async () => { + const browser = await webdriver(appPort, '/') - const files = await readdir(cssFolder) - const cssFiles = files.filter((f) => /\.css$/.test(f)) + const width1 = await browser.eval( + `window.getComputedStyle(document.querySelector('.test1')).borderWidth` + ) + expect(width1).toMatchInlineSnapshot(`"0px"`) - expect(cssFiles.length).toBe(1) - const cssContent = await readFile( - join(cssFolder, cssFiles[0]), - 'utf8' + const width2 = await browser.eval( + `window.getComputedStyle(document.querySelector('.test2')).borderWidth` ) - expect( - cssContent.replace(/\/\*.*?\*\//g, '').trim() - ).toMatchSnapshot() + expect(width2).toMatchInlineSnapshot(`"5px"`) }) }) - }) - }) -}) - -// https://github.com/vercel/next.js/issues/15468 -describe('CSS Property Ordering', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - const appDir = join(fixturesDir, 'next-issue-15468') - const nextConfig = new File(join(appDir, 'next.config.js')) - - describe.each([true, false])(`useLightnincsss(%s)`, (useLightningcss) => { - beforeAll(async () => { - nextConfig.write( - ` -const config = require('../next.config.js'); -module.exports = { - ...config, - experimental: { - useLightningcss: ${useLightningcss} - } -}` - ) - }) - - 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 the border width (property ordering)', async () => { - const browser = await webdriver(appPort, '/') - - const width1 = await browser.eval( - `window.getComputedStyle(document.querySelector('.test1')).borderWidth` - ) - expect(width1).toMatchInlineSnapshot(`"0px"`) - - const width2 = await browser.eval( - `window.getComputedStyle(document.querySelector('.test2')).borderWidth` - ) - expect(width2).toMatchInlineSnapshot(`"5px"`) - }) - }) - }) + } + ) }) diff --git a/test/integration/css/test/css-modules.test.js b/test/integration/css/test/css-modules.test.js index 4d22bb31a8f33..00e8487e97002 100644 --- a/test/integration/css/test/css-modules.test.js +++ b/test/integration/css/test/css-modules.test.js @@ -133,62 +133,69 @@ useLightningcss: ${useLightningcss} }) describe('should handle unresolved files gracefully', () => { - ;(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) - }) + ;(process.env.TURBOPACK_DEV ? 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 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', () => { - ;(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) - }) + ;(process.env.TURBOPACK_DEV ? 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 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:[^"]+"\)/ + ) + }) + } + ) }) describe('Ordering with Global CSS and Modules (dev)', () => { @@ -291,14 +298,16 @@ useLightningcss: ${useLightningcss} }) describe('Ordering with Global CSS and Modules (prod)', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - const appDir = join(fixturesDir, 'global-and-module-ordering') - const nextConfig = new File(join(appDir, 'next.config.js')) + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + const appDir = join(fixturesDir, 'global-and-module-ordering') + const nextConfig = new File(join(appDir, 'next.config.js')) - describe.each([true, false])(`useLightnincsss(%s)`, (useLightningcss) => { - beforeAll(async () => { - nextConfig.write( - ` + describe.each([true, false])(`useLightnincsss(%s)`, (useLightningcss) => { + beforeAll(async () => { + nextConfig.write( + ` const config = require('../next.config.js'); module.exports = { ...config, @@ -306,40 +315,41 @@ module.exports = { useLightningcss: ${useLightningcss} } }` - ) - }) + ) + }) - 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)"`) + }) }) - }) - }) + } + ) }) // https://github.com/vercel/next.js/issues/12445 @@ -513,7 +523,7 @@ module.exports = { tests(true) }) - ;(process.env.TURBOPACK ? describe.skip : describe)( + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( 'production mode', () => { beforeAll(async () => { diff --git a/test/integration/css/test/css-rendering.test.js b/test/integration/css/test/css-rendering.test.js index de3a27d0c5033..c9359eea9848a 100644 --- a/test/integration/css/test/css-rendering.test.js +++ b/test/integration/css/test/css-rendering.test.js @@ -15,15 +15,19 @@ import { join } from 'path' const fixturesDir = join(__dirname, '../..', 'css-fixtures') describe('CSS Support', () => { - ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { - describe('CSS Import from node_modules', () => { - const appDir = join(fixturesDir, 'npm-import-bad') - const nextConfig = new File(join(appDir, 'next.config.js')) - - describe.each([true, false])(`useLightnincsss(%s)`, (useLightningcss) => { - beforeAll(async () => { - nextConfig.write( - ` + ;(process.env.TURBOPACK_DEV ? describe.skip : describe)( + 'production mode', + () => { + describe('CSS Import from node_modules', () => { + const appDir = join(fixturesDir, 'npm-import-bad') + const nextConfig = new File(join(appDir, 'next.config.js')) + + describe.each([true, false])( + `useLightnincsss(%s)`, + (useLightningcss) => { + beforeAll(async () => { + nextConfig.write( + ` const config = require('../next.config.js'); module.exports = { ...config, @@ -31,22 +35,28 @@ module.exports = { useLightningcss: ${useLightningcss} } }` - ) - }) - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) - - 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/) - }) + ) + }) + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) + + 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/) + }) + } + ) }) - }) - }) + } + ) // https://github.com/vercel/next.js/issues/18557 describe('CSS page transition inject