From 59bda2d818bde7ff7dcea1aa46b28cbe046800f4 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Mon, 2 Oct 2023 15:55:23 +0200 Subject: [PATCH] More Turbopack fixes (#56299) Skips additional production-only tests. Follow-up to #56089. In this PR I went through all of `test/integration` looking for `nextBuild(` and added the skipping logic. --- .../500-page/test/gsp-gssp.test.js | 405 ++++----- test/integration/500-page/test/index.test.js | 507 +++++------ .../absolute-assetprefix/test/index.test.js | 178 ++-- .../amp-export-validation/test/index.test.js | 178 ++-- .../test/index.test.js | 74 +- .../test/index.test.js | 44 +- .../amphtml-fragment-style/test/index.test.js | 28 +- .../amphtml-ssg/test/index.test.js | 59 +- .../api-catch-all/test/index.test.js | 3 +- .../api-support/test/index.test.js | 3 +- .../app-dir-export/test/config.test.ts | 190 ++-- .../app-dir-export/test/start.test.ts | 70 +- .../test/index.test.js | 32 +- .../test/index.test.js | 36 +- .../app-dynamic-error/test/index.test.ts | 21 +- .../test/index.test.js | 4 +- .../build-output/test/index.test.js | 452 +++++----- .../test/index.test.js | 118 +-- .../test/index.test.js | 148 ++-- .../build-warnings/test/index.test.js | 120 +-- .../test/index.test.js | 25 +- test/integration/cli/test/index.test.js | 396 ++++----- .../config-promise-error/test/index.test.js | 26 +- .../config-syntax-error/test/index.test.js | 56 +- .../config-validation/test/index.test.ts | 64 +- .../test/index.test.js | 46 +- .../conflicting-ssg-paths/test/index.test.js | 156 ++-- .../critical-css/test/index.test.js | 36 +- .../integration/css-minify/test/index.test.js | 18 +- .../css-modules/test/index.test.js | 64 +- .../css/test/css-and-styled-jsx.test.js | 54 +- .../css/test/css-compilation.test.js | 386 +++++---- .../css/test/css-rendering.test.js | 22 +- .../test/index.test.js | 36 +- .../custom-server/test/index.test.js | 73 +- .../data-fetching-errors/test/index.test.js | 5 +- .../dedupes-scripts/test/index.test.js | 42 +- test/integration/dist-dir/test/index.test.js | 84 +- .../test/index.test.js | 202 +++-- .../test/module-imports.test.js | 108 ++- .../test/index.test.js | 32 +- .../error-in-error/test/index.test.js | 34 +- .../error-load-fail/test/index.test.js | 78 +- .../test/index.test.js | 49 +- .../test/index.test.js | 32 +- .../eslint/test/next-build.test.js | 280 +++--- .../integration/export-404/test/index.test.js | 52 +- .../export-default-map/test/index.test.js | 92 +- .../export-dynamic-pages/test/index.test.js | 9 +- .../test/index.test.js | 26 +- .../test/index.test.js | 14 +- .../export-image-default/test/index.test.js | 22 +- .../test/index.test.js | 238 +++--- .../test/index.test.ts | 18 +- .../test/index.test.js | 44 +- .../export-subfolders/test/index.test.js | 38 +- .../externals-pages-bundle/test/index.test.js | 16 +- .../fallback-modules/test/index.test.js | 86 +- .../test/index.test.js | 5 +- .../fetch-polyfill/test/index.test.js | 5 +- .../firebase-grpc/test/index.test.js | 48 +- test/integration/future/test/index.test.js | 30 +- .../gsp-extension/test/index.test.js | 66 +- .../test/index.test.js | 32 +- .../gssp-redirect/test/index.test.js | 32 +- .../handles-export-errors/test/index.test.js | 34 +- .../hydrate-then-render/test/index.test.js | 42 +- .../i18n-support-base-path/test/index.test.js | 179 ++-- .../i18n-support/test/index.test.js | 282 +++--- .../image-optimizer/test/index.test.ts | 222 ++--- .../invalid-config-values/test/index.test.js | 38 +- .../test/index.test.js | 46 +- .../test/index.test.js | 59 +- .../jsconfig-baseurl/test/index.test.js | 35 +- .../jsconfig-empty/test/index.test.js | 12 +- .../jsconfig-paths/test/index.test.js | 115 +-- test/integration/jsconfig/test/index.test.js | 40 +- .../test/index.test.js | 10 +- .../middleware-basic/test/index.test.js | 2 +- .../test/index.test.js | 110 +-- .../middleware-prefetch/tests/index.test.js | 104 +-- .../basic/test/index.test.ts | 220 ++--- .../custom-resolver/test/index.test.ts | 48 +- .../test/index.test.ts | 20 +- .../test/index.test.ts | 88 +- .../noscript/test/index.test.ts | 42 +- .../svgo-webpack/test/index.test.ts | 4 +- .../typescript/test/index.test.ts | 28 +- .../svgo-webpack/test/index.test.ts | 4 +- .../typescript/test/index.test.ts | 4 +- .../non-next-dist-exclude/test/index.test.js | 14 +- .../test/index.test.js | 91 +- .../numeric-sep/test/index.test.js | 18 +- .../page-config/test/index.test.js | 160 ++-- .../plugin-mdx-rs/test/index.test.js | 2 +- .../preload-viewport/test/index.test.js | 808 +++++++++--------- .../test/index.test.js | 14 +- .../test/index.test.js | 16 +- .../prerender-revalidate/test/index.test.js | 39 +- test/integration/prerender/test/index.test.js | 180 ++-- .../test/index.test.js | 42 +- .../react-profiling-mode/test/index.test.js | 94 +- .../test/index.test.js | 94 +- .../relay-analytics/test/index.test.js | 8 +- .../test/index.test.js | 42 +- .../with-get-initial-props/test/index.test.js | 42 +- .../test/index.test.js | 42 +- .../test/index.test.js | 9 +- .../script-loader/test/index.test.js | 58 +- .../scss-modules/test/dynamic-route.test.js | 180 ++-- .../scss-modules/test/valid-invalid.test.js | 234 ++--- .../scss/test/css-and-styled-jsx.test.js | 54 +- .../integration/static-404/test/index.test.js | 53 +- test/integration/telemetry/test/index.test.js | 55 +- .../telemetry/test/page-features.test.js | 270 +++--- .../test/index.test.js | 118 +-- .../typeof-window-replace/test/index.test.js | 92 +- .../test/index.test.js | 12 +- .../test/index.test.js | 14 +- .../test/index.test.js | 104 +-- .../integration/typescript/test/index.test.js | 77 +- .../test/index.test.js | 12 +- .../webpack-config-mainjs/test/index.test.js | 16 +- .../webpack-require-hook/test/index.test.js | 54 +- .../with-electron/test/index.test.js | 100 +-- .../with-router/test/index.test.js | 98 +-- .../plugin-config.test.ts | 2 +- 127 files changed, 5751 insertions(+), 5302 deletions(-) diff --git a/test/integration/500-page/test/gsp-gssp.test.js b/test/integration/500-page/test/gsp-gssp.test.js index fd5920bcc5741..ac89b66c051d3 100644 --- a/test/integration/500-page/test/gsp-gssp.test.js +++ b/test/integration/500-page/test/gsp-gssp.test.js @@ -22,217 +22,222 @@ const gip500Err = let appPort let app -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('does not show error with getStaticProps in pages/500 dev', async () => { - await fs.move(pages500, `${pages500}.bak`) - await fs.writeFile( - pages500, - ` +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, + ` const page = () => 'custom 500 page' export const getStaticProps = () => ({ props: { a: 'b' } }) export default page ` - ) - - let stderr = '' - appPort = await findPort() - app = await launchApp(appDir, appPort, { - onStderr(msg) { - stderr += msg || '' - }, - }) - await renderViaHTTP(appPort, '/abc') - await waitFor(1000) - - await killApp(app) - - await fs.remove(pages500) - await fs.move(`${pages500}.bak`, pages500) - - expect(stderr).not.toMatch(gip500Err) -}) - -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) -}) - -it('shows error with getServerSideProps in pages/500 dev', 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 - ` - ) - - let stderr = '' - appPort = await findPort() - app = await launchApp(appDir, appPort, { - onStderr(msg) { - stderr += msg || '' - }, - }) - await renderViaHTTP(appPort, '/500') - await waitFor(1000) - - await killApp(app) - - await fs.remove(pages500) - await fs.move(`${pages500}.bak`, pages500) - - expect(stderr).toMatch(gip500Err) -}) - -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, - ` - 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, 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) + }) + + 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, + ` + const page = () => { + console.log('rendered 500') + return 'custom 500 page' } - } - ` - ) - 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') -}) - -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 default page + + export const getStaticProps = () => { + return { + props: {} + } } - - export const getServerSideProps = ({ req, res, err }) => { - console.error('called _error getServerSideProps') - - if (req.url === '/500') { - throw new Error('should not export /500') + ` + ) + 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') + }) + + 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}

} - - return { - props: { - statusCode: res && res.statusCode ? res.statusCode : err ? err.statusCode : 404 + + 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 renderViaHTTP(appPort, '/err') + await killApp(app) + + expect(appStderr).toContain('called _error getServerSideProps') + }) + }) - export default Error + describe('development mode', () => { + it('does not show error with getStaticProps in pages/500 dev', 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: 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 || '' - }, - }) + ) + + let stderr = '' + appPort = await findPort() + app = await launchApp(appDir, appPort, { + onStderr(msg) { + stderr += msg || '' + }, + }) + await renderViaHTTP(appPort, '/abc') + await waitFor(1000) + + await killApp(app) + + await fs.remove(pages500) + await fs.move(`${pages500}.bak`, pages500) + + expect(stderr).not.toMatch(gip500Err) + }) + + it('shows error with getServerSideProps in pages/500 dev', 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 + ` + ) + + let stderr = '' + appPort = await findPort() + app = await launchApp(appDir, appPort, { + onStderr(msg) { + stderr += msg || '' + }, + }) + await renderViaHTTP(appPort, '/500') + await waitFor(1000) - await renderViaHTTP(appPort, '/err') - await killApp(app) + await killApp(app) - expect(appStderr).toContain('called _error getServerSideProps') + await fs.remove(pages500) + await fs.move(`${pages500}.bak`, pages500) + + expect(stderr).toMatch(gip500Err) + }) + }) }) diff --git a/test/integration/500-page/test/index.test.js b/test/integration/500-page/test/index.test.js index 7235d1e9d209c..8c8e3aa53f4d3 100644 --- a/test/integration/500-page/test/index.test.js +++ b/test/integration/500-page/test/index.test.js @@ -70,6 +70,36 @@ describe('500 Page Support', () => { runTests('dev') }) + describe('development mode 2', () => { + it('shows error with getInitialProps in pages/500 dev', async () => { + await fs.move(pages500, `${pages500}.bak`) + await fs.writeFile( + pages500, + ` + const page = () => 'custom 500 page' + page.getInitialProps = () => ({ a: 'b' }) + export default page + ` + ) + + let stderr = '' + appPort = await findPort() + app = await launchApp(appDir, appPort, { + onStderr(msg) { + stderr += msg || '' + }, + }) + await renderViaHTTP(appPort, '/500') + await waitFor(1000) + + await killApp(app) + + await fs.remove(pages500) + await fs.move(`${pages500}.bak`, pages500) + + expect(stderr).toMatch(gip500Err) + }) + }) ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { beforeAll(async () => { await fs.remove(join(appDir, '.next')) @@ -81,274 +111,249 @@ describe('500 Page Support', () => { runTests('server') }) - - it('does not build 500 statically with getInitialProps in _app', async () => { - await fs.writeFile( - pagesApp, + ;(process.env.TURBOPACK ? describe.skip : describe)( + 'production mode 2', + () => { + it('does not build 500 statically with getInitialProps in _app', async () => { + await fs.writeFile( + pagesApp, + ` + import App from 'next/app' + + const page = ({ Component, pageProps }) => + page.getInitialProps = (ctx) => App.getInitialProps(ctx) + export default page ` - import App from 'next/app' - - const page = ({ Component, pageProps }) => - page.getInitialProps = (ctx) => App.getInitialProps(ctx) - export default page - ` - ) - await fs.remove(join(appDir, '.next')) - const { - stderr, - stdout: buildStdout, - code, - } = await nextBuild(appDir, [], { - stderr: true, - stdout: true, - }) - - await fs.remove(pagesApp) - - expect(stderr).not.toMatch(gip500Err) - expect(buildStdout).not.toContain('rendered 500') - expect(code).toBe(0) - expect( - await fs.pathExists(join(appDir, '.next/server/pages/500.html')) - ).toBe(false) - - 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).toContain('rendered 500') - }) - - it('builds 500 statically by default with no pages/500', async () => { - await fs.rename(pages500, `${pages500}.bak`) - await fs.remove(join(appDir, '.next')) - const { stderr, code } = await nextBuild(appDir, [], { stderr: true }) - await fs.rename(`${pages500}.bak`, pages500) - - expect(stderr).not.toMatch(gip500Err) - expect(code).toBe(0) - expect( - await fs.pathExists(join(appDir, '.next/server/pages/500.html')) - ).toBe(true) - - const pagesManifest = await getPagesManifest(appDir) - await updatePagesManifest( - appDir, - JSON.stringify({ - ...pagesManifest, - '/500': pagesManifest['/404'].replace('/404', '/500'), + ) + await fs.remove(join(appDir, '.next')) + const { + stderr, + stdout: buildStdout, + code, + } = await nextBuild(appDir, [], { + stderr: true, + stdout: true, + }) + + await fs.remove(pagesApp) + + expect(stderr).not.toMatch(gip500Err) + expect(buildStdout).not.toContain('rendered 500') + expect(code).toBe(0) + expect( + await fs.pathExists(join(appDir, '.next/server/pages/500.html')) + ).toBe(false) + + 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).toContain('rendered 500') }) - ) - - // ensure static 500 hydrates correctly - const appPort = await findPort() - const app = await nextStart(appDir, appPort) - - try { - const browser = await webdriver(appPort, '/err?hello=world') - const initialTitle = await browser.eval('document.title') - const currentTitle = await browser.eval('document.title') - - expect(initialTitle).toBe(currentTitle) - expect(initialTitle).toBe('500: Internal Server Error') - } finally { - await killApp(app) - } - }) + it('builds 500 statically by default with no pages/500', async () => { + await fs.rename(pages500, `${pages500}.bak`) + await fs.remove(join(appDir, '.next')) + const { stderr, code } = await nextBuild(appDir, [], { stderr: true }) + await fs.rename(`${pages500}.bak`, pages500) + + expect(stderr).not.toMatch(gip500Err) + expect(code).toBe(0) + expect( + await fs.pathExists(join(appDir, '.next/server/pages/500.html')) + ).toBe(true) + + const pagesManifest = await getPagesManifest(appDir) + await updatePagesManifest( + appDir, + JSON.stringify({ + ...pagesManifest, + '/500': pagesManifest['/404'].replace('/404', '/500'), + }) + ) + + // ensure static 500 hydrates correctly + const appPort = await findPort() + const app = await nextStart(appDir, appPort) + + try { + const browser = await webdriver(appPort, '/err?hello=world') + const initialTitle = await browser.eval('document.title') + + const currentTitle = await browser.eval('document.title') + + expect(initialTitle).toBe(currentTitle) + expect(initialTitle).toBe('500: Internal Server Error') + } finally { + await killApp(app) + } + }) - it('builds 500 statically by default with no pages/500 and custom _error without getInitialProps', async () => { - await fs.rename(pages500, `${pages500}.bak`) - await fs.writeFile( - pagesError, - ` + it('builds 500 statically by default with no pages/500 and custom _error without getInitialProps', async () => { + await fs.rename(pages500, `${pages500}.bak`) + await fs.writeFile( + pagesError, + ` function Error({ statusCode }) { return

Error status: {statusCode}

} 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(true) - }) - - it('does not build 500 statically with no pages/500 and custom getInitialProps in _error', async () => { - await fs.rename(pages500, `${pages500}.bak`) - await fs.writeFile( - pagesError, - ` - function Error({ statusCode }) { - return

Error status: {statusCode}

- } - - Error.getInitialProps = ({ req, res, err }) => { - console.error('called _error.getInitialProps') + ) + 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(true) + }) - if (req.url === '/500') { - throw new Error('should not export /500') + it('does not build 500 statically with no pages/500 and custom getInitialProps in _error', async () => { + await fs.rename(pages500, `${pages500}.bak`) + await fs.writeFile( + pagesError, + ` + function Error({ statusCode }) { + return

Error status: {statusCode}

} - - return { - statusCode: res && res.statusCode ? res.statusCode : err ? err.statusCode : 404 + + 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 - ` - ) - 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.getInitialProps') - }) - - it('does not build 500 statically with no pages/500 and custom getInitialProps in _error and _app', async () => { - await fs.rename(pages500, `${pages500}.bak`) - await fs.writeFile( - pagesError, - ` - function Error({ statusCode }) { - return

Error status: {statusCode}

- } - - Error.getInitialProps = ({ req, res, err }) => { - console.error('called _error.getInitialProps') + + 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 renderViaHTTP(appPort, '/err') + await killApp(app) + + expect(appStderr).toContain('called _error.getInitialProps') + }) - if (req.url === '/500') { - throw new Error('should not export /500') + it('does not build 500 statically with no pages/500 and custom getInitialProps in _error and _app', async () => { + await fs.rename(pages500, `${pages500}.bak`) + await fs.writeFile( + pagesError, + ` + function Error({ statusCode }) { + return

Error status: {statusCode}

} - - return { - statusCode: res && res.statusCode ? res.statusCode : err ? err.statusCode : 404 + + 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 - ` - ) - await fs.writeFile( - pagesApp, - ` - 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) + + export default Error + ` + ) + await fs.writeFile( + pagesApp, + ` + 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 + ` + ) + 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) + await fs.remove(pagesApp) + 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) + }) - return { pageProps } - } - - export default App - ` - ) - 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) - await fs.remove(pagesApp) - 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) - }) - - it('shows error with getInitialProps in pages/500 build', async () => { - await fs.move(pages500, `${pages500}.bak`) - await fs.writeFile( - pages500, - ` - const page = () => 'custom 500 page' - page.getInitialProps = () => ({ 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) - }) - - it('shows error with getInitialProps in pages/500 dev', async () => { - await fs.move(pages500, `${pages500}.bak`) - await fs.writeFile( - pages500, + it('shows error with getInitialProps in pages/500 build', async () => { + await fs.move(pages500, `${pages500}.bak`) + await fs.writeFile( + pages500, + ` + const page = () => 'custom 500 page' + page.getInitialProps = () => ({ a: 'b' }) + export default page ` - const page = () => 'custom 500 page' - page.getInitialProps = () => ({ a: 'b' }) - export default page - ` - ) - - let stderr = '' - appPort = await findPort() - app = await launchApp(appDir, appPort, { - onStderr(msg) { - stderr += msg || '' - }, - }) - await renderViaHTTP(appPort, '/500') - await waitFor(1000) - - await killApp(app) - - await fs.remove(pages500) - await fs.move(`${pages500}.bak`, pages500) - - expect(stderr).toMatch(gip500Err) - }) + ) + 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) + }) + } + ) }) diff --git a/test/integration/absolute-assetprefix/test/index.test.js b/test/integration/absolute-assetprefix/test/index.test.js index 4bfcc00320c80..d6b1ff4ad39fb 100644 --- a/test/integration/absolute-assetprefix/test/index.test.js +++ b/test/integration/absolute-assetprefix/test/index.test.js @@ -19,103 +19,105 @@ let cdnAccessLog = [] const nextConfig = new File(path.resolve(__dirname, '../next.config.js')) describe('absolute assetPrefix with path prefix', () => { - 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 ? 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 07a0dc1d14086..fb97a00e7d924 100644 --- a/test/integration/amp-export-validation/test/index.test.js +++ b/test/integration/amp-export-validation/test/index.test.js @@ -13,114 +13,116 @@ const nextConfig = new File(join(appDir, 'next.config.js')) let buildOutput describe('AMP Validation on Export', () => { - beforeAll(async () => { - const { stdout = '', stderr = '' } = await nextBuild(appDir, [], { - stdout: true, - stderr: true, + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + beforeAll(async () => { + const { stdout = '', stderr = '' } = await nextBuild(appDir, [], { + stdout: true, + stderr: true, + }) + await nextExport(appDir, { outdir: outDir }, { ignoreFail: true }) + buildOutput = stdout + stderr }) - await nextExport(appDir, { outdir: outDir }, { ignoreFail: true }) - 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'\./ - ) - }) + it('should have shown errors during build', async () => { + expect(buildOutput).toMatch( + /error.*The mandatory attribute 'height' is missing in tag 'amp-video'\./ + ) + }) - it('should export AMP pages', async () => { - const toCheck = ['first', 'second', 'third.amp'] - await Promise.all( - toCheck.map(async (page) => { - const content = await readFile(join(outDir, `${page}.html`)) - await validateAMP(content.toString()) - }) - ) - }) + it('should export AMP pages', async () => { + const toCheck = ['first', 'second', 'third.amp'] + await Promise.all( + toCheck.map(async (page) => { + const content = await readFile(join(outDir, `${page}.html`)) + await validateAMP(content.toString()) + }) + ) + }) - // 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 4f0ef3f8721e3..3c2126676a5fd 100644 --- a/test/integration/amphtml-custom-optimizer/test/index.test.js +++ b/test/integration/amphtml-custom-optimizer/test/index.test.js @@ -14,41 +14,43 @@ let appPort const appDir = join(__dirname, '../') describe('AMP Custom Optimizer', () => { - 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 ? 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 223a192811202..d531b773e84d8 100644 --- a/test/integration/amphtml-custom-validator/test/index.test.js +++ b/test/integration/amphtml-custom-validator/test/index.test.js @@ -15,33 +15,37 @@ let appPort const appDir = join(__dirname, '../') describe('AMP Custom Validator', () => { - it('should build and start successfully', async () => { - const { code } = await nextBuild(appDir) - expect(code).toBe(0) + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + it('should build and start successfully', async () => { + const { code } = await nextBuild(appDir) + expect(code).toBe(0) - appPort = await findPort() - app = await nextStart(appDir, appPort) + appPort = await findPort() + app = await nextStart(appDir, appPort) - const html = await renderViaHTTP(appPort, '/') - await killApp(app) + const html = await renderViaHTTP(appPort, '/') + await killApp(app) - expect(html).toContain('Hello from AMP') + expect(html).toContain('Hello from AMP') + }) }) - it('should run in dev mode successfully', async () => { - let stderr = '' + describe('development mode', () => { + it('should run in dev mode successfully', async () => { + let stderr = '' - appPort = await findPort() - app = await launchApp(appDir, appPort, { - onStderr(msg) { - stderr += msg || '' - }, - }) + appPort = await findPort() + app = await launchApp(appDir, appPort, { + onStderr(msg) { + stderr += msg || '' + }, + }) - const html = await renderViaHTTP(appPort, '/') - await killApp(app) + const html = await renderViaHTTP(appPort, '/') + await killApp(app) - expect(stderr).not.toContain('error') - expect(html).toContain('Hello from AMP') + expect(stderr).not.toContain('error') + expect(html).toContain('Hello from AMP') + }) }) }) diff --git a/test/integration/amphtml-fragment-style/test/index.test.js b/test/integration/amphtml-fragment-style/test/index.test.js index e7e83e705316d..817ac7655abbc 100644 --- a/test/integration/amphtml-fragment-style/test/index.test.js +++ b/test/integration/amphtml-fragment-style/test/index.test.js @@ -16,19 +16,21 @@ let appPort let app describe('AMP Fragment Styles', () => { - beforeAll(async () => { - await nextBuild(appDir, []) - appPort = await findPort() - app = await nextStart(appDir, appPort) - }) - afterAll(() => killApp(app)) + ;(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('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 6bd9f6e071acf..10a5872003088 100644 --- a/test/integration/amphtml-ssg/test/index.test.js +++ b/test/integration/amphtml-ssg/test/index.test.js @@ -118,32 +118,37 @@ describe('AMP SSG Support', () => { runTests(true) }) describe('export mode', () => { - let buildId - - beforeAll(async () => { - await nextBuild(appDir) - await nextExport(appDir, { outdir: join(appDir, 'out') }) - buildId = await fs.readFile(join(appDir, '.next/BUILD_ID'), 'utf8') - }) - - it('should have copied SSG files correctly', async () => { - const outFile = (file) => join(appDir, 'out', file) - - expect(await fsExists(outFile('amp.html'))).toBe(true) - expect(await fsExists(outFile('index.html'))).toBe(true) - expect(await fsExists(outFile('hybrid.html'))).toBe(true) - expect(await fsExists(outFile('amp.amp.html'))).toBe(false) - expect(await fsExists(outFile('hybrid.amp.html'))).toBe(true) - expect(await fsExists(outFile('blog/post-1.html'))).toBe(true) - expect(await fsExists(outFile('blog/post-1.amp.html'))).toBe(true) - - expect( - await fsExists(outFile(join('_next/data', buildId, 'amp.json'))) - ).toBe(true) - - expect( - await fsExists(outFile(join('_next/data', buildId, 'hybrid.json'))) - ).toBe(true) - }) + ;(process.env.TURBOPACK ? describe.skip : describe)( + 'production mode', + () => { + let buildId + + beforeAll(async () => { + await nextBuild(appDir) + await nextExport(appDir, { outdir: join(appDir, 'out') }) + buildId = await fs.readFile(join(appDir, '.next/BUILD_ID'), 'utf8') + }) + + it('should have copied SSG files correctly', async () => { + const outFile = (file) => join(appDir, 'out', file) + + expect(await fsExists(outFile('amp.html'))).toBe(true) + expect(await fsExists(outFile('index.html'))).toBe(true) + expect(await fsExists(outFile('hybrid.html'))).toBe(true) + expect(await fsExists(outFile('amp.amp.html'))).toBe(false) + expect(await fsExists(outFile('hybrid.amp.html'))).toBe(true) + expect(await fsExists(outFile('blog/post-1.html'))).toBe(true) + expect(await fsExists(outFile('blog/post-1.amp.html'))).toBe(true) + + expect( + await fsExists(outFile(join('_next/data', buildId, 'amp.json'))) + ).toBe(true) + + expect( + await fsExists(outFile(join('_next/data', buildId, 'hybrid.json'))) + ).toBe(true) + }) + } + ) }) }) diff --git a/test/integration/api-catch-all/test/index.test.js b/test/integration/api-catch-all/test/index.test.js index 696465cdc0c6c..90bc7e3d4ccab 100644 --- a/test/integration/api-catch-all/test/index.test.js +++ b/test/integration/api-catch-all/test/index.test.js @@ -59,8 +59,7 @@ describe('API routes', () => { runTests() }) - - describe('Server support', () => { + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { beforeAll(async () => { await nextBuild(appDir) appPort = await findPort() diff --git a/test/integration/api-support/test/index.test.js b/test/integration/api-support/test/index.test.js index 9da3ebe17ef24..a96921782adee 100644 --- a/test/integration/api-support/test/index.test.js +++ b/test/integration/api-support/test/index.test.js @@ -643,8 +643,7 @@ describe('API routes', () => { runTests(true) }) - - describe('Server support', () => { + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { beforeAll(async () => { await nextBuild(appDir) mode = 'server' diff --git a/test/integration/app-dir-export/test/config.test.ts b/test/integration/app-dir-export/test/config.test.ts index 80c78bd7c53f2..79e5c8456905d 100644 --- a/test/integration/app-dir-export/test/config.test.ts +++ b/test/integration/app-dir-export/test/config.test.ts @@ -11,85 +11,54 @@ import { } from './utils' describe('app dir with output export (next dev / next build)', () => { - it('should throw when exportPathMap configured', async () => { - nextConfig.replace( - 'trailingSlash: true,', - `trailingSlash: true, + ;(process.env.TURBOPACK ? 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 warn about "next export" is no longer needed with config', async () => { - await fs.remove(distDir) - await fs.remove(exportDir) - await nextBuild(appDir) - expect(await getFiles()).toEqual(expectedWhenTrailingSlashTrue) - let stdout = '' - let stderr = '' - await nextExportDefault(appDir, { - onStdout(msg) { - stdout += msg - }, - onStderr(msg) { - stderr += msg - }, + ) + 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.' + ) }) - expect(stderr).toContain( - '"next export" is no longer needed when "output: export" is configured in next.config.js' - ) - expect(stdout).toContain('Export successful. Files written to') - expect(await getFiles()).toEqual(expectedWhenTrailingSlashTrue) - }) - it('should error when "next export -o " is used with config', async () => { - await fs.remove(distDir) - await fs.remove(exportDir) - await nextBuild(appDir) - expect(await getFiles()).toEqual(expectedWhenTrailingSlashTrue) - let stdout = '' - let stderr = '' - let error = undefined - try { - await nextExport( - appDir, - { outdir: exportDir }, - { - onStdout(msg) { - stdout += msg - }, - onStderr(msg) { - stderr += msg - }, - } + it('should warn about "next export" is no longer needed with config', async () => { + await fs.remove(distDir) + await fs.remove(exportDir) + await nextBuild(appDir) + expect(await getFiles()).toEqual(expectedWhenTrailingSlashTrue) + let stdout = '' + let stderr = '' + await nextExportDefault(appDir, { + onStdout(msg) { + stdout += msg + }, + onStderr(msg) { + stderr += msg + }, + }) + expect(stderr).toContain( + '"next export" is no longer needed when "output: export" is configured in next.config.js' ) - } catch (e) { - error = e - } - expect(error).toBeDefined() - expect(stderr).toContain( - '"next export -o " cannot be used when "output: export" is configured in next.config.js. Instead add "distDir" in next.config.js' - ) - expect(stdout).not.toContain('Export successful. Files written to') - }) - it('should error when no config.output detected for next export', async () => { - await fs.remove(distDir) - await fs.remove(exportDir) - nextConfig.replace(`output: 'export',`, '') - try { + expect(stdout).toContain('Export successful. Files written to') + expect(await getFiles()).toEqual(expectedWhenTrailingSlashTrue) + }) + it('should error when "next export -o " is used with config', async () => { + await fs.remove(distDir) + await fs.remove(exportDir) await nextBuild(appDir) - expect(await getFiles()).toEqual([]) + expect(await getFiles()).toEqual(expectedWhenTrailingSlashTrue) let stdout = '' let stderr = '' let error = undefined @@ -111,32 +80,65 @@ describe('app dir with output export (next dev / next build)', () => { } expect(error).toBeDefined() expect(stderr).toContain( - '"next export" does not work with App Router. Please use "output: export" in next.config.js' + '"next export -o " cannot be used when "output: export" is configured in next.config.js. Instead add "distDir" in next.config.js' ) expect(stdout).not.toContain('Export successful. Files written to') - expect(await getFiles()).toEqual([]) - } finally { - nextConfig.restore() + }) + it('should error when no config.output detected for 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.replace(`output: 'export',`, '') + try { + await nextBuild(appDir) + expect(await getFiles()).toEqual([]) + let stdout = '' + let stderr = '' + let error = undefined + try { + await nextExport( + appDir, + { outdir: exportDir }, + { + onStdout(msg) { + stdout += msg + }, + onStderr(msg) { + stderr += msg + }, + } + ) + } catch (e) { + error = e + } + expect(error).toBeDefined() + expect(stderr).toContain( + '"next export" does not work with App Router. Please use "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/start.test.ts b/test/integration/app-dir-export/test/start.test.ts index 895f25857930c..b7d5241493c13 100644 --- a/test/integration/app-dir-export/test/start.test.ts +++ b/test/integration/app-dir-export/test/start.test.ts @@ -18,43 +18,45 @@ const nextConfig = new File(join(appDir, 'next.config.js')) let app describe('app dir with output export (next start)', () => { - afterEach(async () => { - await killApp(app) - nextConfig.restore() - await fs.remove(distDir) - await fs.remove(exportDir) - }) + ;(process.env.TURBOPACK ? 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-document-import-order/test/index.test.js b/test/integration/app-document-import-order/test/index.test.js index 3ea0197c9a3ec..4850182812c23 100644 --- a/test/integration/app-document-import-order/test/index.test.js +++ b/test/integration/app-document-import-order/test/index.test.js @@ -51,24 +51,26 @@ const respectsChunkAttachmentOrder = async () => { } describe('Root components import order', () => { - beforeAll(async () => { - await nextBuild(appDir) - appPort = await findPort() - app = await nextStart(appDir, appPort) + ;(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 + ) }) - 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('on dev server', () => { +describe('development mode', () => { beforeAll(async () => { appPort = await findPort() app = await launchApp(join(__dirname, '../'), appPort) 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 4d31d5a3693da..3b81191139ab6 100644 --- a/test/integration/app-document-style-fragment/test/index.test.js +++ b/test/integration/app-document-style-fragment/test/index.test.js @@ -16,25 +16,27 @@ let server let app describe('Custom Document Fragment Styles', () => { - beforeAll(async () => { - await nextBuild(appDir) - app = nextServer({ - dir: join(__dirname, '../'), - dev: false, - quiet: true, - }) + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + beforeAll(async () => { + await nextBuild(appDir) + app = nextServer({ + dir: join(__dirname, '../'), + dev: false, + quiet: true, + }) - server = await startApp(app) - appPort = server.address().port - }) - afterAll(() => stopApp(server)) + 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 c2cff266fc489..1215ef263b3df 100644 --- a/test/integration/app-dynamic-error/test/index.test.ts +++ b/test/integration/app-dynamic-error/test/index.test.ts @@ -1,12 +1,17 @@ import { nextBuild } from 'next-test-utils' import { join } from 'path' - -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, +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, + }) + 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/basepath-root-catch-all/test/index.test.js b/test/integration/basepath-root-catch-all/test/index.test.js index 3361256d9c914..1e3d0d955fd7e 100644 --- a/test/integration/basepath-root-catch-all/test/index.test.js +++ b/test/integration/basepath-root-catch-all/test/index.test.js @@ -27,8 +27,10 @@ const runTests = () => { }) } -describe('dev mode', () => { +// Skip as it runs `next build`, seems that is a bug. +;(process.env.TURBOPACK ? describe.skip : describe)('dev mode', () => { beforeAll(async () => { + // TODO: This look like a bug, `nextBuild` shouldn't be required here. await nextBuild(appDir) appPort = await findPort() buildId = 'development' diff --git a/test/integration/build-output/test/index.test.js b/test/integration/build-output/test/index.test.js index aa5c135d49541..c33bae18a76c2 100644 --- a/test/integration/build-output/test/index.test.js +++ b/test/integration/build-output/test/index.test.js @@ -11,284 +11,288 @@ const fixturesDir = join(__dirname, '..', 'fixtures') const nextConfig = new File(join(fixturesDir, 'basic-app/next.config.js')) describe('Build Output', () => { - 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 ? 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/ - ) + 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('') + expect(stdout).not.toContain(' /_document') + expect(stdout).not.toContain(' /_app') + expect(stdout).not.toContain(' /_error') + expect(stdout).not.toContain('') - expect(stdout).toContain('○ /') - }) + expect(stdout).toContain('○ /') + }) - // TODO: change format of this test to be more reliable - it.skip('should not deviate from snapshot', async () => { - console.log(stdout) + // TODO: change format of this test to be more reliable + it.skip('should not deviate from snapshot', async () => { + console.log(stdout) - if (process.env.NEXT_PRIVATE_SKIP_SIZE_TESTS) { - return - } - - 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).not.toContain(' /_document') - expect(stdout).not.toContain(' /_app') - expect(stdout).not.toContain('') + 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(' /_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('') }) }) }) 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 9cbcfc20ce0fa..7afd802ddd006 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,67 +7,71 @@ import { nextBuild } from 'next-test-utils' const appDir = join(__dirname, '../app') describe('build trace with extra entries', () => { - 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') - ) + ;(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 tracedFiles = [ - ...appTrace.files, - ...indexTrace.files, - ...anotherTrace.files, - ...imageTrace.files, - ] + 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') + ) - 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) + 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 ) - ).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') + + 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 ) - ).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 e14cc432195f4..e75a0bf119911 100644 --- a/test/integration/build-trace-extra-entries/test/index.test.js +++ b/test/integration/build-trace-extra-entries/test/index.test.js @@ -7,81 +7,87 @@ import { nextBuild } from 'next-test-utils' const appDir = join(__dirname, '../app') describe('build trace with extra entries', () => { - 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') - ) + ;(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) - expect(appTrace.files.some((file) => file.endsWith('hello.json'))).toBe( - true - ) - 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 appTrace = await fs.readJSON( + join(appDir, '.next/server/pages/_app.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') - ).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') + 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') ) - ).toBe(true) - expect( - anotherTrace.files.some((file) => - file.includes('nested-structure/package.json') + const imageTrace = await fs.readJSON( + join(appDir, '.next/server/pages/image-import.js.nft.json') ) - ).toBe(true) - expect( - anotherTrace.files.some((file) => - file.includes('nested-structure/dist/constants.js') + + expect(appTrace.files.some((file) => file.endsWith('hello.json'))).toBe( + true + ) + 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 ) - ).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( + 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 d9a51350a7e0a..8ea63d4207387 100644 --- a/test/integration/build-warnings/test/index.test.js +++ b/test/integration/build-warnings/test/index.test.js @@ -7,83 +7,85 @@ import { join } from 'path' const appDir = join(__dirname, '../') describe('Build warnings', () => { - it('should not shown warning about minification withou any modification', async () => { - const { stderr } = await nextBuild(appDir, undefined, { stderr: true }) - expect(stderr).not.toContain('optimization has been disabled') - }) + ;(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')) + it('should shown warning about minification for minimize', async () => { + const nextConfig = new File(join(appDir, 'next.config.js')) - await waitFor(500) + await waitFor(500) - nextConfig.replace('true', 'false') + nextConfig.replace('true', 'false') - const { stderr } = await nextBuild(appDir, undefined, { stderr: true }) + const { stderr } = await nextBuild(appDir, undefined, { stderr: true }) - expect(stderr).toContain('optimization has been disabled') + expect(stderr).toContain('optimization has been disabled') - nextConfig.restore() - }) + nextConfig.restore() + }) - it('should shown warning about minification for minimizer', async () => { - const nextConfig = new File(join(appDir, 'next.config.js')) + it('should shown warning about minification for minimizer', async () => { + const nextConfig = new File(join(appDir, 'next.config.js')) - await waitFor(500) + await waitFor(500) - nextConfig.replace( - 'config.optimization.minimize = true', - 'config.optimization.minimizer = []' - ) + nextConfig.replace( + 'config.optimization.minimize = true', + 'config.optimization.minimizer = []' + ) - const { stderr } = await nextBuild(appDir, undefined, { stderr: true }) + const { stderr } = await nextBuild(appDir, undefined, { stderr: true }) - expect(stderr).toContain('optimization has been disabled') + expect(stderr).toContain('optimization has been disabled') - nextConfig.restore() - }) + nextConfig.restore() + }) - 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: '', - }, + 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 d8ffd2fe8b964..fbbe018644ca1 100644 --- a/test/integration/catches-missing-getStaticProps/test/index.test.js +++ b/test/integration/catches-missing-getStaticProps/test/index.test.js @@ -13,19 +13,22 @@ const appDir = join(__dirname, '../') const errorRegex = /getStaticPaths was added without a getStaticProps in/ describe('Catches Missing getStaticProps', () => { - it('should catch it in dev mode', async () => { - const appPort = await findPort() - const app = await launchApp(appDir, appPort) - const html = await renderViaHTTP(appPort, '/hello') - await killApp(app) + describe('development mode', () => { + it('should catch it in dev mode', async () => { + const appPort = await findPort() + const app = await launchApp(appDir, appPort) + const html = await renderViaHTTP(appPort, '/hello') + await killApp(app) - expect(html).toMatch(errorRegex) + expect(html).toMatch(errorRegex) + }) }) - - it('should catch it in server build mode', async () => { - const { stderr } = await nextBuild(appDir, [], { - stderr: true, + ;(process.env.TURBOPACK ? 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/cli/test/index.test.js b/test/integration/cli/test/index.test.js index 4c9f9bac53e9f..94343b3f4fc04 100644 --- a/test/integration/cli/test/index.test.js +++ b/test/integration/cli/test/index.test.js @@ -80,200 +80,235 @@ const testExitSignal = async ( } describe('CLI Usage', () => { - 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 ? 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:/ + ) + }) + 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:/ + ) }) - 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('--help', async () => { + const help = await runNextCommand(['start', '--help'], { + stdout: true, + }) + expect(help.stdout).toMatch(/Starts the application in production mode/) }) - const port = await findPort() - await testExitSignal( - 'SIGTERM', - ['start', dirBasic, '-p', port], - /- Local:/ - ) - }) - test('--help', async () => { - const help = await runNextCommand(['start', '--help'], { - stdout: true, + test('-h', async () => { + const help = await runNextCommand(['start', '-h'], { + stdout: true, + }) + expect(help.stdout).toMatch(/Starts the application 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 + }, + } + ) + + 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) + } }) - expect(help.stdout).toMatch(/Starts the application in production mode/) - }) - test('-h', async () => { - const help = await runNextCommand(['start', '-h'], { - stdout: true, + test('should warn when unknown argument provided', async () => { + const { stderr } = await runNextCommand(['start', '--random'], { + stderr: true, + }) + expect(stderr).toEqual('Unknown or unexpected option: --random\n') + }) + test('should not throw UnhandledPromiseRejectionWarning', async () => { + const { stderr } = await runNextCommand(['start', '--random'], { + stderr: true, + }) + expect(stderr).not.toContain('UnhandledPromiseRejectionWarning') }) - expect(help.stdout).toMatch(/Starts the application in production mode/) - }) - test('should format IPv6 addresses correctly', async () => { - await nextBuild(dirBasic) - const port = await findPort() + test('duplicate sass deps', async () => { + const port = await findPort() - let stdout = '' - const app = await runNextCommandDev( - ['start', dirBasic, '--hostname', '::', '--port', port], - undefined, - { - nextStart: true, - onStdout(msg) { - stdout += msg + 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(() => {}) } - ) + }) - 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('invalid directory', async () => { + const output = await runNextCommand(['start', 'non-existent'], { + stderr: true, }) - } finally { - await killApp(app) - } - }) + expect(output.stderr).toContain( + 'Invalid project directory provided, no such directory' + ) + }) - test('should warn when unknown argument provided', async () => { - const { stderr } = await runNextCommand(['start', '--random'], { - stderr: true, + test('--keepAliveTimeout string arg', async () => { + const { stderr } = await runNextCommand( + ['start', '--keepAliveTimeout', 'string'], + { + stderr: true, + } + ) + expect(stderr).toContain( + 'Invalid --keepAliveTimeout, expected a non negative number but received "NaN"' + ) }) - expect(stderr).toEqual('Unknown or unexpected option: --random\n') - }) - test('should not throw UnhandledPromiseRejectionWarning', async () => { - const { stderr } = await runNextCommand(['start', '--random'], { - stderr: true, + + test('--keepAliveTimeout negative number', async () => { + const { stderr } = await runNextCommand( + ['start', '--keepAliveTimeout=-100'], + { + stderr: true, + } + ) + expect(stderr).toContain( + 'Invalid --keepAliveTimeout, expected a non negative number but received "-100"' + ) }) - expect(stderr).not.toContain('UnhandledPromiseRejectionWarning') - }) - test('duplicate sass deps', async () => { - const port = await findPort() + test('--keepAliveTimeout Infinity', async () => { + const { stderr } = await runNextCommand( + ['start', '--keepAliveTimeout', 'Infinity'], + { + stderr: true, + } + ) + expect(stderr).toContain( + 'Invalid --keepAliveTimeout, expected a non negative number but received "Infinity"' + ) + }) - let stderr = '' - let instance = await launchApp(dirDuplicateSass, port, { - stderr: true, - onStderr(msg) { - stderr += msg - }, + test('--keepAliveTimeout happy path', async () => { + const { stderr } = await runNextCommand( + ['start', '--keepAliveTimeout', '100'], + { + stderr: true, + } + ) + expect(stderr).not.toContain( + 'Invalid keep alive timeout provided, expected a non negative number' + ) }) - try { - await check(() => stderr, /both `sass` and `node-sass` installed/) - } finally { - await killApp(instance).catch(() => {}) - } - }) + test('should not start on a port out of range', async () => { + const invalidPort = '300001' + const { stderr } = await runNextCommand( + ['start', '--port', invalidPort], + { + stderr: true, + } + ) - test('invalid directory', async () => { - const output = await runNextCommand(['start', 'non-existent'], { - stderr: true, + expect(stderr).toContain(`options.port should be >= 0 and < 65536.`) }) - expect(output.stderr).toContain( - 'Invalid project directory provided, no such directory' - ) - }) - test('--keepAliveTimeout string arg', async () => { - const { stderr } = await runNextCommand( - ['start', '--keepAliveTimeout', 'string'], - { - stderr: true, - } - ) - expect(stderr).toContain( - 'Invalid --keepAliveTimeout, expected a non negative number but received "NaN"' - ) - }) + test('should not start on a reserved port', async () => { + const reservedPort = '4045' + const { stderr } = await runNextCommand( + ['start', '--port', reservedPort], + { + stderr: true, + } + ) - test('--keepAliveTimeout negative number', async () => { - const { stderr } = await runNextCommand( - ['start', '--keepAliveTimeout=-100'], - { - stderr: true, - } - ) - expect(stderr).toContain( - 'Invalid --keepAliveTimeout, expected a non negative number but received "-100"' - ) + expect(stderr).toContain( + `Bad port: "${reservedPort}" is reserved for npp` + ) + }) }) - test('--keepAliveTimeout Infinity', async () => { - const { stderr } = await runNextCommand( - ['start', '--keepAliveTimeout', 'Infinity'], - { - stderr: true, - } - ) - expect(stderr).toContain( - 'Invalid --keepAliveTimeout, expected a non negative number but received "Infinity"' - ) - }) + describe('telemetry', () => { + test('--help', async () => { + const help = await runNextCommand(['telemetry', '--help'], { + stdout: true, + }) + expect(help.stdout).toMatch( + /Allows you to control Next\.js' telemetry collection/ + ) + }) - test('--keepAliveTimeout happy path', async () => { - const { stderr } = await runNextCommand( - ['start', '--keepAliveTimeout', '100'], - { - stderr: true, - } - ) - expect(stderr).not.toContain( - 'Invalid keep alive timeout provided, expected a non negative number' - ) - }) + test('-h', async () => { + const help = await runNextCommand(['telemetry', '-h'], { + stdout: true, + }) + expect(help.stdout).toMatch( + /Allows you to control Next\.js' telemetry collection/ + ) + }) - test('should not start on a port out of range', async () => { - const invalidPort = '300001' - const { stderr } = await runNextCommand( - ['start', '--port', invalidPort], - { + test('should warn when unknown argument provided', async () => { + const { stderr } = await runNextCommand(['telemetry', '--random'], { stderr: true, - } - ) - - expect(stderr).toContain(`options.port should be >= 0 and < 65536.`) - }) - - test('should not start on a reserved port', async () => { - const reservedPort = '4045' - const { stderr } = await runNextCommand( - ['start', '--port', reservedPort], - { + }) + expect(stderr).toEqual('Unknown or unexpected option: --random\n') + }) + test('should not throw UnhandledPromiseRejectionWarning', async () => { + const { stderr } = await runNextCommand(['telemetry', '--random'], { stderr: true, - } - ) - - expect(stderr).toContain( - `Bad port: "${reservedPort}" is reserved for npp` - ) + }) + expect(stderr).not.toContain('UnhandledPromiseRejectionWarning') + }) }) }) @@ -755,39 +790,6 @@ describe('CLI Usage', () => { }) }) - describe('telemetry', () => { - test('--help', async () => { - const help = await runNextCommand(['telemetry', '--help'], { - stdout: true, - }) - expect(help.stdout).toMatch( - /Allows you to control Next\.js' telemetry collection/ - ) - }) - - test('-h', async () => { - const help = await runNextCommand(['telemetry', '-h'], { - stdout: true, - }) - expect(help.stdout).toMatch( - /Allows you to control Next\.js' telemetry collection/ - ) - }) - - test('should warn when unknown argument provided', async () => { - const { stderr } = await runNextCommand(['telemetry', '--random'], { - stderr: true, - }) - expect(stderr).toEqual('Unknown or unexpected option: --random\n') - }) - test('should not throw UnhandledPromiseRejectionWarning', async () => { - const { stderr } = await runNextCommand(['telemetry', '--random'], { - stderr: true, - }) - expect(stderr).not.toContain('UnhandledPromiseRejectionWarning') - }) - }) - describe('info', () => { function matchInfoOutput(stdout, { nextConfigOutput = '.*' } = {}) { expect(stdout).toMatch( diff --git a/test/integration/config-promise-error/test/index.test.js b/test/integration/config-promise-error/test/index.test.js index b5f4a20b98228..ae979a8e30f4b 100644 --- a/test/integration/config-promise-error/test/index.test.js +++ b/test/integration/config-promise-error/test/index.test.js @@ -7,12 +7,13 @@ import { nextBuild } from 'next-test-utils' const appDir = join(__dirname, '..') describe('Promise in next config', () => { - afterEach(() => fs.remove(join(appDir, 'next.config.js'))) + ;(process.env.TURBOPACK ? 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) => { @@ -21,14 +22,15 @@ 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 2476330fef7bc..b82db8b657f96 100644 --- a/test/integration/config-syntax-error/test/index.test.js +++ b/test/integration/config-syntax-error/test/index.test.js @@ -8,44 +8,46 @@ const nextConfigJS = join(appDir, 'next.config.js') const nextConfigMJS = join(appDir, 'next.config.mjs') describe('Invalid config syntax', () => { - it('should error when next.config.js contains syntax error', async () => { - await fs.writeFile( - nextConfigJS, - ` + ;(process.env.TURBOPACK ? 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 16b5302fa40be..6f44afe56168d 100644 --- a/test/integration/config-validation/test/index.test.ts +++ b/test/integration/config-validation/test/index.test.ts @@ -5,10 +5,11 @@ import fs from 'fs-extra' const nextConfigPath = path.join(__dirname, '../next.config.js') describe('next.config.js validation', () => { - it.each([ - { - name: 'invalid config types', - configContent: ` + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + it.each([ + { + name: 'invalid config types', + configContent: ` module.exports = { swcMinify: 'hello', rewrites: true, @@ -17,15 +18,15 @@ describe('next.config.js validation', () => { } } `, - outputs: [ - 'The value at .images.loader must be one of', - 'The value at .rewrites must be a function that returns a Promise', - 'The value at .swcMinify must be a boolean but it was a string', - ], - }, - { - name: 'unexpected config fields', - configContent: ` + outputs: [ + 'The value at .images.loader must be one of', + 'The value at .rewrites must be a function that returns a Promise', + 'The value at .swcMinify must be a boolean but it was a string', + ], + }, + { + name: 'unexpected config fields', + configContent: ` module.exports = { nonExistent: true, experimental: { @@ -33,24 +34,25 @@ describe('next.config.js validation', () => { } } `, - outputs: [ - 'The root value has an unexpected property, nonExistent,', - 'The value at .experimental has an unexpected property, anotherNonExistent', - ], - }, - ])( - '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: [ + 'The root value has an unexpected property, nonExistent,', + 'The value at .experimental has an unexpected property, anotherNonExistent', + ], + }, + ])( + '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) + } } - } - ) + ) + }) }) 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 53d641874cc45..a15c161e78ba2 100644 --- a/test/integration/conflicting-public-file-page/test/index.test.js +++ b/test/integration/conflicting-public-file-page/test/index.test.js @@ -12,28 +12,34 @@ import { const appDir = path.join(__dirname, '..') describe('Errors on conflict between public file and page file', () => { - it('Throws error during development', async () => { - const appPort = await findPort() - const app = await launchApp(appDir, appPort) - const conflicts = ['/another/conflict', '/hello'] + describe('development mode', () => { + it('Throws error during development', async () => { + const appPort = await findPort() + const app = await launchApp(appDir, appPort) + const conflicts = ['/another/conflict', '/hello'] - for (const conflict of conflicts) { - const html = await renderViaHTTP(appPort, conflict) - expect(html).toMatch( - /A conflicting public file and page file was found for path/ - ) - } - await killApp(app) + for (const conflict of conflicts) { + const html = await renderViaHTTP(appPort, conflict) + expect(html).toMatch( + /A conflicting public file and page file was found for path/ + ) + } + 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/) - 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 88f53b51cebd5..086dab1a22d75 100644 --- a/test/integration/conflicting-ssg-paths/test/index.test.js +++ b/test/integration/conflicting-ssg-paths/test/index.test.js @@ -8,13 +8,14 @@ const appDir = join(__dirname, '../') const pagesDir = join(appDir, 'pages') describe('Conflicting SSG paths', () => { - 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 ? 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: {} @@ -35,11 +36,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: {} @@ -60,39 +61,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: {} @@ -113,40 +114,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: {} @@ -167,21 +168,22 @@ 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 f8d31c85ee4b5..70bc40996c3f5 100644 --- a/test/integration/critical-css/test/index.test.js +++ b/test/integration/critical-css/test/index.test.js @@ -57,23 +57,25 @@ function runTests() { } describe('CSS optimization for SSR apps', () => { - beforeAll(async () => { - await fs.writeFile( - nextConfig, - `module.exports = { experimental: {optimizeCss: true} }`, - 'utf8' - ) + ;(process.env.TURBOPACK ? 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) + 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() }) - runTests() }) diff --git a/test/integration/css-minify/test/index.test.js b/test/integration/css-minify/test/index.test.js index 80d55db2c6bae..4a57d1163ca7c 100644 --- a/test/integration/css-minify/test/index.test.js +++ b/test/integration/css-minify/test/index.test.js @@ -28,13 +28,15 @@ function runTests() { } describe('css-minify', () => { - beforeAll(async () => { - await nextBuild(appDir) - appPort = await findPort() - app = await nextStart(appDir, appPort) + ;(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() }) - 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 9d45eef3c7d71..e887acfc7c5ca 100644 --- a/test/integration/css-modules/test/index.test.js +++ b/test/integration/css-modules/test/index.test.js @@ -243,44 +243,52 @@ describe('Can hot reload CSS Module without losing state', () => { }) describe.skip('Invalid CSS Module Usage in node_modules', () => { - const appDir = join(fixturesDir, 'invalid-module') + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + const appDir = join(fixturesDir, 'invalid-module') - 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('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/ + ) }) - 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', () => { - const appDir = join(fixturesDir, 'invalid-global-module') + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + const appDir = join(fixturesDir, 'invalid-global-module') - 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('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/ + ) }) - 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/) }) }) 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 bc9d8928039e8..454f2c45695ff 100644 --- a/test/integration/css/test/css-and-styled-jsx.test.js +++ b/test/integration/css/test/css-and-styled-jsx.test.js @@ -38,35 +38,37 @@ describe('Ordering with styled-jsx (dev)', () => { }) describe('Ordering with styled-jsx (prod)', () => { - const appDir = join(fixturesDir, 'with-styled-jsx') + ;(process.env.TURBOPACK ? 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 43293d3cd148f..34ea5f1ee779f 100644 --- a/test/integration/css/test/css-compilation.test.js +++ b/test/integration/css/test/css-compilation.test.js @@ -15,52 +15,53 @@ import { join } from 'path' const fixturesDir = join(__dirname, '../..', 'css-fixtures') describe('CSS Support', () => { - describe('CSS Compilation and Prefixing', () => { - const appDir = join(fixturesDir, 'compilation-and-prefixing') + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + describe('CSS Compilation and Prefixing', () => { + const appDir = join(fixturesDir, 'compilation-and-prefixing') - 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 (min-width:480px) and (max-width:767px){::placeholder{color:green}}.flex-parsing{flex:0 0 calc(50% - var(--vertical-gutter))}.transform-parsing{transform:translate3d(0,0)}.css-grid-shorthand{grid-column:span 2}.g-docs-sidenav .filter::-webkit-input-placeholder{opacity:80%}"` - ) + expect(cssFiles.length).toBe(1) + const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8') + expect( + cssContent.replace(/\/\*.*?\*\//g, '').trim() + ).toMatchInlineSnapshot( + `"@media (min-width:480px) and (max-width:767px){::placeholder{color:green}}.flex-parsing{flex:0 0 calc(50% - var(--vertical-gutter))}.transform-parsing{transform:translate3d(0,0)}.css-grid-shorthand{grid-column:span 2}.g-docs-sidenav .filter::-webkit-input-placeholder{opacity:80%}"` + ) - // 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(` Object { "mappings": "AAAA,+CACE,cACE,WACF,CACF,CAEA,cACE,2CACF,CAEA,mBACE,0BACF,CAEA,oBACE,kBACF,CAEA,mDACE,WACF", "sourcesContent": Array [ @@ -90,199 +91,206 @@ describe('CSS Support', () => { "version": 3, } `) + }) }) - }) - describe('React Lifecyce Order (production)', () => { - const appDir = join(fixturesDir, 'transition-react') - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) + describe('React Lifecyce Order (production)', () => { + const appDir = join(fixturesDir, 'transition-react') + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) - 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) - }) + 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 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() + 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('Has CSS in computed styles in Production', () => { - const appDir = join(fixturesDir, 'multi-page') + describe('Has CSS in computed styles in Production', () => { + const appDir = join(fixturesDir, 'multi-page') + + let appPort + let app + let stdout + let code + beforeAll(async () => { + await remove(join(appDir, '.next')) + ;({ code, stdout } = await nextBuild(appDir, [], { + stdout: true, + })) + appPort = await findPort() + app = await nextStart(appDir, appPort) + }) + afterAll(async () => { + await killApp(app) + }) - let appPort - let app - let stdout - let code - beforeAll(async () => { - await remove(join(appDir, '.next')) - ;({ code, stdout } = await nextBuild(appDir, [], { - stdout: true, - })) - appPort = await findPort() - app = await nextStart(appDir, appPort) - }) - afterAll(async () => { - await killApp(app) - }) + it('should have compiled successfully', () => { + expect(code).toBe(0) + expect(stdout).toMatch(/Compiled successfully/) + }) - it('should have compiled successfully', () => { - expect(code).toBe(0) - expect(stdout).toMatch(/Compiled successfully/) - }) + it('should have CSS for page', async () => { + const browser = await webdriver(appPort, '/page2') - 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)"`) + }) - 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]) + }) }) - it(`should've preloaded the CSS file and injected it in `, async () => { - const content = await renderViaHTTP(appPort, '/page2') - const $ = cheerio.load(content) + describe('Good CSS Import from node_modules', () => { + const appDir = join(fixturesDir, 'npm-import') - const cssPreload = $('link[rel="preload"][as="style"]') - expect(cssPreload.length).toBe(1) - expect(cssPreload.attr('href')).toMatch(/^\/_next\/static\/css\/.*\.css$/) + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) - const cssSheet = $('link[rel="stylesheet"]') - expect(cssSheet.length).toBe(1) - expect(cssSheet.attr('href')).toMatch(/^\/_next\/static\/css\/.*\.css$/) + it('should compile successfully', async () => { + const { code, stdout } = await nextBuild(appDir, [], { + stdout: true, + }) + expect(code).toBe(0) + expect(stdout).toMatch(/Compiled successfully/) + }) - /* 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]) - }) - }) + it(`should've emitted a single CSS file`, async () => { + const cssFolder = join(appDir, '.next/static/css') - describe('Good CSS Import from node_modules', () => { - const appDir = join(fixturesDir, 'npm-import') + const files = await readdir(cssFolder) + const cssFiles = files.filter((f) => /\.css$/.test(f)) - beforeAll(async () => { - await remove(join(appDir, '.next')) + expect(cssFiles.length).toBe(1) + const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8') + expect(cssContent.replace(/\/\*.*?\*\//g, '').trim()).toMatch( + /nprogress/ + ) + }) }) - it('should compile successfully', async () => { - const { code, stdout } = await nextBuild(appDir, [], { - stdout: true, + describe('Good Nested CSS Import from node_modules', () => { + const appDir = join(fixturesDir, 'npm-import-nested') + + beforeAll(async () => { + await remove(join(appDir, '.next')) }) - expect(code).toBe(0) - expect(stdout).toMatch(/Compiled successfully/) - }) - it(`should've emitted a single CSS file`, async () => { - const cssFolder = join(appDir, '.next/static/css') + it('should compile successfully', async () => { + const { code, stdout } = await nextBuild(appDir, [], { + stdout: true, + }) + expect(code).toBe(0) + expect(stdout).toMatch(/Compiled successfully/) + }) + + 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()).toMatch(/nprogress/) + expect(cssFiles.length).toBe(1) + const cssContent = await readFile(join(cssFolder, cssFiles[0]), 'utf8') + expect( + cssContent.replace(/\/\*.*?\*\//g, '').trim() + ).toMatchInlineSnapshot(`".other{color:blue}.test{color:red}"`) + }) }) }) +}) - describe('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 ? describe.skip : describe)('production mode', () => { + const appDir = join(fixturesDir, 'next-issue-15468') + 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') - expect( - cssContent.replace(/\/\*.*?\*\//g, '').trim() - ).toMatchInlineSnapshot(`".other{color:blue}.test{color:red}"`) + const width2 = await browser.eval( + `window.getComputedStyle(document.querySelector('.test2')).borderWidth` + ) + expect(width2).toMatchInlineSnapshot(`"5px"`) }) }) }) - -// https://github.com/vercel/next.js/issues/15468 -describe('CSS Property Ordering', () => { - const appDir = join(fixturesDir, 'next-issue-15468') - - 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-rendering.test.js b/test/integration/css/test/css-rendering.test.js index 68adeef2c8667..b89b16791384c 100644 --- a/test/integration/css/test/css-rendering.test.js +++ b/test/integration/css/test/css-rendering.test.js @@ -15,19 +15,21 @@ import { join } from 'path' const fixturesDir = join(__dirname, '../..', 'css-fixtures') describe('CSS Support', () => { - describe('CSS Import from node_modules', () => { - const appDir = join(fixturesDir, 'npm-import-bad') + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + describe('CSS Import from node_modules', () => { + const appDir = join(fixturesDir, 'npm-import-bad') - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) - it('should fail the build', async () => { - const { code, stderr } = await nextBuild(appDir, [], { stderr: true }) + it('should fail the build', async () => { + const { code, stderr } = await nextBuild(appDir, [], { stderr: true }) - expect(code).toBe(0) - expect(stderr).not.toMatch(/Can't resolve '[^']*?nprogress[^']*?'/) - expect(stderr).not.toMatch(/Build error occurred/) + expect(code).toBe(0) + expect(stderr).not.toMatch(/Can't resolve '[^']*?nprogress[^']*?'/) + expect(stderr).not.toMatch(/Build error occurred/) + }) }) }) diff --git a/test/integration/custom-error-page-exception/test/index.test.js b/test/integration/custom-error-page-exception/test/index.test.js index da579761ef751..ddc2722c9d8ec 100644 --- a/test/integration/custom-error-page-exception/test/index.test.js +++ b/test/integration/custom-error-page-exception/test/index.test.js @@ -11,24 +11,26 @@ let app // TODO: re-enable with React 18 describe.skip('Custom error page exception', () => { - beforeAll(async () => { - await nextBuild(appDir, undefined, { - nodeArgs, + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + beforeAll(async () => { + await nextBuild(appDir, undefined, { + nodeArgs, + }) + appPort = await findPort() + app = await nextStart(appDir, appPort, { + nodeArgs, + }) }) - appPort = await findPort() - app = await nextStart(appDir, appPort, { - nodeArgs, - }) - }) - afterAll(() => killApp(app)) - it('should handle errors from _error render', async () => { - const navSel = '#nav' - const browser = await webdriver(appPort, '/') - await browser.waitForElementByCss(navSel).elementByCss(navSel).click() + afterAll(() => killApp(app)) + it('should handle errors from _error render', async () => { + const navSel = '#nav' + const browser = await webdriver(appPort, '/') + await browser.waitForElementByCss(navSel).elementByCss(navSel).click() - await check( - () => browser.eval('document.documentElement.innerHTML'), - /Application error: a client-side exception has occurred/ - ) + await check( + () => browser.eval('document.documentElement.innerHTML'), + /Application error: a client-side exception has occurred/ + ) + }) }) }) diff --git a/test/integration/custom-server/test/index.test.js b/test/integration/custom-server/test/index.test.js index cbad8af2922b3..14ea328617968 100644 --- a/test/integration/custom-server/test/index.test.js +++ b/test/integration/custom-server/test/index.test.js @@ -143,16 +143,23 @@ describe.skip.each([ }) describe('with generateEtags enabled', () => { - beforeAll(async () => { - await nextBuild(appDir) - await startServer({ GENERATE_ETAGS: 'true', NODE_ENV: 'production' }) - }) - afterAll(() => killApp(server)) + ;(process.env.TURBOPACK ? describe.skip : describe)( + 'production mode', + () => { + beforeAll(async () => { + await nextBuild(appDir) + await startServer({ GENERATE_ETAGS: 'true', NODE_ENV: 'production' }) + }) + afterAll(() => killApp(server)) - it('response includes etag header', async () => { - const response = await fetchViaHTTP(nextUrl, '/', undefined, { agent }) - expect(response.headers.get('etag')).toBeTruthy() - }) + it('response includes etag header', async () => { + const response = await fetchViaHTTP(nextUrl, '/', undefined, { + agent, + }) + expect(response.headers.get('etag')).toBeTruthy() + }) + } + ) }) describe('with generateEtags disabled', () => { @@ -222,28 +229,32 @@ describe.skip.each([ expect(html).toContain('made it to dashboard') expect(stderr).toContain('Cannot render page with path "dashboard"') }) - - it('should warn in production mode', async () => { - const { code } = await nextBuild(appDir) - expect(code).toBe(0) - - let stderr = '' - - await startServer( - { NODE_ENV: 'production' }, - { - onStderr(msg) { - stderr += msg || '' - }, - } - ) - - const html = await renderViaHTTP(nextUrl, '/no-slash', undefined, { - agent, - }) - expect(html).toContain('made it to dashboard') - expect(stderr).toContain('Cannot render page with path "dashboard"') - }) + ;(process.env.TURBOPACK ? describe.skip : describe)( + 'production mode', + () => { + it('should warn in production mode', async () => { + const { code } = await nextBuild(appDir) + expect(code).toBe(0) + + let stderr = '' + + await startServer( + { NODE_ENV: 'production' }, + { + onStderr(msg) { + stderr += msg || '' + }, + } + ) + + const html = await renderViaHTTP(nextUrl, '/no-slash', undefined, { + agent, + }) + expect(html).toContain('made it to dashboard') + expect(stderr).toContain('Cannot render page with path "dashboard"') + }) + } + ) }) describe('compression handling', function () { diff --git a/test/integration/data-fetching-errors/test/index.test.js b/test/integration/data-fetching-errors/test/index.test.js index 2d61dede3b7da..553c0995addee 100644 --- a/test/integration/data-fetching-errors/test/index.test.js +++ b/test/integration/data-fetching-errors/test/index.test.js @@ -132,12 +132,9 @@ describe('GS(S)P Page Errors', () => { describe('dev mode', () => { runTests(true) }) - - describe('build mode', () => { + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { runTests() - }) - describe('start mode', () => { it('Error stack printed to stderr', async () => { try { await fs.writeFile( diff --git a/test/integration/dedupes-scripts/test/index.test.js b/test/integration/dedupes-scripts/test/index.test.js index ac9088b0096ce..40004637feffe 100644 --- a/test/integration/dedupes-scripts/test/index.test.js +++ b/test/integration/dedupes-scripts/test/index.test.js @@ -15,28 +15,30 @@ let appPort let app describe('De-dedupes scripts in _document', () => { - beforeAll(async () => { - appPort = await findPort() - await nextBuild(appDir) - app = await nextStart(appDir, appPort) - }) - afterAll(() => killApp(app)) + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + beforeAll(async () => { + appPort = await findPort() + await nextBuild(appDir) + app = await nextStart(appDir, appPort) + }) + afterAll(() => killApp(app)) - it('Does not have duplicate script references', async () => { - const html = await renderViaHTTP(appPort, '/') - const $ = cheerio.load(html) - let foundDuplicate = false - const srcs = new Set() + it('Does not have duplicate script references', async () => { + const html = await renderViaHTTP(appPort, '/') + const $ = cheerio.load(html) + let foundDuplicate = false + const srcs = new Set() - for (const script of $('script').toArray()) { - const { src } = script.attribs - if (!src || !src.startsWith('/_next/static')) continue - if (srcs.has(src)) { - console.error(`Found duplicate script ${src}`) - foundDuplicate = true + for (const script of $('script').toArray()) { + const { src } = script.attribs + if (!src || !src.startsWith('/_next/static')) continue + if (srcs.has(src)) { + console.error(`Found duplicate script ${src}`) + foundDuplicate = true + } + srcs.add(src) } - srcs.add(src) - } - expect(foundDuplicate).toBe(false) + expect(foundDuplicate).toBe(false) + }) }) }) diff --git a/test/integration/dist-dir/test/index.test.js b/test/integration/dist-dir/test/index.test.js index 9d9fc296f9440..d296bc652e730 100644 --- a/test/integration/dist-dir/test/index.test.js +++ b/test/integration/dist-dir/test/index.test.js @@ -19,28 +19,33 @@ let app describe('distDir', () => { describe('With basic usage', () => { - beforeAll(async () => { - await fs.remove(join(appDir, '.next')) - await fs.remove(join(appDir, 'dist')) - await nextBuild(appDir) - appPort = await findPort() - app = await nextStart(appDir, appPort) - }) - afterAll(() => killApp(app)) + ;(process.env.TURBOPACK ? describe.skip : describe)( + 'production mode', + () => { + beforeAll(async () => { + await fs.remove(join(appDir, '.next')) + await fs.remove(join(appDir, 'dist')) + await nextBuild(appDir) + appPort = await findPort() + app = await nextStart(appDir, appPort) + }) + afterAll(() => killApp(app)) - it('should render the page', async () => { - const html = await renderViaHTTP(appPort, '/') - expect(html).toMatch(/Hello World/) - }) + it('should render the page', async () => { + const html = await renderViaHTTP(appPort, '/') + expect(html).toMatch(/Hello World/) + }) - it('should build the app within the given `dist` directory', async () => { - expect( - await fs.exists(join(__dirname, `/../dist/${BUILD_ID_FILE}`)) - ).toBeTruthy() - }) - it('should not build the app within the default `.next` directory', async () => { - expect(await fs.exists(join(__dirname, '/../.next'))).toBeFalsy() - }) + it('should build the app within the given `dist` directory', async () => { + expect( + await fs.exists(join(__dirname, `/../dist/${BUILD_ID_FILE}`)) + ).toBeTruthy() + }) + it('should not build the app within the default `.next` directory', async () => { + expect(await fs.exists(join(__dirname, '/../.next'))).toBeFalsy() + }) + } + ) }) describe('dev mode', () => { @@ -66,27 +71,28 @@ describe('distDir', () => { expect(await fs.exists(join(__dirname, '/../.next'))).toBeFalsy() }) }) + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + it('should throw error with invalid distDir', async () => { + const origNextConfig = await fs.readFile(nextConfig, 'utf8') + await fs.writeFile(nextConfig, `module.exports = { distDir: '' }`) + const { stderr } = await nextBuild(appDir, [], { stderr: true }) + await fs.writeFile(nextConfig, origNextConfig) - it('should throw error with invalid distDir', async () => { - const origNextConfig = await fs.readFile(nextConfig, 'utf8') - await fs.writeFile(nextConfig, `module.exports = { distDir: '' }`) - const { stderr } = await nextBuild(appDir, [], { stderr: true }) - await fs.writeFile(nextConfig, origNextConfig) - - expect(stderr).toContain( - 'Invalid distDir provided, distDir can not be an empty string. Please remove this config or set it to undefined' - ) - }) + expect(stderr).toContain( + 'Invalid distDir provided, distDir can not be an empty string. Please remove this config or set it to undefined' + ) + }) - it('should handle null/undefined distDir', async () => { - const origNextConfig = await fs.readFile(nextConfig, 'utf8') - await fs.writeFile( - nextConfig, - `module.exports = { distDir: null, eslint: { ignoreDuringBuilds: true } }` - ) - const { stderr } = await nextBuild(appDir, [], { stderr: true }) - await fs.writeFile(nextConfig, origNextConfig) + it('should handle null/undefined distDir', async () => { + const origNextConfig = await fs.readFile(nextConfig, 'utf8') + await fs.writeFile( + nextConfig, + `module.exports = { distDir: null, eslint: { ignoreDuringBuilds: true } }` + ) + const { stderr } = await nextBuild(appDir, [], { stderr: true }) + await fs.writeFile(nextConfig, origNextConfig) - expect(stderr.length).toBe(0) + expect(stderr.length).toBe(0) + }) }) }) diff --git a/test/integration/edge-runtime-module-errors/test/index.test.js b/test/integration/edge-runtime-module-errors/test/index.test.js index 0cefbae1838e2..13aee61e12509 100644 --- a/test/integration/edge-runtime-module-errors/test/index.test.js +++ b/test/integration/edge-runtime-module-errors/test/index.test.js @@ -82,30 +82,44 @@ describe('Edge runtime code with imports', () => { beforeEach(() => init(importStatement)) - it('throws unsupported module error in dev at runtime and highlights the faulty line', async () => { - context.app = await launchApp(context.appDir, context.appPort, appOption) - const res = await fetchViaHTTP(context.appPort, url) - expect(res.status).toBe(500) - await check(async () => { - expectUnsupportedModuleDevError( - moduleName, - importStatement, - await res.text() + describe('development mode', () => { + it('throws unsupported module error in dev at runtime and highlights the faulty line', async () => { + context.app = await launchApp( + context.appDir, + context.appPort, + appOption ) - return 'success' - }, 'success') - }) - - it('throws unsupported module error in production at runtime and prints error on logs', async () => { - const { stderr } = await nextBuild(context.appDir, undefined, { - stderr: true, + const res = await fetchViaHTTP(context.appPort, url) + expect(res.status).toBe(500) + await check(async () => { + expectUnsupportedModuleDevError( + moduleName, + importStatement, + await res.text() + ) + return 'success' + }, 'success') }) - expect(stderr).toContain(getUnsupportedModuleWarning(moduleName)) - context.app = await nextStart(context.appDir, context.appPort, appOption) - const res = await fetchViaHTTP(context.appPort, url) - expect(res.status).toBe(500) - expectUnsupportedModuleProdError(moduleName) }) + ;(process.env.TURBOPACK ? describe.skip : describe)( + 'production mode', + () => { + it('throws unsupported module error in production at runtime and prints error on logs', async () => { + const { stderr } = await nextBuild(context.appDir, undefined, { + stderr: true, + }) + expect(stderr).toContain(getUnsupportedModuleWarning(moduleName)) + context.app = await nextStart( + context.appDir, + context.appPort, + appOption + ) + const res = await fetchViaHTTP(context.appPort, url) + expect(res.status).toBe(500) + expectUnsupportedModuleProdError(moduleName) + }) + } + ) }) describe.each([ @@ -154,38 +168,44 @@ describe('Edge runtime code with imports', () => { `) }) - it('throws unsupported module error in dev at runtime and highlights the faulty line', async () => { - context.app = await launchApp( - context.appDir, - context.appPort, - appOption - ) - const res = await fetchViaHTTP(context.appPort, url) - expect(res.status).toBe(500) - await check(async () => { - expectUnsupportedModuleDevError( - moduleName, - importStatement, - await res.text() + describe('development mode', () => { + it('throws unsupported module error in dev at runtime and highlights the faulty line', async () => { + context.app = await launchApp( + context.appDir, + context.appPort, + appOption ) - return 'success' - }, 'success') - }) - - it('throws unsupported module error in production at runtime and prints error on logs', async () => { - const { stderr } = await nextBuild(context.appDir, undefined, { - stderr: true, + const res = await fetchViaHTTP(context.appPort, url) + expect(res.status).toBe(500) + await check(async () => { + expectUnsupportedModuleDevError( + moduleName, + importStatement, + await res.text() + ) + return 'success' + }, 'success') }) - expect(stderr).toContain(getUnsupportedModuleWarning(moduleName)) - context.app = await nextStart( - context.appDir, - context.appPort, - appOption - ) - const res = await fetchViaHTTP(context.appPort, url) - expect(res.status).toBe(500) - expectUnsupportedModuleProdError(moduleName) }) + ;(process.env.TURBOPACK ? describe.skip : describe)( + 'production mode', + () => { + it('throws unsupported module error in production at runtime and prints error on logs', async () => { + const { stderr } = await nextBuild(context.appDir, undefined, { + stderr: true, + }) + expect(stderr).toContain(getUnsupportedModuleWarning(moduleName)) + context.app = await nextStart( + context.appDir, + context.appPort, + appOption + ) + const res = await fetchViaHTTP(context.appPort, url) + expect(res.status).toBe(500) + expectUnsupportedModuleProdError(moduleName) + }) + } + ) } ) @@ -241,16 +261,20 @@ describe('Edge runtime code with imports', () => { return 'success' }, 'success') }) - - it('does not build and reports', async () => { - const { code, stderr } = await nextBuild(context.appDir, undefined, { - ignoreFail: true, - stdout: true, - stderr: true, - }) - expect(code).toEqual(1) - expectModuleNotFoundProdError(moduleName, stderr) - }) + ;(process.env.TURBOPACK ? describe.skip : describe)( + 'production mode', + () => { + it('does not build and reports', async () => { + const { code, stderr } = await nextBuild(context.appDir, undefined, { + ignoreFail: true, + stdout: true, + stderr: true, + }) + expect(code).toEqual(1) + expectModuleNotFoundProdError(moduleName, stderr) + }) + } + ) }) describe.each([ @@ -299,18 +323,26 @@ describe('Edge runtime code with imports', () => { expect(res.headers.get('x-from-runtime')).toBeDefined() expectNoError(moduleName) }) - - it('does not throw in production at runtime', async () => { - const { stderr } = await nextBuild(context.appDir, undefined, { - stderr: true, - }) - expect(stderr).not.toContain(getUnsupportedModuleWarning(moduleName)) - context.app = await nextStart(context.appDir, context.appPort, appOption) - const res = await fetchViaHTTP(context.appPort, url) - expect(res.status).toBe(200) - expect(res.headers.get('x-from-runtime')).toBeDefined() - expectNoError(moduleName) - }) + ;(process.env.TURBOPACK ? describe.skip : describe)( + 'production mode', + () => { + it('does not throw in production at runtime', async () => { + const { stderr } = await nextBuild(context.appDir, undefined, { + stderr: true, + }) + expect(stderr).not.toContain(getUnsupportedModuleWarning(moduleName)) + context.app = await nextStart( + context.appDir, + context.appPort, + appOption + ) + const res = await fetchViaHTTP(context.appPort, url) + expect(res.status).toBe(200) + expect(res.headers.get('x-from-runtime')).toBeDefined() + expectNoError(moduleName) + }) + } + ) }) describe.each([ @@ -360,14 +392,22 @@ describe('Edge runtime code with imports', () => { expect(res.headers.get('x-from-runtime')).toBe('false') expectNoError(moduleName) }) - - it('does not throw in production at runtime', async () => { - await nextBuild(context.appDir, undefined, { stderr: true }) - context.app = await nextStart(context.appDir, context.appPort, appOption) - const res = await fetchViaHTTP(context.appPort, url) - expect(res.status).toBe(200) - expect(res.headers.get('x-from-runtime')).toBe('false') - expectNoError(moduleName) - }) + ;(process.env.TURBOPACK ? describe.skip : describe)( + 'production mode', + () => { + it('does not throw in production at runtime', async () => { + await nextBuild(context.appDir, undefined, { stderr: true }) + context.app = await nextStart( + context.appDir, + context.appPort, + appOption + ) + const res = await fetchViaHTTP(context.appPort, url) + expect(res.status).toBe(200) + expect(res.headers.get('x-from-runtime')).toBe('false') + expectNoError(moduleName) + }) + } + ) }) }) diff --git a/test/integration/edge-runtime-module-errors/test/module-imports.test.js b/test/integration/edge-runtime-module-errors/test/module-imports.test.js index c53c209a204f5..749398b9ca05a 100644 --- a/test/integration/edge-runtime-module-errors/test/module-imports.test.js +++ b/test/integration/edge-runtime-module-errors/test/module-imports.test.js @@ -95,17 +95,25 @@ describe('Edge runtime code with imports', () => { return 'success' }, 'success') }) - - it('throws unsupported module error in production at runtime and prints error on logs', async () => { - const { stderr } = await nextBuild(context.appDir, undefined, { - stderr: true, - }) - expect(stderr).toContain(getUnsupportedModuleWarning(moduleName)) - context.app = await nextStart(context.appDir, context.appPort, appOption) - const res = await fetchViaHTTP(context.appPort, url) - expect(res.status).toBe(500) - expectUnsupportedModuleProdError(moduleName) - }) + ;(process.env.TURBOPACK ? describe.skip : describe)( + 'production mode', + () => { + it('throws unsupported module error in production at runtime and prints error on logs', async () => { + const { stderr } = await nextBuild(context.appDir, undefined, { + stderr: true, + }) + expect(stderr).toContain(getUnsupportedModuleWarning(moduleName)) + context.app = await nextStart( + context.appDir, + context.appPort, + appOption + ) + const res = await fetchViaHTTP(context.appPort, url) + expect(res.status).toBe(500) + expectUnsupportedModuleProdError(moduleName) + }) + } + ) }) describe.each([ @@ -157,16 +165,20 @@ describe('Edge runtime code with imports', () => { return 'success' }, 'success') }) - - it('does not build and reports module not found error', async () => { - const { code, stderr } = await nextBuild(context.appDir, undefined, { - ignoreFail: true, - stdout: true, - stderr: true, - }) - expect(code).toEqual(1) - expectModuleNotFoundProdError(moduleName, stderr) - }) + ;(process.env.TURBOPACK ? describe.skip : describe)( + 'production mode', + () => { + it('does not build and reports module not found error', async () => { + const { code, stderr } = await nextBuild(context.appDir, undefined, { + ignoreFail: true, + stdout: true, + stderr: true, + }) + expect(code).toEqual(1) + expectModuleNotFoundProdError(moduleName, stderr) + }) + } + ) }) describe.each([ @@ -221,17 +233,21 @@ describe('Edge runtime code with imports', () => { return 'success' }, 'success') }) + ;(process.env.TURBOPACK ? describe.skip : describe)( + 'production mode', + () => { + it('does not build and reports module not found error', async () => { + const { code, stderr } = await nextBuild(context.appDir, undefined, { + ignoreFail: true, + stdout: true, + stderr: true, + }) + expect(code).toEqual(1) - it('does not build and reports module not found error', async () => { - const { code, stderr } = await nextBuild(context.appDir, undefined, { - ignoreFail: true, - stdout: true, - stderr: true, - }) - expect(code).toEqual(1) - - expectModuleNotFoundProdError(moduleName, stderr) - }) + expectModuleNotFoundProdError(moduleName, stderr) + }) + } + ) }) describe.each([ @@ -279,16 +295,24 @@ describe('Edge runtime code with imports', () => { expect(res.status).toBe(200) expectNoError(moduleName) }) - - it('does not throw in production at runtime', async () => { - const { stderr } = await nextBuild(context.appDir, undefined, { - stderr: true, - }) - expect(stderr).toContain(getUnsupportedModuleWarning(moduleName)) - context.app = await nextStart(context.appDir, context.appPort, appOption) - const res = await fetchViaHTTP(context.appPort, url) - expect(res.status).toBe(200) - expectNoError(moduleName) - }) + ;(process.env.TURBOPACK ? describe.skip : describe)( + 'production mode', + () => { + it('does not throw in production at runtime', async () => { + const { stderr } = await nextBuild(context.appDir, undefined, { + stderr: true, + }) + expect(stderr).toContain(getUnsupportedModuleWarning(moduleName)) + context.app = await nextStart( + context.appDir, + context.appPort, + appOption + ) + const res = await fetchViaHTTP(context.appPort, url) + expect(res.status).toBe(200) + expectNoError(moduleName) + }) + } + ) }) }) diff --git a/test/integration/edge-runtime-response-error/test/index.test.js b/test/integration/edge-runtime-response-error/test/index.test.js index ad57562801e83..d6718dfa52a18 100644 --- a/test/integration/edge-runtime-response-error/test/index.test.js +++ b/test/integration/edge-runtime-response-error/test/index.test.js @@ -72,17 +72,25 @@ describe('Edge runtime code with imports', () => { ) expect(res.status).toBe(500) }) - - it(`${title} build test Response`, async () => { - await nextBuild(context.appDir, undefined, { - stderr: true, - }) - context.app = await nextStart(context.appDir, context.appPort, appOption) - const res = await fetchViaHTTP(context.appPort, url) - expect(context.logs.stderr).toContain( - 'Expected an instance of Response to be returned' - ) - expect(res.status).toBe(500) - }) + ;(process.env.TURBOPACK ? describe.skip : describe)( + 'production mode', + () => { + it(`${title} build test Response`, async () => { + await nextBuild(context.appDir, undefined, { + stderr: true, + }) + context.app = await nextStart( + context.appDir, + context.appPort, + appOption + ) + const res = await fetchViaHTTP(context.appPort, url) + expect(context.logs.stderr).toContain( + 'Expected an instance of Response to be returned' + ) + expect(res.status).toBe(500) + }) + } + ) }) }) diff --git a/test/integration/error-in-error/test/index.test.js b/test/integration/error-in-error/test/index.test.js index cd81039e428bf..9c7773d58c0bb 100644 --- a/test/integration/error-in-error/test/index.test.js +++ b/test/integration/error-in-error/test/index.test.js @@ -16,23 +16,25 @@ let app let port describe('Handles an Error in _error', () => { - beforeAll(async () => { - await nextBuild(appDir) - port = await findPort() - app = await nextStart(appDir, port) - }) - afterAll(() => killApp(app)) + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + beforeAll(async () => { + await nextBuild(appDir) + port = await findPort() + app = await nextStart(appDir, port) + }) + afterAll(() => killApp(app)) - it('Handles error during SSR', async () => { - const html = await renderViaHTTP(port, '/some-404-page') - expect(html).toMatch(/Internal Server Error/i) - }) + it('Handles error during SSR', async () => { + const html = await renderViaHTTP(port, '/some-404-page') + expect(html).toMatch(/Internal Server Error/i) + }) - it('Handles error during client transition', async () => { - const browser = await webdriver(port, '/') - await browser.waitForElementByCss('a').click() - await waitFor(1000) - const html = await browser.eval('document.body.innerHTML') - expect(html).toMatch(/Internal Server Error/i) + it('Handles error during client transition', async () => { + const browser = await webdriver(port, '/') + await browser.waitForElementByCss('a').click() + await waitFor(1000) + const html = await browser.eval('document.body.innerHTML') + expect(html).toMatch(/Internal Server Error/i) + }) }) }) diff --git a/test/integration/error-load-fail/test/index.test.js b/test/integration/error-load-fail/test/index.test.js index 0e07d4801aadc..0c37a5824f437 100644 --- a/test/integration/error-load-fail/test/index.test.js +++ b/test/integration/error-load-fail/test/index.test.js @@ -16,48 +16,50 @@ const appDir = join(__dirname, '..') let app describe('Failing to load _error', () => { - afterAll(() => killApp(app)) - - it('handles failing to load _error correctly', async () => { - await nextBuild(appDir) - const appPort = await findPort() - app = await nextStart(appDir, appPort) - - const browser = await webdriver(appPort, '/') - await browser.eval(`window.beforeNavigate = true`) - - await browser.elementByCss('#to-broken').moveTo() - await check( - async () => { - const scripts = await browser.elementsByCss('script') - let found = false - - for (const script of scripts) { - const src = await script.getAttribute('src') - if (src.includes('broken-')) { - found = true - break + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + afterAll(() => killApp(app)) + + it('handles failing to load _error correctly', async () => { + await nextBuild(appDir) + const appPort = await findPort() + app = await nextStart(appDir, appPort) + + const browser = await webdriver(appPort, '/') + await browser.eval(`window.beforeNavigate = true`) + + await browser.elementByCss('#to-broken').moveTo() + await check( + async () => { + const scripts = await browser.elementsByCss('script') + let found = false + + for (const script of scripts) { + const src = await script.getAttribute('src') + if (src.includes('broken-')) { + found = true + break + } } - } - return found - }, - { - test(content) { - return content === true + return found }, - } - ) + { + test(content) { + return content === true + }, + } + ) - const errorPageFilePath = getPageFileFromBuildManifest(appDir, '/_error') - // remove _error client bundle so that it can't be loaded - await fs.remove(join(appDir, '.next', errorPageFilePath)) + const errorPageFilePath = getPageFileFromBuildManifest(appDir, '/_error') + // remove _error client bundle so that it can't be loaded + await fs.remove(join(appDir, '.next', errorPageFilePath)) - await browser.elementByCss('#to-broken').click() + await browser.elementByCss('#to-broken').click() - await check(async () => { - return !(await browser.eval('window.beforeNavigate')) - ? 'reloaded' - : 'fail' - }, /reloaded/) + await check(async () => { + return !(await browser.eval('window.beforeNavigate')) + ? 'reloaded' + : 'fail' + }, /reloaded/) + }) }) }) diff --git a/test/integration/errors-on-output-to-public/test/index.test.js b/test/integration/errors-on-output-to-public/test/index.test.js index 3ee45233dd72d..9b0e926556ad4 100644 --- a/test/integration/errors-on-output-to-public/test/index.test.js +++ b/test/integration/errors-on-output-to-public/test/index.test.js @@ -8,29 +8,34 @@ const appDir = path.join(__dirname, '..') const nextConfig = path.join(appDir, 'next.config.js') describe('Errors on output to public', () => { - it('Throws error when `distDir` is set to public', async () => { - await fs.writeFile(nextConfig, `module.exports = { distDir: 'public' }`) - const results = await nextBuild(appDir, [], { stdout: true, stderr: true }) - expect(results.stdout + results.stderr).toMatch( - /The 'public' directory is reserved in Next\.js and can not be set as/ - ) - await fs.remove(nextConfig) - }) - - it('Throws error when export out dir is public', async () => { - await fs.remove(nextConfig) - await nextBuild(appDir) - const outdir = path.join(appDir, 'public') - const results = await nextExport( - appDir, - { outdir }, - { + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + it('Throws error when `distDir` is set to public', async () => { + await fs.writeFile(nextConfig, `module.exports = { distDir: 'public' }`) + const results = await nextBuild(appDir, [], { stdout: true, stderr: true, - } - ) - expect(results.stdout + results.stderr).toMatch( - /The 'public' directory is reserved in Next\.js and can not be used as/ - ) + }) + expect(results.stdout + results.stderr).toMatch( + /The 'public' directory is reserved in Next\.js and can not be set as/ + ) + await fs.remove(nextConfig) + }) + + it('Throws error when export out dir is public', async () => { + await fs.remove(nextConfig) + await nextBuild(appDir) + const outdir = path.join(appDir, 'public') + const results = await nextExport( + appDir, + { outdir }, + { + stdout: true, + stderr: true, + } + ) + expect(results.stdout + results.stderr).toMatch( + /The 'public' directory is reserved in Next\.js and can not be used as/ + ) + }) }) }) diff --git a/test/integration/errors-on-output-to-static/test/index.test.js b/test/integration/errors-on-output-to-static/test/index.test.js index 1f34e5c919cb0..83cc9fbf5ed64 100644 --- a/test/integration/errors-on-output-to-static/test/index.test.js +++ b/test/integration/errors-on-output-to-static/test/index.test.js @@ -8,20 +8,22 @@ const appDir = path.join(__dirname, '..') const nextConfig = path.join(appDir, 'next.config.js') describe('Errors on output to static', () => { - it('Throws error when export out dir is static', async () => { - await fs.remove(nextConfig) - await nextBuild(appDir) - const outdir = path.join(appDir, 'static') - const results = await nextExport( - appDir, - { outdir }, - { - stdout: true, - stderr: true, - } - ) - expect(results.stdout + results.stderr).toMatch( - /The 'static' directory is reserved in Next\.js and can not be used as/ - ) + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + it('Throws error when export out dir is static', async () => { + await fs.remove(nextConfig) + await nextBuild(appDir) + const outdir = path.join(appDir, 'static') + const results = await nextExport( + appDir, + { outdir }, + { + stdout: true, + stderr: true, + } + ) + expect(results.stdout + results.stderr).toMatch( + /The 'static' directory is reserved in Next\.js and can not be used as/ + ) + }) }) }) diff --git a/test/integration/eslint/test/next-build.test.js b/test/integration/eslint/test/next-build.test.js index 1ce25e8a97a69..df1d8512df2a5 100644 --- a/test/integration/eslint/test/next-build.test.js +++ b/test/integration/eslint/test/next-build.test.js @@ -40,170 +40,182 @@ const mjsCjsLinting = join(__dirname, '../mjs-cjs-linting') const dirTypescript = join(__dirname, '../with-typescript') describe('Next Build', () => { - test('first time setup', async () => { - const eslintrcJson = join(dirFirstTimeSetup, '.eslintrc.json') - await fs.writeFile(eslintrcJson, '') + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + test('first time setup', async () => { + const eslintrcJson = join(dirFirstTimeSetup, '.eslintrc.json') + await fs.writeFile(eslintrcJson, '') - const { stdout, stderr } = await nextBuild(dirFirstTimeSetup, [], { - stdout: true, - stderr: true, - }) - const output = stdout + stderr - - expect(output).toContain( - 'No ESLint configuration detected. Run next lint to begin setup' - ) - }) + const { stdout, stderr } = await nextBuild(dirFirstTimeSetup, [], { + stdout: true, + stderr: true, + }) + const output = stdout + stderr - test('shows warnings and errors', async () => { - const { stdout, stderr } = await nextBuild(dirCustomConfig, [], { - stdout: true, - stderr: true, + expect(output).toContain( + 'No ESLint configuration detected. Run next lint to begin setup' + ) }) - const output = stdout + stderr - expect(output).toContain('Warning: Synchronous scripts should not be used.') - expect(output).toContain( - 'Error: Comments inside children section of tag should be placed inside braces' - ) - }) - - test('ignore during builds', async () => { - const { stdout, stderr } = await nextBuild(dirIgnoreDuringBuilds, [], { - stdout: true, - stderr: true, + test('shows warnings and errors', async () => { + const { stdout, stderr } = await nextBuild(dirCustomConfig, [], { + stdout: true, + stderr: true, + }) + + const output = stdout + stderr + expect(output).toContain( + 'Warning: Synchronous scripts should not be used.' + ) + expect(output).toContain( + 'Error: Comments inside children section of tag should be placed inside braces' + ) }) - const output = stdout + stderr - expect(output).not.toContain('Failed to compile') - expect(output).not.toContain( - 'Error: Comments inside children section of tag should be placed inside braces' - ) - }) + test('ignore during builds', async () => { + const { stdout, stderr } = await nextBuild(dirIgnoreDuringBuilds, [], { + stdout: true, + stderr: true, + }) - test('base directories are linted by default during builds', async () => { - const { stdout, stderr } = await nextBuild(dirBaseDirectories, [], { - stdout: true, - stderr: true, + const output = stdout + stderr + expect(output).not.toContain('Failed to compile') + expect(output).not.toContain( + 'Error: Comments inside children section of tag should be placed inside braces' + ) }) - const output = stdout + stderr - - expect(output).toContain('Failed to compile') - expect(output).toContain( - 'Error: `next/head` should not be imported in `pages/_document.js`. Use `` from `next/document` instead' - ) - expect(output).toContain( - 'Warning: Using `` could result in slower LCP and higher bandwidth. Consider using `` from `next/image` to automatically optimize images.' - ) - expect(output).toContain('Warning: Do not include stylesheets manually') - expect(output).toContain('Warning: Synchronous scripts should not be used') - expect(output).toContain( - 'Warning: `rel="preconnect"` is missing from Google Font' - ) - - // Files in app, pages, components, lib, and src directories are linted - expect(output).toContain('pages/_document.js') - expect(output).toContain('components/bar.js') - expect(output).toContain('lib/foo.js') - expect(output).toContain('src/index.js') - expect(output).toContain('app/layout.js') - }) - - test('custom directories', async () => { - const { stdout, stderr } = await nextBuild(dirCustomDirectories, [], { - stdout: true, - stderr: true, + test('base directories are linted by default during builds', async () => { + const { stdout, stderr } = await nextBuild(dirBaseDirectories, [], { + stdout: true, + stderr: true, + }) + + const output = stdout + stderr + + expect(output).toContain('Failed to compile') + expect(output).toContain( + 'Error: `next/head` should not be imported in `pages/_document.js`. Use `` from `next/document` instead' + ) + expect(output).toContain( + 'Warning: Using `` could result in slower LCP and higher bandwidth. Consider using `` from `next/image` to automatically optimize images.' + ) + expect(output).toContain('Warning: Do not include stylesheets manually') + expect(output).toContain( + 'Warning: Synchronous scripts should not be used' + ) + expect(output).toContain( + 'Warning: `rel="preconnect"` is missing from Google Font' + ) + + // Files in app, pages, components, lib, and src directories are linted + expect(output).toContain('pages/_document.js') + expect(output).toContain('components/bar.js') + expect(output).toContain('lib/foo.js') + expect(output).toContain('src/index.js') + expect(output).toContain('app/layout.js') }) - const output = stdout + stderr - expect(output).toContain('Failed to compile') - expect(output).toContain( - 'Error: Comments inside children section of tag should be placed inside braces' - ) - expect(output).toContain('Warning: Synchronous scripts should not be used.') - }) - - test('invalid older eslint version', async () => { - const { stdout, stderr } = await nextBuild( - dirInvalidOlderEslintVersion, - [], - { + test('custom directories', async () => { + const { stdout, stderr } = await nextBuild(dirCustomDirectories, [], { stdout: true, stderr: true, - } - ) - - const output = stdout + stderr - expect(output).toContain( - 'Your project has an older version of ESLint installed' - ) - }) + }) + + const output = stdout + stderr + expect(output).toContain('Failed to compile') + expect(output).toContain( + 'Error: Comments inside children section of tag should be placed inside braces' + ) + expect(output).toContain( + 'Warning: Synchronous scripts should not be used.' + ) + }) - test('empty directories do not fail the build', async () => { - const { stdout, stderr } = await nextBuild(dirEmptyDirectory, [], { - stdout: true, - stderr: true, + test('invalid older eslint version', async () => { + const { stdout, stderr } = await nextBuild( + dirInvalidOlderEslintVersion, + [], + { + stdout: true, + stderr: true, + } + ) + + const output = stdout + stderr + expect(output).toContain( + 'Your project has an older version of ESLint installed' + ) }) - const output = stdout + stderr - expect(output).not.toContain('Build error occurred') - expect(output).not.toContain('NoFilesFoundError') - expect(output).toContain('Warning: Synchronous scripts should not be used.') - expect(output).toContain('Compiled successfully') - }) + test('empty directories do not fail the build', async () => { + const { stdout, stderr } = await nextBuild(dirEmptyDirectory, [], { + stdout: true, + stderr: true, + }) + + const output = stdout + stderr + expect(output).not.toContain('Build error occurred') + expect(output).not.toContain('NoFilesFoundError') + expect(output).toContain( + 'Warning: Synchronous scripts should not be used.' + ) + expect(output).toContain('Compiled successfully') + }) - test('eslint ignored directories do not fail the build', async () => { - const { stdout, stderr } = await nextBuild(dirEslintIgnore, [], { - stdout: true, - stderr: true, + test('eslint ignored directories do not fail the build', async () => { + const { stdout, stderr } = await nextBuild(dirEslintIgnore, [], { + stdout: true, + stderr: true, + }) + + const output = stdout + stderr + expect(output).not.toContain('Build error occurred') + expect(output).not.toContain('AllFilesIgnoredError') + expect(output).toContain( + 'Warning: Synchronous scripts should not be used.' + ) + expect(output).toContain('Compiled successfully') }) - const output = stdout + stderr - expect(output).not.toContain('Build error occurred') - expect(output).not.toContain('AllFilesIgnoredError') - expect(output).toContain('Warning: Synchronous scripts should not be used.') - expect(output).toContain('Compiled successfully') - }) + test('missing Next.js plugin', async () => { + const { stdout, stderr } = await nextBuild(dirNoEslintPlugin, [], { + stdout: true, + stderr: true, + }) - test('missing Next.js plugin', async () => { - const { stdout, stderr } = await nextBuild(dirNoEslintPlugin, [], { - stdout: true, - stderr: true, + const output = stdout + stderr + expect(output).toContain( + 'The Next.js plugin was not detected in your ESLint configuration' + ) }) - const output = stdout + stderr - expect(output).toContain( - 'The Next.js plugin was not detected in your ESLint configuration' - ) - }) - - test('eslint caching is enabled', async () => { - const cacheDir = join(dirEslintCache, '.next', 'cache') + test('eslint caching is enabled', async () => { + const cacheDir = join(dirEslintCache, '.next', 'cache') - await fs.remove(cacheDir) - await nextBuild(dirEslintCache, []) + await fs.remove(cacheDir) + await nextBuild(dirEslintCache, []) - const files = await fs.readdir(join(cacheDir, 'eslint/')) - const cacheExists = files.some((f) => /\.cache/.test(f)) + const files = await fs.readdir(join(cacheDir, 'eslint/')) + const cacheExists = files.some((f) => /\.cache/.test(f)) - expect(cacheExists).toBe(true) - }) + expect(cacheExists).toBe(true) + }) - test('eslint cache lives in the user defined build directory', async () => { - const oldCacheDir = join(dirEslintCacheCustomDir, '.next', 'cache') - const newCacheDir = join(dirEslintCacheCustomDir, 'build', 'cache') + test('eslint cache lives in the user defined build directory', async () => { + const oldCacheDir = join(dirEslintCacheCustomDir, '.next', 'cache') + const newCacheDir = join(dirEslintCacheCustomDir, 'build', 'cache') - await fs.remove(oldCacheDir) - await fs.remove(newCacheDir) + await fs.remove(oldCacheDir) + await fs.remove(newCacheDir) - await nextBuild(dirEslintCacheCustomDir, []) + await nextBuild(dirEslintCacheCustomDir, []) - expect(fs.existsSync(oldCacheDir)).toBe(false) + expect(fs.existsSync(oldCacheDir)).toBe(false) - const files = await fs.readdir(join(newCacheDir, 'eslint/')) - const cacheExists = files.some((f) => /\.cache/.test(f)) + const files = await fs.readdir(join(newCacheDir, 'eslint/')) + const cacheExists = files.some((f) => /\.cache/.test(f)) - expect(cacheExists).toBe(true) + expect(cacheExists).toBe(true) + }) }) }) diff --git a/test/integration/export-404/test/index.test.js b/test/integration/export-404/test/index.test.js index b90a681e43364..1ab4130e4874b 100644 --- a/test/integration/export-404/test/index.test.js +++ b/test/integration/export-404/test/index.test.js @@ -19,33 +19,37 @@ const fileExist = (path) => // Issue #36855 // https://github.com/vercel/next.js/issues/36855 describe('Static 404 Export', () => { - it('only export 404.html when trailingSlash: false', async () => { - await nextBuild(appDir) - await nextExport(appDir, { outdir }) - - expect(await fileExist(join(outdir, '404.html'))).toBe(true) - expect(await fileExist(join(outdir, '404.html.html'))).toBe(false) - expect(await fileExist(join(outdir, '404/index.html'))).toBe(false) - }) - - it('export 404.html and 404/index.html when trailingSlash: true', async () => { - nextConfig.replace(`trailingSlash: false`, `trailingSlash: true`) - await nextBuild(appDir) - await nextExport(appDir, { outdir }) - nextConfig.restore() - - expect(await fileExist(join(outdir, '404/index.html'))).toBe(true) - expect(await fileExist(join(outdir, '404.html.html'))).toBe(false) - expect(await fileExist(join(outdir, '404.html'))).toBe(true) + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + it('only export 404.html when trailingSlash: false', async () => { + await nextBuild(appDir) + await nextExport(appDir, { outdir }) + + expect(await fileExist(join(outdir, '404.html'))).toBe(true) + expect(await fileExist(join(outdir, '404.html.html'))).toBe(false) + expect(await fileExist(join(outdir, '404/index.html'))).toBe(false) + }) + + it('export 404.html and 404/index.html when trailingSlash: true', async () => { + nextConfig.replace(`trailingSlash: false`, `trailingSlash: true`) + await nextBuild(appDir) + await nextExport(appDir, { outdir }) + nextConfig.restore() + + expect(await fileExist(join(outdir, '404/index.html'))).toBe(true) + expect(await fileExist(join(outdir, '404.html.html'))).toBe(false) + expect(await fileExist(join(outdir, '404.html'))).toBe(true) + }) }) }) describe('Export with a page named 404.js', () => { - it('should export a custom 404.html instead of default 404.html', async () => { - await nextBuild(appDir) - await nextExport(appDir, { outdir }) - - const html = await readFile(join(outdir, '404.html'), 'utf8') - expect(html).toMatch(/this is a 404 page override the default 404\.html/) + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + it('should export a custom 404.html instead of default 404.html', async () => { + await nextBuild(appDir) + await nextExport(appDir, { outdir }) + + const html = await readFile(join(outdir, '404.html'), 'utf8') + expect(html).toMatch(/this is a 404 page override the default 404\.html/) + }) }) }) diff --git a/test/integration/export-default-map/test/index.test.js b/test/integration/export-default-map/test/index.test.js index 210efe87c09d3..61483d0e2485e 100644 --- a/test/integration/export-default-map/test/index.test.js +++ b/test/integration/export-default-map/test/index.test.js @@ -10,56 +10,64 @@ const appDir = join(__dirname, '../') const outdir = join(appDir, 'out') describe('Export with default map', () => { - beforeAll(async () => { - await nextBuild(appDir) - await nextExport(appDir, { outdir }) - }) + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + beforeAll(async () => { + await nextBuild(appDir) + await nextExport(appDir, { outdir }) + }) - it('should export with folder that has dot in name', async () => { - expect.assertions(1) - await expect(access(join(outdir, 'v1.12.html'))).resolves.toBe(undefined) - }) + it('should export with folder that has dot in name', async () => { + expect.assertions(1) + await expect(access(join(outdir, 'v1.12.html'))).resolves.toBe(undefined) + }) - it('should export an amp only page to clean path', async () => { - expect.assertions(1) - await expect(access(join(outdir, 'docs.html'))).resolves.toBe(undefined) - }) + it('should export an amp only page to clean path', async () => { + expect.assertions(1) + await expect(access(join(outdir, 'docs.html'))).resolves.toBe(undefined) + }) - it('should export hybrid amp page correctly', async () => { - expect.assertions(2) - await expect(access(join(outdir, 'some.html'))).resolves.toBe(undefined) - await expect(access(join(outdir, 'some.amp.html'))).resolves.toBe(undefined) - }) + it('should export hybrid amp page correctly', async () => { + expect.assertions(2) + await expect(access(join(outdir, 'some.html'))).resolves.toBe(undefined) + await expect(access(join(outdir, 'some.amp.html'))).resolves.toBe( + undefined + ) + }) - it('should export nested hybrid amp page correctly', async () => { - expect.assertions(3) - await expect(access(join(outdir, 'docs.html'))).resolves.toBe(undefined) - await expect(access(join(outdir, 'docs.amp.html'))).resolves.toBe(undefined) + it('should export nested hybrid amp page correctly', async () => { + expect.assertions(3) + await expect(access(join(outdir, 'docs.html'))).resolves.toBe(undefined) + await expect(access(join(outdir, 'docs.amp.html'))).resolves.toBe( + undefined + ) - const html = await readFile(join(outdir, 'docs.html')) - const $ = cheerio.load(html) - expect($('link[rel=amphtml]').attr('href')).toBe('/docs.amp') - }) + const html = await readFile(join(outdir, 'docs.html')) + const $ = cheerio.load(html) + expect($('link[rel=amphtml]').attr('href')).toBe('/docs.amp') + }) - it('should export nested hybrid amp page correctly with folder', async () => { - expect.assertions(3) - await expect(access(join(outdir, 'info.html'))).resolves.toBe(undefined) - await expect(access(join(outdir, 'info.amp.html'))).resolves.toBe(undefined) + it('should export nested hybrid amp page correctly with folder', async () => { + expect.assertions(3) + await expect(access(join(outdir, 'info.html'))).resolves.toBe(undefined) + await expect(access(join(outdir, 'info.amp.html'))).resolves.toBe( + undefined + ) - const html = await readFile(join(outdir, 'info.html')) - const $ = cheerio.load(html) - expect($('link[rel=amphtml]').attr('href')).toBe('/info.amp') - }) + const html = await readFile(join(outdir, 'info.html')) + const $ = cheerio.load(html) + expect($('link[rel=amphtml]').attr('href')).toBe('/info.amp') + }) - it('should export hybrid index amp page correctly', async () => { - expect.assertions(3) - await expect(access(join(outdir, 'index.html'))).resolves.toBe(undefined) - await expect(access(join(outdir, 'index.amp.html'))).resolves.toBe( - undefined - ) + it('should export hybrid index amp page correctly', async () => { + expect.assertions(3) + await expect(access(join(outdir, 'index.html'))).resolves.toBe(undefined) + await expect(access(join(outdir, 'index.amp.html'))).resolves.toBe( + undefined + ) - const html = await readFile(join(outdir, 'index.html')) - const $ = cheerio.load(html) - expect($('link[rel=amphtml]').attr('href')).toBe('/index.amp') + const html = await readFile(join(outdir, 'index.html')) + const $ = cheerio.load(html) + expect($('link[rel=amphtml]').attr('href')).toBe('/index.amp') + }) }) }) diff --git a/test/integration/export-dynamic-pages/test/index.test.js b/test/integration/export-dynamic-pages/test/index.test.js index cd9fc56f94bc0..2216dc9bed824 100644 --- a/test/integration/export-dynamic-pages/test/index.test.js +++ b/test/integration/export-dynamic-pages/test/index.test.js @@ -14,9 +14,8 @@ import { const appDir = join(__dirname, '../') const outdir = join(appDir, 'out') -;(process.env.TURBOPACK ? describe.skip : describe)( - 'Export Dynamic Pages', - () => { +describe('Export Dynamic Pages', () => { + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { let server let port beforeAll(async () => { @@ -48,5 +47,5 @@ const outdir = join(appDir, 'out') await browser.close() } }) - } -) + }) +}) diff --git a/test/integration/export-fallback-true-error/test/index.test.js b/test/integration/export-fallback-true-error/test/index.test.js index 502e730807336..52454fec3dd06 100644 --- a/test/integration/export-fallback-true-error/test/index.test.js +++ b/test/integration/export-fallback-true-error/test/index.test.js @@ -8,18 +8,20 @@ const appDir = join(__dirname, '../') const outdir = join(appDir, 'out') describe('Export error for fallback: true', () => { - it('should build successfully', async () => { - await fs.remove(join(appDir, '.next')) - const { code } = await nextBuild(appDir) - if (code !== 0) throw new Error(`build failed with status ${code}`) - }) + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + it('should build successfully', async () => { + await fs.remove(join(appDir, '.next')) + const { code } = await nextBuild(appDir) + if (code !== 0) throw new Error(`build failed with status ${code}`) + }) - it('should have error during next export', async () => { - const { stderr } = await nextExport(appDir, { outdir }, { stderr: true }) - expect(stderr).toContain('Found pages with `fallback` enabled') - expect(stderr).toContain( - 'Pages with `fallback` enabled in `getStaticPaths` can not be exported' - ) - expect(stderr).toContain('/[slug]') + it('should have error during next export', async () => { + const { stderr } = await nextExport(appDir, { outdir }, { stderr: true }) + expect(stderr).toContain('Found pages with `fallback` enabled') + expect(stderr).toContain( + 'Pages with `fallback` enabled in `getStaticPaths` can not be exported' + ) + expect(stderr).toContain('/[slug]') + }) }) }) diff --git a/test/integration/export-getInitialProps-warn/test/index.test.js b/test/integration/export-getInitialProps-warn/test/index.test.js index 6738da658a03d..9c8bb77728217 100644 --- a/test/integration/export-getInitialProps-warn/test/index.test.js +++ b/test/integration/export-getInitialProps-warn/test/index.test.js @@ -7,11 +7,13 @@ const appDir = join(__dirname, '../') const outdir = join(appDir, 'out') describe('Export with getInitialProps', () => { - it('should show warning with next export', async () => { - await nextBuild(appDir) - const { stderr } = await nextExport(appDir, { outdir }, { stderr: true }) - expect(stderr).toContain( - 'https://nextjs.org/docs/messages/get-initial-props-export' - ) + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + it('should show warning with next export', async () => { + await nextBuild(appDir) + const { stderr } = await nextExport(appDir, { outdir }, { stderr: true }) + expect(stderr).toContain( + 'https://nextjs.org/docs/messages/get-initial-props-export' + ) + }) }) }) diff --git a/test/integration/export-image-default/test/index.test.js b/test/integration/export-image-default/test/index.test.js index eee30bf8eba7c..c28340c0db9cd 100644 --- a/test/integration/export-image-default/test/index.test.js +++ b/test/integration/export-image-default/test/index.test.js @@ -8,16 +8,18 @@ const appDir = join(__dirname, '../') const outdir = join(appDir, 'out') describe('Export with default loader next/image component', () => { - it('should build successfully', async () => { - await fs.remove(join(appDir, '.next')) - const { code } = await nextBuild(appDir) - if (code !== 0) throw new Error(`build failed with status ${code}`) - }) + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + it('should build successfully', async () => { + await fs.remove(join(appDir, '.next')) + const { code } = await nextBuild(appDir) + if (code !== 0) throw new Error(`build failed with status ${code}`) + }) - it('should have error during next export', async () => { - const { stderr } = await nextExport(appDir, { outdir }, { stderr: true }) - expect(stderr).toContain( - 'Image Optimization using the default loader is not compatible with export.' - ) + it('should have error during next export', async () => { + const { stderr } = await nextExport(appDir, { outdir }, { stderr: true }) + expect(stderr).toContain( + 'Image Optimization using the default loader is not compatible with export.' + ) + }) }) }) diff --git a/test/integration/export-image-loader-legacy/test/index.test.js b/test/integration/export-image-loader-legacy/test/index.test.js index a15d38215ec7f..3c18c1bf98a14 100644 --- a/test/integration/export-image-loader-legacy/test/index.test.js +++ b/test/integration/export-image-loader-legacy/test/index.test.js @@ -11,132 +11,140 @@ const nextConfig = new File(join(appDir, 'next.config.js')) const pagesIndexJs = new File(join(appDir, 'pages', 'index.js')) describe('Export with cloudinary loader next/legacy/image component', () => { - beforeAll(async () => { - await nextConfig.replace( - '{ /* replaceme */ }', - JSON.stringify({ - images: { - loader: 'cloudinary', - path: 'https://example.com/', - }, - }) - ) - }) - it('should build successfully', async () => { - await fs.remove(join(appDir, '.next')) - const { code } = await nextBuild(appDir) - if (code !== 0) throw new Error(`build failed with status ${code}`) - }) - - it('should export successfully', async () => { - const { code } = await nextExport(appDir, { outdir }) - if (code !== 0) throw new Error(`export failed with status ${code}`) - }) - - it('should contain img element in html output', async () => { - const html = await fs.readFile(join(outdir, 'index.html')) - const $ = cheerio.load(html) - expect($('img[alt="icon"]').attr('alt')).toBe('icon') - }) - - afterAll(async () => { - await nextConfig.restore() + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + beforeAll(async () => { + await nextConfig.replace( + '{ /* replaceme */ }', + JSON.stringify({ + images: { + loader: 'cloudinary', + path: 'https://example.com/', + }, + }) + ) + }) + it('should build successfully', async () => { + await fs.remove(join(appDir, '.next')) + const { code } = await nextBuild(appDir) + if (code !== 0) throw new Error(`build failed with status ${code}`) + }) + + it('should export successfully', async () => { + const { code } = await nextExport(appDir, { outdir }) + if (code !== 0) throw new Error(`export failed with status ${code}`) + }) + + it('should contain img element in html output', async () => { + const html = await fs.readFile(join(outdir, 'index.html')) + const $ = cheerio.load(html) + expect($('img[alt="icon"]').attr('alt')).toBe('icon') + }) + + afterAll(async () => { + await nextConfig.restore() + }) }) }) describe('Export with custom loader next/legacy/image component', () => { - beforeAll(async () => { - await nextConfig.replace( - '{ /* replaceme */ }', - JSON.stringify({ - images: { - loader: 'custom', - }, - }) - ) - await pagesIndexJs.replace( - 'loader = undefined', - 'loader = ({src}) => "/custom" + src' - ) - }) - it('should build successfully', async () => { - await fs.remove(join(appDir, '.next')) - const { code } = await nextBuild(appDir) - if (code !== 0) throw new Error(`build failed with status ${code}`) - }) - - it('should export successfully', async () => { - const { code } = await nextExport(appDir, { outdir }) - if (code !== 0) throw new Error(`export failed with status ${code}`) - }) - - it('should contain img element with same src in html output', async () => { - const html = await fs.readFile(join(outdir, 'index.html')) - const $ = cheerio.load(html) - expect($('img[src="/custom/o.png"]')).toBeDefined() - }) - - afterAll(async () => { - await nextConfig.restore() - await pagesIndexJs.restore() + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + beforeAll(async () => { + await nextConfig.replace( + '{ /* replaceme */ }', + JSON.stringify({ + images: { + loader: 'custom', + }, + }) + ) + await pagesIndexJs.replace( + 'loader = undefined', + 'loader = ({src}) => "/custom" + src' + ) + }) + it('should build successfully', async () => { + await fs.remove(join(appDir, '.next')) + const { code } = await nextBuild(appDir) + if (code !== 0) throw new Error(`build failed with status ${code}`) + }) + + it('should export successfully', async () => { + const { code } = await nextExport(appDir, { outdir }) + if (code !== 0) throw new Error(`export failed with status ${code}`) + }) + + it('should contain img element with same src in html output', async () => { + const html = await fs.readFile(join(outdir, 'index.html')) + const $ = cheerio.load(html) + expect($('img[src="/custom/o.png"]')).toBeDefined() + }) + + afterAll(async () => { + await nextConfig.restore() + await pagesIndexJs.restore() + }) }) }) describe('Export with custom loader config but no loader prop on next/legacy/image', () => { - beforeAll(async () => { - await nextConfig.replace( - '{ /* replaceme */ }', - JSON.stringify({ - images: { - loader: 'custom', - }, - }) - ) - }) - it('should fail build', async () => { - await fs.remove(join(appDir, '.next')) - const { code, stderr } = await nextBuild(appDir, [], { stderr: true }) - expect(code).toBe(1) - expect(stderr).toContain( - 'Error: Image with src "/i.png" is missing "loader" prop' - ) - }) - - afterAll(async () => { - await nextConfig.restore() - await pagesIndexJs.restore() + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + beforeAll(async () => { + await nextConfig.replace( + '{ /* replaceme */ }', + JSON.stringify({ + images: { + loader: 'custom', + }, + }) + ) + }) + it('should fail build', async () => { + await fs.remove(join(appDir, '.next')) + const { code, stderr } = await nextBuild(appDir, [], { stderr: true }) + expect(code).toBe(1) + expect(stderr).toContain( + 'Error: Image with src "/i.png" is missing "loader" prop' + ) + }) + + afterAll(async () => { + await nextConfig.restore() + await pagesIndexJs.restore() + }) }) }) describe('Export with unoptimized next/legacy/image component', () => { - beforeAll(async () => { - await nextConfig.replace( - '{ /* replaceme */ }', - JSON.stringify({ - images: { - unoptimized: true, - }, - }) - ) - }) - it('should build successfully', async () => { - await fs.remove(join(appDir, '.next')) - const { code } = await nextBuild(appDir) - if (code !== 0) throw new Error(`build failed with status ${code}`) - }) - - it('should export successfully', async () => { - const { code } = await nextExport(appDir, { outdir }) - if (code !== 0) throw new Error(`export failed with status ${code}`) - }) - - it('should contain img element with same src in html output', async () => { - const html = await fs.readFile(join(outdir, 'index.html')) - const $ = cheerio.load(html) - expect($('img[src="/o.png"]')).toBeDefined() - }) - - afterAll(async () => { - await nextConfig.restore() + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + beforeAll(async () => { + await nextConfig.replace( + '{ /* replaceme */ }', + JSON.stringify({ + images: { + unoptimized: true, + }, + }) + ) + }) + it('should build successfully', async () => { + await fs.remove(join(appDir, '.next')) + const { code } = await nextBuild(appDir) + if (code !== 0) throw new Error(`build failed with status ${code}`) + }) + + it('should export successfully', async () => { + const { code } = await nextExport(appDir, { outdir }) + if (code !== 0) throw new Error(`export failed with status ${code}`) + }) + + it('should contain img element with same src in html output', async () => { + const html = await fs.readFile(join(outdir, 'index.html')) + const $ = cheerio.load(html) + expect($('img[src="/o.png"]')).toBeDefined() + }) + + afterAll(async () => { + await nextConfig.restore() + }) }) }) diff --git a/test/integration/export-index-not-found-gsp/test/index.test.ts b/test/integration/export-index-not-found-gsp/test/index.test.ts index c915d7af1b879..4032dcf45df0f 100644 --- a/test/integration/export-index-not-found-gsp/test/index.test.ts +++ b/test/integration/export-index-not-found-gsp/test/index.test.ts @@ -8,14 +8,16 @@ const appDir = join(__dirname, '../') const outdir = join(appDir, 'out') describe('Export index page with `notFound: true` in `getStaticProps`', () => { - it('should build successfully', async () => { - await fs.remove(join(appDir, '.next')) - const { code } = await nextBuild(appDir) - if (code !== 0) throw new Error(`build failed with status ${code}`) - }) + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + it('should build successfully', async () => { + await fs.remove(join(appDir, '.next')) + const { code } = await nextBuild(appDir) + if (code !== 0) throw new Error(`build failed with status ${code}`) + }) - it('should export successfully', async () => { - const { code } = await nextExport(appDir, { outdir }) - if (code !== 0) throw new Error(`export failed with status ${code}`) + it('should export successfully', async () => { + const { code } = await nextExport(appDir, { outdir }) + if (code !== 0) throw new Error(`export failed with status ${code}`) + }) }) }) diff --git a/test/integration/export-progress-status-message/test/index.test.js b/test/integration/export-progress-status-message/test/index.test.js index 2daddeb22539a..e887c919d4d6b 100644 --- a/test/integration/export-progress-status-message/test/index.test.js +++ b/test/integration/export-progress-status-message/test/index.test.js @@ -6,30 +6,32 @@ import { nextBuild, nextExportDefault } from 'next-test-utils' const appDir = join(__dirname, '../') describe('Export cli prints progress info', () => { - let buildStdout - let exportStdout - beforeAll(async () => { - const buildResult = await nextBuild(appDir, [], { stdout: true }) - buildStdout = buildResult.stdout - const exportResult = await nextExportDefault(appDir, { stdout: true }) - exportStdout = exportResult.stdout - }) + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + let buildStdout + let exportStdout + beforeAll(async () => { + const buildResult = await nextBuild(appDir, [], { stdout: true }) + buildStdout = buildResult.stdout + const exportResult = await nextExportDefault(appDir, { stdout: true }) + exportStdout = exportResult.stdout + }) - it('build: should log with internally passed statusMessage', async () => { - const lines = buildStdout.split('\n') - // Search `info - Generating static pages (n/m)` line - const found = lines.some((line) => - /Generating static pages \(\d+\/\d+\)/.test(line) - ) + it('build: should log with internally passed statusMessage', async () => { + const lines = buildStdout.split('\n') + // Search `info - Generating static pages (n/m)` line + const found = lines.some((line) => + /Generating static pages \(\d+\/\d+\)/.test(line) + ) - expect(found).toBeTruthy() - }) + expect(found).toBeTruthy() + }) - it('export: should log with default label', async () => { - const lines = exportStdout.split('\n') - // Search `info - Exporting (n/m)` line - const found = lines.some((line) => /Exporting \(\d+\/\d+\)/.test(line)) + it('export: should log with default label', async () => { + const lines = exportStdout.split('\n') + // Search `info - Exporting (n/m)` line + const found = lines.some((line) => /Exporting \(\d+\/\d+\)/.test(line)) - expect(found).toBeTruthy() + expect(found).toBeTruthy() + }) }) }) diff --git a/test/integration/export-subfolders/test/index.test.js b/test/integration/export-subfolders/test/index.test.js index 6fcbee3dfeb22..4ed380f816264 100644 --- a/test/integration/export-subfolders/test/index.test.js +++ b/test/integration/export-subfolders/test/index.test.js @@ -10,27 +10,29 @@ const appDir = join(__dirname, '../') const outdir = join(appDir, 'out') describe('Export config#exportTrailingSlash set to false', () => { - beforeAll(async () => { - await nextBuild(appDir) - await nextExport(appDir, { outdir }) - }) + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + beforeAll(async () => { + await nextBuild(appDir) + await nextExport(appDir, { outdir }) + }) - it('should export pages as [filename].html instead of [filename]/index.html', async () => { - expect.assertions(6) + it('should export pages as [filename].html instead of [filename]/index.html', async () => { + expect.assertions(6) - await expect(access(join(outdir, 'index.html'))).resolves.toBe(undefined) - await expect(access(join(outdir, 'about.html'))).resolves.toBe(undefined) - await expect(access(join(outdir, 'posts.html'))).resolves.toBe(undefined) - await expect(access(join(outdir, 'posts', 'single.html'))).resolves.toBe( - undefined - ) + await expect(access(join(outdir, 'index.html'))).resolves.toBe(undefined) + await expect(access(join(outdir, 'about.html'))).resolves.toBe(undefined) + await expect(access(join(outdir, 'posts.html'))).resolves.toBe(undefined) + await expect(access(join(outdir, 'posts', 'single.html'))).resolves.toBe( + undefined + ) - const html = await readFile(join(outdir, 'index.html')) - const $ = cheerio.load(html) - expect($('p').text()).toBe('I am a home page') + const html = await readFile(join(outdir, 'index.html')) + const $ = cheerio.load(html) + expect($('p').text()).toBe('I am a home page') - const htmlSingle = await readFile(join(outdir, 'posts', 'single.html')) - const $single = cheerio.load(htmlSingle) - expect($single('p').text()).toBe('I am a single post') + const htmlSingle = await readFile(join(outdir, 'posts', 'single.html')) + const $single = cheerio.load(htmlSingle) + expect($single('p').text()).toBe('I am a single post') + }) }) }) diff --git a/test/integration/externals-pages-bundle/test/index.test.js b/test/integration/externals-pages-bundle/test/index.test.js index 9ada207985f70..11145e0e0862e 100644 --- a/test/integration/externals-pages-bundle/test/index.test.js +++ b/test/integration/externals-pages-bundle/test/index.test.js @@ -7,12 +7,14 @@ import { nextBuild } from 'next-test-utils' const appDir = join(__dirname, '../') describe('bundle pages externals with config.experimental.bundlePagesExternals', () => { - it('should have no externals with the config set', async () => { - await nextBuild(appDir, [], { stdout: true }) - const output = await fs.readFile( - join(appDir, '.next/server/pages/index.js'), - 'utf8' - ) - expect(output).not.toContain('require("external-package")') + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + it('should have no externals with the config set', async () => { + await nextBuild(appDir, [], { stdout: true }) + const output = await fs.readFile( + join(appDir, '.next/server/pages/index.js'), + 'utf8' + ) + expect(output).not.toContain('require("external-package")') + }) }) }) diff --git a/test/integration/fallback-modules/test/index.test.js b/test/integration/fallback-modules/test/index.test.js index 50213e5bdc508..41c7c1bd47d9f 100644 --- a/test/integration/fallback-modules/test/index.test.js +++ b/test/integration/fallback-modules/test/index.test.js @@ -7,48 +7,50 @@ import { join } from 'path' const fixturesDir = join(__dirname, '..', 'fixtures') -describe('Build Output', () => { - describe('Crypto Application', () => { - let stdout - const appDir = join(fixturesDir, 'with-crypto') - - beforeAll(async () => { - await remove(join(appDir, '.next')) - }) - - it('should not include crypto', async () => { - if (process.env.NEXT_PRIVATE_SKIP_SIZE_TESTS) { - return - } - - ;({ stdout } = await nextBuild(appDir, [], { - stdout: true, - })) - - console.log(stdout) - - 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 indexSize = parsePageSize('/') - const indexFirstLoad = parsePageFirstLoad('/') - - // expect(parseFloat(indexSize)).toBeLessThanOrEqual(3.1) - // expect(parseFloat(indexSize)).toBeGreaterThanOrEqual(2) - expect(indexSize.endsWith('kB')).toBe(true) - - // expect(parseFloat(indexFirstLoad)).toBeLessThanOrEqual(67.9) - // expect(parseFloat(indexFirstLoad)).toBeGreaterThanOrEqual(60) - expect(indexFirstLoad.endsWith('kB')).toBe(true) +describe('Fallback Modules', () => { + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + describe('Crypto Application', () => { + let stdout + const appDir = join(fixturesDir, 'with-crypto') + + beforeAll(async () => { + await remove(join(appDir, '.next')) + }) + + it('should not include crypto', async () => { + if (process.env.NEXT_PRIVATE_SKIP_SIZE_TESTS) { + return + } + + ;({ stdout } = await nextBuild(appDir, [], { + stdout: true, + })) + + console.log(stdout) + + 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 indexSize = parsePageSize('/') + const indexFirstLoad = parsePageFirstLoad('/') + + // expect(parseFloat(indexSize)).toBeLessThanOrEqual(3.1) + // expect(parseFloat(indexSize)).toBeGreaterThanOrEqual(2) + expect(indexSize.endsWith('kB')).toBe(true) + + // expect(parseFloat(indexFirstLoad)).toBeLessThanOrEqual(67.9) + // expect(parseFloat(indexFirstLoad)).toBeGreaterThanOrEqual(60) + expect(indexFirstLoad.endsWith('kB')).toBe(true) + }) }) }) }) diff --git a/test/integration/fetch-polyfill-ky-universal/test/index.test.js b/test/integration/fetch-polyfill-ky-universal/test/index.test.js index 8488da5c83b9f..5b8a86acabcc7 100644 --- a/test/integration/fetch-polyfill-ky-universal/test/index.test.js +++ b/test/integration/fetch-polyfill-ky-universal/test/index.test.js @@ -51,7 +51,7 @@ function runTests() { } describe('Fetch polyfill with ky-universal', () => { - describe('dev support', () => { + describe('development mode', () => { beforeAll(async () => { appPort = await findPort() await startApiServer() @@ -68,8 +68,7 @@ describe('Fetch polyfill with ky-universal', () => { runTests() }) - - describe('Server support', () => { + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { beforeAll(async () => { await startApiServer() await nextBuild(appDir, [], { diff --git a/test/integration/fetch-polyfill/test/index.test.js b/test/integration/fetch-polyfill/test/index.test.js index f90e953407053..d0face0ff09c3 100644 --- a/test/integration/fetch-polyfill/test/index.test.js +++ b/test/integration/fetch-polyfill/test/index.test.js @@ -70,7 +70,7 @@ function runTests() { } describe('Fetch polyfill', () => { - describe('dev support', () => { + describe('development mode', () => { beforeAll(async () => { appPort = await findPort() await startApiServer() @@ -87,8 +87,7 @@ describe('Fetch polyfill', () => { runTests() }) - - describe('Server support', () => { + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { beforeAll(async () => { await startApiServer() await nextBuild(appDir, [], { diff --git a/test/integration/firebase-grpc/test/index.test.js b/test/integration/firebase-grpc/test/index.test.js index ba6e3312c2644..d921796be5eb9 100644 --- a/test/integration/firebase-grpc/test/index.test.js +++ b/test/integration/firebase-grpc/test/index.test.js @@ -8,25 +8,35 @@ const appDir = path.join(__dirname, '..') const nextConfig = path.join(appDir, 'next.config.js') describe('Building Firebase', () => { - // TODO: investigate re-enabling this test in node 12 environment - it.skip('Throws an error when building with firebase dependency with worker_threads', async () => { - await fs.writeFile( - nextConfig, - `module.exports = { experimental: { workerThreads: true } }` - ) - const results = await nextBuild(appDir, [], { stdout: true, stderr: true }) - expect(results.stdout + results.stderr).toMatch(/Build error occurred/) - expect(results.stdout + results.stderr).toMatch( - /grpc_node\.node\. Module did not self-register\./ - ) - }) + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + // TODO: investigate re-enabling this test in node 12 environment + it.skip('Throws an error when building with firebase dependency with worker_threads', async () => { + await fs.writeFile( + nextConfig, + `module.exports = { experimental: { workerThreads: true } }` + ) + const results = await nextBuild(appDir, [], { + stdout: true, + stderr: true, + }) + expect(results.stdout + results.stderr).toMatch(/Build error occurred/) + expect(results.stdout + results.stderr).toMatch( + /grpc_node\.node\. Module did not self-register\./ + ) + }) - it('Throws no error when building with firebase dependency without worker_threads', async () => { - await fs.remove(nextConfig) - const results = await nextBuild(appDir, [], { stdout: true, stderr: true }) - expect(results.stdout + results.stderr).not.toMatch(/Build error occurred/) - expect(results.stdout + results.stderr).not.toMatch( - /grpc_node\.node\. Module did not self-register\./ - ) + it('Throws no error when building with firebase dependency without worker_threads', async () => { + await fs.remove(nextConfig) + const results = await nextBuild(appDir, [], { + stdout: true, + stderr: true, + }) + expect(results.stdout + results.stderr).not.toMatch( + /Build error occurred/ + ) + expect(results.stdout + results.stderr).not.toMatch( + /grpc_node\.node\. Module did not self-register\./ + ) + }) }) }) diff --git a/test/integration/future/test/index.test.js b/test/integration/future/test/index.test.js index 9258cdba2abd1..ca47e7a981465 100644 --- a/test/integration/future/test/index.test.js +++ b/test/integration/future/test/index.test.js @@ -15,20 +15,22 @@ let appPort let app describe('excludeDefaultMomentLocales', () => { - beforeAll(async () => { - appPort = await findPort() - await nextBuild(appDir) - app = await nextStart(appDir, appPort) - await renderViaHTTP(appPort, '/') - }) - afterAll(() => killApp(app)) + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + beforeAll(async () => { + appPort = await findPort() + await nextBuild(appDir) + app = await nextStart(appDir, appPort) + await renderViaHTTP(appPort, '/') + }) + afterAll(() => killApp(app)) - it('should load momentjs', async () => { - const browser = await webdriver(appPort, '/') - expect(await browser.elementByCss('h1').text()).toMatch(/current time/i) - const locales = await browser.eval('moment.locales()') - expect(locales).toEqual(['en']) - expect(locales.length).toBe(1) - await browser.close() + it('should load momentjs', async () => { + const browser = await webdriver(appPort, '/') + expect(await browser.elementByCss('h1').text()).toMatch(/current time/i) + const locales = await browser.eval('moment.locales()') + expect(locales).toEqual(['en']) + expect(locales.length).toBe(1) + await browser.close() + }) }) }) diff --git a/test/integration/gsp-extension/test/index.test.js b/test/integration/gsp-extension/test/index.test.js index a89cf2397fd13..0f43c0cab4cf9 100644 --- a/test/integration/gsp-extension/test/index.test.js +++ b/test/integration/gsp-extension/test/index.test.js @@ -18,41 +18,43 @@ let app const fileNames = ['1', '2.ext', '3.html'] describe('GS(S)P with file extension', () => { - beforeAll(async () => { - await fs.remove(join(appDir, '.next')) - const { code } = await nextBuild(appDir) - if (code !== 0) throw new Error(`build failed with code ${code}`) - - appPort = await findPort() - app = await nextStart(appDir, appPort) - }) - afterAll(() => killApp(app)) - - it('should support slug with different extensions', async () => { - const baseDir = join(appDir, '.next/server/pages') - fileNames.forEach((name) => { - const filePath = join(baseDir, name) - expect(fs.existsSync(filePath + '.html')).toBe(true) - expect(fs.existsSync(filePath + '.json')).toBe(true) + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + beforeAll(async () => { + await fs.remove(join(appDir, '.next')) + const { code } = await nextBuild(appDir) + if (code !== 0) throw new Error(`build failed with code ${code}`) + + appPort = await findPort() + app = await nextStart(appDir, appPort) + }) + afterAll(() => killApp(app)) + + it('should support slug with different extensions', async () => { + const baseDir = join(appDir, '.next/server/pages') + fileNames.forEach((name) => { + const filePath = join(baseDir, name) + expect(fs.existsSync(filePath + '.html')).toBe(true) + expect(fs.existsSync(filePath + '.json')).toBe(true) + }) }) - }) - it('should render properly for routes with extension', async () => { - const paths = fileNames.map((name) => `/${name}`) - const contentPromises = paths.map((path) => renderViaHTTP(appPort, path)) - const contents = await Promise.all(contentPromises) - contents.forEach((content, i) => expect(content).toContain(fileNames[i])) - }) + it('should render properly for routes with extension', async () => { + const paths = fileNames.map((name) => `/${name}`) + const contentPromises = paths.map((path) => renderViaHTTP(appPort, path)) + const contents = await Promise.all(contentPromises) + contents.forEach((content, i) => expect(content).toContain(fileNames[i])) + }) - it('should contain extension in name of json files in _next/data', async () => { - const buildId = await fs.readFile(join(appDir, '.next/BUILD_ID'), 'utf8') - const requests = fileNames.map((name) => { - const pathname = `/_next/data/${buildId}/${name}.json` - return fetchViaHTTP(appPort, pathname).then((r) => r.json()) + it('should contain extension in name of json files in _next/data', async () => { + const buildId = await fs.readFile(join(appDir, '.next/BUILD_ID'), 'utf8') + const requests = fileNames.map((name) => { + const pathname = `/_next/data/${buildId}/${name}.json` + return fetchViaHTTP(appPort, pathname).then((r) => r.json()) + }) + const results = await Promise.all(requests) + results.forEach((result, i) => + expect(result.pageProps.value).toBe(fileNames[i]) + ) }) - const results = await Promise.all(requests) - results.forEach((result, i) => - expect(result.pageProps.value).toBe(fileNames[i]) - ) }) }) diff --git a/test/integration/gssp-redirect-base-path/test/index.test.js b/test/integration/gssp-redirect-base-path/test/index.test.js index 055e9824ea297..075bd47d2d154 100644 --- a/test/integration/gssp-redirect-base-path/test/index.test.js +++ b/test/integration/gssp-redirect-base-path/test/index.test.js @@ -499,13 +499,12 @@ describe('GS(S)P Redirect Support', () => { afterAll(() => killApp(app)) runTests() - }) - it('should error for redirect during prerendering', async () => { - await fs.mkdirp(join(appDir, 'pages/invalid')) - await fs.writeFile( - join(appDir, 'pages', 'invalid', '[slug].js'), - ` + it('should error for redirect during prerendering', async () => { + await fs.mkdirp(join(appDir, 'pages/invalid')) + await fs.writeFile( + join(appDir, 'pages', 'invalid', '[slug].js'), + ` export default function Post(props) { return "hi" } @@ -526,16 +525,17 @@ describe('GS(S)P Redirect Support', () => { } } ` - ) - const { stdout, stderr } = await nextBuild(appDir, undefined, { - stdout: true, - stderr: true, - }) - const output = stdout + stderr - await fs.remove(join(appDir, 'pages/invalid')) + ) + const { stdout, stderr } = await nextBuild(appDir, undefined, { + stdout: true, + stderr: true, + }) + const output = stdout + stderr + await fs.remove(join(appDir, 'pages/invalid')) - expect(output).toContain( - '`redirect` can not be returned from getStaticProps during prerendering' - ) + expect(output).toContain( + '`redirect` can not be returned from getStaticProps during prerendering' + ) + }) }) }) diff --git a/test/integration/gssp-redirect/test/index.test.js b/test/integration/gssp-redirect/test/index.test.js index 2c52a55c51867..6338402ed93ad 100644 --- a/test/integration/gssp-redirect/test/index.test.js +++ b/test/integration/gssp-redirect/test/index.test.js @@ -537,13 +537,12 @@ describe('GS(S)P Redirect Support', () => { it('should not have errors in output', async () => { expect(output).not.toContain('Failed to update prerender files') }) - }) - it('should error for redirect during prerendering', async () => { - await fs.mkdirp(join(appDir, 'pages/invalid')) - await fs.writeFile( - join(appDir, 'pages', 'invalid', '[slug].js'), - ` + it('should error for redirect during prerendering', async () => { + await fs.mkdirp(join(appDir, 'pages/invalid')) + await fs.writeFile( + join(appDir, 'pages', 'invalid', '[slug].js'), + ` export default function Post(props) { return "hi" } @@ -564,16 +563,17 @@ describe('GS(S)P Redirect Support', () => { } } ` - ) - const { stdout, stderr } = await nextBuild(appDir, undefined, { - stdout: true, - stderr: true, - }) - const output = stdout + stderr - await fs.remove(join(appDir, 'pages/invalid')) + ) + const { stdout, stderr } = await nextBuild(appDir, undefined, { + stdout: true, + stderr: true, + }) + const output = stdout + stderr + await fs.remove(join(appDir, 'pages/invalid')) - expect(output).toContain( - '`redirect` can not be returned from getStaticProps during prerendering' - ) + expect(output).toContain( + '`redirect` can not be returned from getStaticProps during prerendering' + ) + }) }) }) diff --git a/test/integration/handles-export-errors/test/index.test.js b/test/integration/handles-export-errors/test/index.test.js index bce7db44ffced..ad451841b64ef 100644 --- a/test/integration/handles-export-errors/test/index.test.js +++ b/test/integration/handles-export-errors/test/index.test.js @@ -6,22 +6,24 @@ import { nextBuild } from 'next-test-utils' const appDir = path.join(__dirname, '..') describe('Handles Errors During Export', () => { - it('Does not crash workers', async () => { - const { stdout, stderr } = await nextBuild(appDir, [], { - stdout: true, - stderr: true, - }) + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + it('Does not crash workers', async () => { + const { stdout, stderr } = await nextBuild(appDir, [], { + stdout: true, + stderr: true, + }) - expect(stdout + stderr).not.toMatch(/ERR_IPC_CHANNEL_CLOSED/) - expect(stderr).toContain('Export encountered errors on following paths') - expect(stderr).toContain('/page') - expect(stderr).toContain('/page-1') - expect(stderr).toContain('/page-2') - expect(stderr).toContain('/page-3') - expect(stderr).toContain('/page-13') - expect(stderr).toContain('/blog/[slug]: /blog/first') - expect(stderr).toContain('/blog/[slug]: /blog/second') - expect(stderr).toContain('/custom-error') - expect(stderr).toContain('custom error message') + expect(stdout + stderr).not.toMatch(/ERR_IPC_CHANNEL_CLOSED/) + expect(stderr).toContain('Export encountered errors on following paths') + expect(stderr).toContain('/page') + expect(stderr).toContain('/page-1') + expect(stderr).toContain('/page-2') + expect(stderr).toContain('/page-3') + expect(stderr).toContain('/page-13') + expect(stderr).toContain('/blog/[slug]: /blog/first') + expect(stderr).toContain('/blog/[slug]: /blog/second') + expect(stderr).toContain('/custom-error') + expect(stderr).toContain('custom error message') + }) }) }) diff --git a/test/integration/hydrate-then-render/test/index.test.js b/test/integration/hydrate-then-render/test/index.test.js index 83a634de7a60f..9e075766c2da8 100644 --- a/test/integration/hydrate-then-render/test/index.test.js +++ b/test/integration/hydrate-then-render/test/index.test.js @@ -9,28 +9,30 @@ let appPort let server describe('hydrate/render ordering', () => { - beforeAll(async () => { - appPort = await findPort() - await nextBuild(appDir, [], {}) - server = await nextStart(appDir, appPort) - }) - afterAll(() => killApp(server)) + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + beforeAll(async () => { + appPort = await findPort() + await nextBuild(appDir, [], {}) + server = await nextStart(appDir, appPort) + }) + afterAll(() => killApp(server)) - it('correctly measures hydrate followed by render', async () => { - const browser = await webdriver(appPort, '/') - await browser.waitForElementByCss('#to-other') - await browser.elementByCss('#to-other').click() - await browser.waitForElementByCss('#on-other') + it('correctly measures hydrate followed by render', async () => { + const browser = await webdriver(appPort, '/') + await browser.waitForElementByCss('#to-other') + await browser.elementByCss('#to-other').click() + await browser.waitForElementByCss('#on-other') - const beacons = (await browser.eval('window.__BEACONS')) - .map(([, value]) => Object.fromEntries(new URLSearchParams(value))) - .filter((p) => p.label === 'custom') - expect(beacons).toMatchObject([ - { name: 'Next.js-hydration' }, - { name: 'Next.js-render' }, - { name: 'Next.js-route-change-to-render' }, - ]) + const beacons = (await browser.eval('window.__BEACONS')) + .map(([, value]) => Object.fromEntries(new URLSearchParams(value))) + .filter((p) => p.label === 'custom') + expect(beacons).toMatchObject([ + { name: 'Next.js-hydration' }, + { name: 'Next.js-render' }, + { name: 'Next.js-route-change-to-render' }, + ]) - await browser.close() + await browser.close() + }) }) }) diff --git a/test/integration/i18n-support-base-path/test/index.test.js b/test/integration/i18n-support-base-path/test/index.test.js index 66045f8519aac..822d50b79fc8b 100644 --- a/test/integration/i18n-support-base-path/test/index.test.js +++ b/test/integration/i18n-support-base-path/test/index.test.js @@ -78,100 +78,105 @@ describe('i18n Support basePath', () => { }) describe('with localeDetection disabled', () => { - beforeAll(async () => { - await fs.remove(join(appDir, '.next')) - nextConfig.replace('// localeDetection', 'localeDetection') + ;(process.env.TURBOPACK ? describe.skip : describe)( + 'production mode', + () => { + beforeAll(async () => { + await fs.remove(join(appDir, '.next')) + nextConfig.replace('// localeDetection', 'localeDetection') - await nextBuild(appDir) - ctx.appPort = await findPort() - ctx.app = await nextStart(appDir, ctx.appPort) - }) - afterAll(async () => { - nextConfig.restore() - await killApp(ctx.app) - }) + await nextBuild(appDir) + ctx.appPort = await findPort() + ctx.app = await nextStart(appDir, ctx.appPort) + }) + afterAll(async () => { + nextConfig.restore() + await killApp(ctx.app) + }) - it('should have localeDetection in routes-manifest', async () => { - const routesManifest = await fs.readJSON( - join(appDir, '.next/routes-manifest.json') - ) + it('should have localeDetection in routes-manifest', async () => { + const routesManifest = await fs.readJSON( + join(appDir, '.next/routes-manifest.json') + ) - expect(routesManifest.i18n).toEqual({ - localeDetection: false, - locales: [ - 'en-US', - 'nl-NL', - 'nl-BE', - 'nl', - 'fr-BE', - 'fr', - 'en', - 'go', - 'go-BE', - 'do', - 'do-BE', - ], - defaultLocale: 'en-US', - domains: [ - { - http: true, - domain: 'example.do', - defaultLocale: 'do', - locales: ['do-BE'], - }, - { - domain: 'example.com', - defaultLocale: 'go', - locales: ['go-BE'], - }, - ], - }) - }) + expect(routesManifest.i18n).toEqual({ + localeDetection: false, + locales: [ + 'en-US', + 'nl-NL', + 'nl-BE', + 'nl', + 'fr-BE', + 'fr', + 'en', + 'go', + 'go-BE', + 'do', + 'do-BE', + ], + defaultLocale: 'en-US', + domains: [ + { + http: true, + domain: 'example.do', + defaultLocale: 'do', + locales: ['do-BE'], + }, + { + domain: 'example.com', + defaultLocale: 'go', + locales: ['go-BE'], + }, + ], + }) + }) - it('should not detect locale from accept-language', async () => { - const res = await fetchViaHTTP( - ctx.appPort, - `${ctx.basePath || '/'}`, - {}, - { - redirect: 'manual', - headers: { - 'accept-language': 'fr', - }, - } - ) + it('should not detect locale from accept-language', async () => { + const res = await fetchViaHTTP( + ctx.appPort, + `${ctx.basePath || '/'}`, + {}, + { + redirect: 'manual', + headers: { + 'accept-language': 'fr', + }, + } + ) - expect(res.status).toBe(200) - const $ = cheerio.load(await res.text()) - expect($('html').attr('lang')).toBe('en-US') - expect($('#router-locale').text()).toBe('en-US') - expect(JSON.parse($('#router-locales').text())).toEqual(locales) - expect($('#router-pathname').text()).toBe('/') - expect($('#router-as-path').text()).toBe('/') - }) + expect(res.status).toBe(200) + const $ = cheerio.load(await res.text()) + expect($('html').attr('lang')).toBe('en-US') + expect($('#router-locale').text()).toBe('en-US') + expect(JSON.parse($('#router-locales').text())).toEqual(locales) + expect($('#router-pathname').text()).toBe('/') + expect($('#router-as-path').text()).toBe('/') + }) - it('should set locale from detected path', async () => { - for (const locale of locales) { - const res = await fetchViaHTTP( - ctx.appPort, - `${ctx.basePath}/${locale}`, - {}, - { - redirect: 'manual', - headers: { - 'accept-language': 'en-US,en;q=0.9', - }, - } - ) + it('should set locale from detected path', async () => { + for (const locale of locales) { + const res = await fetchViaHTTP( + ctx.appPort, + `${ctx.basePath}/${locale}`, + {}, + { + redirect: 'manual', + headers: { + 'accept-language': 'en-US,en;q=0.9', + }, + } + ) - expect(res.status).toBe(200) - const $ = cheerio.load(await res.text()) - expect($('html').attr('lang')).toBe(locale) - expect($('#router-locale').text()).toBe(locale) - expect(JSON.parse($('#router-locales').text())).toEqual(locales) - expect($('#router-pathname').text()).toBe('/') - expect($('#router-as-path').text()).toBe('/') + expect(res.status).toBe(200) + const $ = cheerio.load(await res.text()) + expect($('html').attr('lang')).toBe(locale) + expect($('#router-locale').text()).toBe(locale) + expect(JSON.parse($('#router-locales').text())).toEqual(locales) + expect($('#router-pathname').text()).toBe('/') + expect($('#router-as-path').text()).toBe('/') + } + }) } - }) + ) }) }) diff --git a/test/integration/i18n-support/test/index.test.js b/test/integration/i18n-support/test/index.test.js index 6a06cc4899288..e4f1eea9534ca 100644 --- a/test/integration/i18n-support/test/index.test.js +++ b/test/integration/i18n-support/test/index.test.js @@ -88,123 +88,128 @@ describe('i18n Support', () => { }) describe('with localeDetection disabled', () => { - beforeAll(async () => { - await fs.remove(join(appDir, '.next')) - nextConfig.replace('// localeDetection', 'localeDetection') + ;(process.env.TURBOPACK ? describe.skip : describe)( + 'production mode', + () => { + beforeAll(async () => { + await fs.remove(join(appDir, '.next')) + nextConfig.replace('// localeDetection', 'localeDetection') - await nextBuild(appDir) - ctx.appPort = await findPort() - ctx.app = await nextStart(appDir, ctx.appPort) - }) - afterAll(async () => { - nextConfig.restore() - await killApp(ctx.app) - }) + await nextBuild(appDir) + ctx.appPort = await findPort() + ctx.app = await nextStart(appDir, ctx.appPort) + }) + afterAll(async () => { + nextConfig.restore() + await killApp(ctx.app) + }) - it('should have localeDetection in routes-manifest', async () => { - const routesManifest = await fs.readJSON( - join(appDir, '.next/routes-manifest.json') - ) + it('should have localeDetection in routes-manifest', async () => { + const routesManifest = await fs.readJSON( + join(appDir, '.next/routes-manifest.json') + ) - expect(routesManifest.i18n).toEqual({ - localeDetection: false, - locales: [ - 'en-US', - 'nl-NL', - 'nl-BE', - 'nl', - 'fr-BE', - 'fr', - 'en', - 'go', - 'go-BE', - 'do', - 'do-BE', - ], - defaultLocale: 'en-US', - domains: [ - { - http: true, - domain: 'example.do', - defaultLocale: 'do', - locales: ['do-BE'], - }, - { - domain: 'example.com', - defaultLocale: 'go', - locales: ['go-BE'], - }, - ], - }) - }) + expect(routesManifest.i18n).toEqual({ + localeDetection: false, + locales: [ + 'en-US', + 'nl-NL', + 'nl-BE', + 'nl', + 'fr-BE', + 'fr', + 'en', + 'go', + 'go-BE', + 'do', + 'do-BE', + ], + defaultLocale: 'en-US', + domains: [ + { + http: true, + domain: 'example.do', + defaultLocale: 'do', + locales: ['do-BE'], + }, + { + domain: 'example.com', + defaultLocale: 'go', + locales: ['go-BE'], + }, + ], + }) + }) - it('should not detect locale from accept-language', async () => { - const res = await fetchViaHTTP( - ctx.appPort, - '/', - {}, - { - redirect: 'manual', - headers: { - 'accept-language': 'fr', - }, - } - ) + it('should not detect locale from accept-language', async () => { + const res = await fetchViaHTTP( + ctx.appPort, + '/', + {}, + { + redirect: 'manual', + headers: { + 'accept-language': 'fr', + }, + } + ) - expect(res.status).toBe(200) - const $ = cheerio.load(await res.text()) - expect($('html').attr('lang')).toBe('en-US') - expect($('#router-locale').text()).toBe('en-US') - expect(JSON.parse($('#router-locales').text())).toEqual(locales) - expect($('#router-pathname').text()).toBe('/') - expect($('#router-as-path').text()).toBe('/') - }) + expect(res.status).toBe(200) + const $ = cheerio.load(await res.text()) + expect($('html').attr('lang')).toBe('en-US') + expect($('#router-locale').text()).toBe('en-US') + expect(JSON.parse($('#router-locales').text())).toEqual(locales) + expect($('#router-pathname').text()).toBe('/') + expect($('#router-as-path').text()).toBe('/') + }) - it('should ignore the invalid accept-language header', async () => { - nextConfig.replace('localeDetection: false', 'localeDetection: true') - const res = await fetchViaHTTP( - ctx.appPort, - '/', - {}, - { - headers: { - 'accept-language': 'ldfir;', - }, - } - ) + it('should ignore the invalid accept-language header', async () => { + nextConfig.replace('localeDetection: false', 'localeDetection: true') + const res = await fetchViaHTTP( + ctx.appPort, + '/', + {}, + { + headers: { + 'accept-language': 'ldfir;', + }, + } + ) - expect(res.status).toBe(200) - const $ = cheerio.load(await res.text()) - expect($('html').attr('lang')).toBe('en-US') - expect($('#router-locale').text()).toBe('en-US') - expect(JSON.parse($('#router-locales').text())).toEqual(locales) - expect($('#router-pathname').text()).toBe('/') - expect($('#router-as-path').text()).toBe('/') - }) + expect(res.status).toBe(200) + const $ = cheerio.load(await res.text()) + expect($('html').attr('lang')).toBe('en-US') + expect($('#router-locale').text()).toBe('en-US') + expect(JSON.parse($('#router-locales').text())).toEqual(locales) + expect($('#router-pathname').text()).toBe('/') + expect($('#router-as-path').text()).toBe('/') + }) - it('should set locale from detected path', async () => { - for (const locale of nonDomainLocales) { - const res = await fetchViaHTTP( - ctx.appPort, - `/${locale}`, - {}, - { - redirect: 'manual', - headers: { - 'accept-language': 'en-US,en;q=0.9', - }, - } - ) + it('should set locale from detected path', async () => { + for (const locale of nonDomainLocales) { + const res = await fetchViaHTTP( + ctx.appPort, + `/${locale}`, + {}, + { + redirect: 'manual', + headers: { + 'accept-language': 'en-US,en;q=0.9', + }, + } + ) - expect(res.status).toBe(200) - const $ = cheerio.load(await res.text()) - expect($('html').attr('lang')).toBe(locale) - expect($('#router-locale').text()).toBe(locale) - expect(JSON.parse($('#router-locales').text())).toEqual(locales) - expect($('#router-pathname').text()).toBe('/') - expect($('#router-as-path').text()).toBe('/') + expect(res.status).toBe(200) + const $ = cheerio.load(await res.text()) + expect($('html').attr('lang')).toBe(locale) + expect($('#router-locale').text()).toBe(locale) + expect(JSON.parse($('#router-locales').text())).toEqual(locales) + expect($('#router-pathname').text()).toBe('/') + expect($('#router-as-path').text()).toBe('/') + } + }) } - }) + ) }) describe('with trailingSlash: true', () => { @@ -520,9 +525,9 @@ describe('i18n Support', () => { } ) }) - - it('should show proper error for duplicate defaultLocales', async () => { - nextConfig.write(` + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + it('should show proper error for duplicate defaultLocales', async () => { + nextConfig.write(` module.exports = { i18n: { locales: ['en', 'fr', 'nl'], @@ -545,18 +550,18 @@ describe('i18n Support', () => { } `) - const { code, stderr } = await nextBuild(appDir, undefined, { - stderr: true, + const { code, stderr } = await nextBuild(appDir, undefined, { + stderr: true, + }) + nextConfig.restore() + expect(code).toBe(1) + expect(stderr).toContain( + 'Both fr.example.com and french.example.com configured the defaultLocale fr but only one can' + ) }) - nextConfig.restore() - expect(code).toBe(1) - expect(stderr).toContain( - 'Both fr.example.com and french.example.com configured the defaultLocale fr but only one can' - ) - }) - it('should show proper error for duplicate locales', async () => { - nextConfig.write(` + it('should show proper error for duplicate locales', async () => { + nextConfig.write(` module.exports = { i18n: { locales: ['en', 'fr', 'nl', 'eN', 'fr'], @@ -565,19 +570,19 @@ describe('i18n Support', () => { } `) - const { code, stderr } = await nextBuild(appDir, undefined, { - stderr: true, + const { code, stderr } = await nextBuild(appDir, undefined, { + stderr: true, + }) + nextConfig.restore() + expect(code).toBe(1) + expect(stderr).toContain( + 'Specified i18n.locales contains the following duplicate locales:' + ) + expect(stderr).toContain(`eN, fr`) }) - nextConfig.restore() - expect(code).toBe(1) - expect(stderr).toContain( - 'Specified i18n.locales contains the following duplicate locales:' - ) - expect(stderr).toContain(`eN, fr`) - }) - it('should show proper error for invalid locale domain', async () => { - nextConfig.write(` + it('should show proper error for invalid locale domain', async () => { + nextConfig.write(` module.exports = { i18n: { locales: ['en', 'fr', 'nl', 'eN', 'fr'], @@ -592,13 +597,14 @@ describe('i18n Support', () => { } `) - const { code, stderr } = await nextBuild(appDir, undefined, { - stderr: true, + const { code, stderr } = await nextBuild(appDir, undefined, { + stderr: true, + }) + nextConfig.restore() + expect(code).toBe(1) + expect(stderr).toContain( + `i18n domain: "hello:3000" is invalid it should be a valid domain without protocol (https://) or port (:3000) e.g. example.vercel.sh` + ) }) - nextConfig.restore() - expect(code).toBe(1) - expect(stderr).toContain( - `i18n domain: "hello:3000" is invalid it should be a valid domain without protocol (https://) or port (:3000) e.g. example.vercel.sh` - ) }) }) diff --git a/test/integration/image-optimizer/test/index.test.ts b/test/integration/image-optimizer/test/index.test.ts index 662049e091d1b..b0209037a3135 100644 --- a/test/integration/image-optimizer/test/index.test.ts +++ b/test/integration/image-optimizer/test/index.test.ts @@ -483,14 +483,17 @@ describe('Image Optimizer', () => { }) describe('Server support for headers in next.config.js', () => { - const size = 96 // defaults defined in server/config.ts - let app - let appPort - - beforeAll(async () => { - nextConfig.replace( - '{ /* replaceme */ }', - `{ + ;(process.env.TURBOPACK ? describe.skip : describe)( + 'production mode', + () => { + const size = 96 // defaults defined in server/config.ts + let app + let appPort + + beforeAll(async () => { + nextConfig.replace( + '{ /* replaceme */ }', + `{ async headers() { return [ { @@ -505,58 +508,62 @@ describe('Image Optimizer', () => { ] }, }` - ) - await nextBuild(appDir) - await cleanImagesDir({ imagesDir }) - appPort = await findPort() - app = await nextStart(appDir, appPort) - }) - afterAll(async () => { - await killApp(app) - nextConfig.restore() - }) - - it('should set max-age header', async () => { - const query = { url: '/test.png', w: size, q: 75 } - const opts = { headers: { accept: 'image/webp' } } - const res = await fetchViaHTTP(appPort, '/_next/image', query, opts) - expect(res.status).toBe(200) - expect(res.headers.get('Cache-Control')).toBe( - `public, max-age=86400, must-revalidate` - ) - expect(res.headers.get('Content-Disposition')).toBe( - `inline; filename="test.webp"` - ) - - await check(async () => { - const files = await fsToJson(imagesDir) - - let found = false - const maxAge = '86400' + ) + await nextBuild(appDir) + await cleanImagesDir({ imagesDir }) + appPort = await findPort() + app = await nextStart(appDir, appPort) + }) + afterAll(async () => { + await killApp(app) + nextConfig.restore() + }) - Object.keys(files).forEach((dir) => { - if ( - Object.keys(files[dir]).some((file) => file.includes(`${maxAge}.`)) - ) { - found = true - } + it('should set max-age header', async () => { + const query = { url: '/test.png', w: size, q: 75 } + const opts = { headers: { accept: 'image/webp' } } + const res = await fetchViaHTTP(appPort, '/_next/image', query, opts) + expect(res.status).toBe(200) + expect(res.headers.get('Cache-Control')).toBe( + `public, max-age=86400, must-revalidate` + ) + expect(res.headers.get('Content-Disposition')).toBe( + `inline; filename="test.webp"` + ) + + await check(async () => { + const files = await fsToJson(imagesDir) + + let found = false + const maxAge = '86400' + + Object.keys(files).forEach((dir) => { + if ( + Object.keys(files[dir]).some((file) => + file.includes(`${maxAge}.`) + ) + ) { + found = true + } + }) + return found ? 'success' : 'failed' + }, 'success') }) - return found ? 'success' : 'failed' - }, 'success') - }) - it('should not set max-age header when not matching next.config.js', async () => { - const query = { url: '/test.jpg', w: size, q: 75 } - const opts = { headers: { accept: 'image/webp' } } - const res = await fetchViaHTTP(appPort, '/_next/image', query, opts) - expect(res.status).toBe(200) - expect(res.headers.get('Cache-Control')).toBe( - `public, max-age=60, must-revalidate` - ) - expect(res.headers.get('Content-Disposition')).toBe( - `inline; filename="test.webp"` - ) - }) + it('should not set max-age header when not matching next.config.js', async () => { + const query = { url: '/test.jpg', w: size, q: 75 } + const opts = { headers: { accept: 'image/webp' } } + const res = await fetchViaHTTP(appPort, '/_next/image', query, opts) + expect(res.status).toBe(200) + expect(res.headers.get('Cache-Control')).toBe( + `public, max-age=60, must-revalidate` + ) + expect(res.headers.get('Content-Disposition')).toBe( + `inline; filename="test.webp"` + ) + }) + } + ) }) describe('dev support next.config.js cloudinary loader', () => { @@ -619,11 +626,14 @@ describe('Image Optimizer', () => { }) describe('External rewrite support with for serving static content in images', () => { - let app - let appPort - - beforeAll(async () => { - const newConfig = `{ + ;(process.env.TURBOPACK ? describe.skip : describe)( + 'production mode', + () => { + let app + let appPort + + beforeAll(async () => { + const newConfig = `{ async rewrites() { return [ { @@ -633,50 +643,54 @@ describe('Image Optimizer', () => { ] }, }` - nextConfig.replace('{ /* replaceme */ }', newConfig) - await nextBuild(appDir) - await cleanImagesDir({ imagesDir }) - appPort = await findPort() - app = await nextStart(appDir, appPort) - }) - afterAll(async () => { - await killApp(app) - nextConfig.restore() - }) - - it('should return response when image is served from an external rewrite', async () => { - await cleanImagesDir({ imagesDir }) - - const query = { url: '/next-js/next-js-bg.png', w: 64, q: 75 } - const opts = { headers: { accept: 'image/webp' } } - const res = await fetchViaHTTP(appPort, '/_next/image', query, opts) - expect(res.status).toBe(200) - expect(res.headers.get('Content-Type')).toBe('image/webp') - expect(res.headers.get('Cache-Control')).toBe( - `public, max-age=31536000, must-revalidate` - ) - expect(res.headers.get('Vary')).toBe('Accept') - expect(res.headers.get('Content-Disposition')).toBe( - `inline; filename="next-js-bg.webp"` - ) - - await check(async () => { - const files = await fsToJson(imagesDir) - - let found = false - const maxAge = '31536000' + nextConfig.replace('{ /* replaceme */ }', newConfig) + await nextBuild(appDir) + await cleanImagesDir({ imagesDir }) + appPort = await findPort() + app = await nextStart(appDir, appPort) + }) + afterAll(async () => { + await killApp(app) + nextConfig.restore() + }) - Object.keys(files).forEach((dir) => { - if ( - Object.keys(files[dir]).some((file) => file.includes(`${maxAge}.`)) - ) { - found = true - } + it('should return response when image is served from an external rewrite', async () => { + await cleanImagesDir({ imagesDir }) + + const query = { url: '/next-js/next-js-bg.png', w: 64, q: 75 } + const opts = { headers: { accept: 'image/webp' } } + const res = await fetchViaHTTP(appPort, '/_next/image', query, opts) + expect(res.status).toBe(200) + expect(res.headers.get('Content-Type')).toBe('image/webp') + expect(res.headers.get('Cache-Control')).toBe( + `public, max-age=31536000, must-revalidate` + ) + expect(res.headers.get('Vary')).toBe('Accept') + expect(res.headers.get('Content-Disposition')).toBe( + `inline; filename="next-js-bg.webp"` + ) + + await check(async () => { + const files = await fsToJson(imagesDir) + + let found = false + const maxAge = '31536000' + + Object.keys(files).forEach((dir) => { + if ( + Object.keys(files[dir]).some((file) => + file.includes(`${maxAge}.`) + ) + ) { + found = true + } + }) + return found ? 'success' : 'failed' + }, 'success') + await expectWidth(res, 64) }) - return found ? 'success' : 'failed' - }, 'success') - await expectWidth(res, 64) - }) + } + ) }) describe('dev support for dynamic blur placeholder', () => { diff --git a/test/integration/invalid-config-values/test/index.test.js b/test/integration/invalid-config-values/test/index.test.js index 6ee53558811a7..915c81b914bb8 100644 --- a/test/integration/invalid-config-values/test/index.test.js +++ b/test/integration/invalid-config-values/test/index.test.js @@ -10,29 +10,31 @@ const nextConfigPath = join(appDir, 'next.config.js') const cleanUp = () => fs.remove(nextConfigPath) describe('Handles valid/invalid assetPrefix', () => { - beforeAll(() => cleanUp()) - afterAll(() => cleanUp()) - - it('should not error without usage of assetPrefix', async () => { - await fs.writeFile( - nextConfigPath, - `module.exports = { + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + beforeAll(() => cleanUp()) + afterAll(() => cleanUp()) + + it('should not error without usage of assetPrefix', async () => { + await fs.writeFile( + nextConfigPath, + `module.exports = { }` - ) + ) - const { stderr } = await nextBuild(appDir, undefined, { stderr: true }) - expect(stderr).not.toMatch(/Specified assetPrefix is not a string/) - }) + const { stderr } = await nextBuild(appDir, undefined, { stderr: true }) + expect(stderr).not.toMatch(/Specified assetPrefix is not a string/) + }) - it('should not error when assetPrefix is a string', async () => { - await fs.writeFile( - nextConfigPath, - `module.exports = { + it('should not error when assetPrefix is a string', async () => { + await fs.writeFile( + nextConfigPath, + `module.exports = { assetPrefix: '/hello' }` - ) + ) - const { stderr } = await nextBuild(appDir, undefined, { stderr: true }) - expect(stderr).not.toMatch(/Specified assetPrefix is not a string/) + const { stderr } = await nextBuild(appDir, undefined, { stderr: true }) + expect(stderr).not.toMatch(/Specified assetPrefix is not a string/) + }) }) }) diff --git a/test/integration/invalid-document-image-import/test/index.test.js b/test/integration/invalid-document-image-import/test/index.test.js index 6e6fa16418f95..59359db12e8fc 100644 --- a/test/integration/invalid-document-image-import/test/index.test.js +++ b/test/integration/invalid-document-image-import/test/index.test.js @@ -8,37 +8,39 @@ const appDir = join(__dirname, '../') const nextConfig = new File(join(appDir, 'next.config.js')) describe('Invalid static image import in _document', () => { - afterAll(() => nextConfig.restore()) + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + afterAll(() => nextConfig.restore()) - it('Should fail to build when no next.config.js', async () => { - const { code, stderr } = await nextBuild(appDir, [], { - stderr: true, + it('Should fail to build when no next.config.js', async () => { + const { code, stderr } = await nextBuild(appDir, [], { + stderr: true, + }) + expect(code).not.toBe(0) + expect(stderr).toContain('Failed to compile') + expect(stderr).toMatch( + /Images.*cannot.*be imported within.*pages[\\/]_document\.js/ + ) + expect(stderr).toMatch(/Location:.*pages[\\/]_document\.js/) }) - expect(code).not.toBe(0) - expect(stderr).toContain('Failed to compile') - expect(stderr).toMatch( - /Images.*cannot.*be imported within.*pages[\\/]_document\.js/ - ) - expect(stderr).toMatch(/Location:.*pages[\\/]_document\.js/) - }) - it('Should fail to build when disableStaticImages in next.config.js', async () => { - nextConfig.write(` + it('Should fail to build when disableStaticImages in next.config.js', async () => { + nextConfig.write(` module.exports = { images: { disableStaticImages: true } } `) - const { code, stderr } = await nextBuild(appDir, [], { - stderr: true, + const { code, stderr } = await nextBuild(appDir, [], { + stderr: true, + }) + expect(code).not.toBe(0) + expect(stderr).toMatch( + /You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file/ + ) + expect(stderr).not.toMatch( + /Images.*cannot.*be imported within.*pages[\\/]_document\.js/ + ) }) - expect(code).not.toBe(0) - expect(stderr).toMatch( - /You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file/ - ) - expect(stderr).not.toMatch( - /Images.*cannot.*be imported within.*pages[\\/]_document\.js/ - ) }) }) diff --git a/test/integration/invalid-page-automatic-static-optimization/test/index.test.js b/test/integration/invalid-page-automatic-static-optimization/test/index.test.js index bf12b6ded2989..574e66df77c5e 100644 --- a/test/integration/invalid-page-automatic-static-optimization/test/index.test.js +++ b/test/integration/invalid-page-automatic-static-optimization/test/index.test.js @@ -7,24 +7,28 @@ import { nextBuild } from 'next-test-utils' const appDir = path.join(__dirname, '..') describe('Invalid Page automatic static optimization', () => { - it('Fails softly with descriptive error', async () => { - const { stderr } = await nextBuild(appDir, [], { stderr: true }) + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + it('Fails softly with descriptive error', async () => { + const { stderr } = await nextBuild(appDir, [], { stderr: true }) - expect(stderr).toMatch( - /Build optimization failed: found pages without a React Component as default export in/ - ) - expect(stderr).toMatch(/pages\/invalid/) - expect(stderr).toMatch(/pages\/also-invalid/) - }) + expect(stderr).toMatch( + /Build optimization failed: found pages without a React Component as default export in/ + ) + expect(stderr).toMatch(/pages\/invalid/) + expect(stderr).toMatch(/pages\/also-invalid/) + }) - it('handles non-error correctly', async () => { - const testPage = path.join(appDir, 'pages/[slug].js') - await fs.rename(path.join(appDir, 'pages'), path.join(appDir, 'pages-bak')) + it('handles non-error correctly', async () => { + const testPage = path.join(appDir, 'pages/[slug].js') + await fs.rename( + path.join(appDir, 'pages'), + path.join(appDir, 'pages-bak') + ) - await fs.ensureDir(path.join(appDir, 'pages')) - await fs.writeFile( - testPage, - ` + await fs.ensureDir(path.join(appDir, 'pages')) + await fs.writeFile( + testPage, + ` export default function Page() { return

hello world

} @@ -41,18 +45,19 @@ describe('Invalid Page automatic static optimization', () => { } } ` - ) - - try { - const { stderr } = await nextBuild(appDir, [], { stderr: true }) - expect(stderr).toMatch(/invalid API token/) - expect(stderr).not.toMatch(/without a React Component/) - } finally { - await fs.remove(path.join(appDir, 'pages')) - await fs.rename( - path.join(appDir, 'pages-bak'), - path.join(appDir, 'pages') ) - } + + try { + const { stderr } = await nextBuild(appDir, [], { stderr: true }) + expect(stderr).toMatch(/invalid API token/) + expect(stderr).not.toMatch(/without a React Component/) + } finally { + await fs.remove(path.join(appDir, 'pages')) + await fs.rename( + path.join(appDir, 'pages-bak'), + path.join(appDir, 'pages') + ) + } + }) }) }) diff --git a/test/integration/jsconfig-baseurl/test/index.test.js b/test/integration/jsconfig-baseurl/test/index.test.js index 4ad014d0e8f03..bf593d7e32c25 100644 --- a/test/integration/jsconfig-baseurl/test/index.test.js +++ b/test/integration/jsconfig-baseurl/test/index.test.js @@ -65,19 +65,26 @@ describe('TypeScript Features', () => { }) describe('should build', () => { - beforeAll(async () => { - await nextBuild(appDir) - }) - it('should trace correctly', async () => { - const helloTrace = await fs.readJSON( - join(appDir, '.next/server/pages/hello.js.nft.json') - ) - expect( - helloTrace.files.some((file) => file.includes('components/world.js')) - ).toBe(false) - expect( - helloTrace.files.some((file) => file.includes('react/index.js')) - ).toBe(true) - }) + ;(process.env.TURBOPACK ? describe.skip : describe)( + 'production mode', + () => { + beforeAll(async () => { + await nextBuild(appDir) + }) + it('should trace correctly', async () => { + const helloTrace = await fs.readJSON( + join(appDir, '.next/server/pages/hello.js.nft.json') + ) + expect( + helloTrace.files.some((file) => + file.includes('components/world.js') + ) + ).toBe(false) + expect( + helloTrace.files.some((file) => file.includes('react/index.js')) + ).toBe(true) + }) + } + ) }) }) diff --git a/test/integration/jsconfig-empty/test/index.test.js b/test/integration/jsconfig-empty/test/index.test.js index 6a2a05560ad68..6ed2ad89846be 100644 --- a/test/integration/jsconfig-empty/test/index.test.js +++ b/test/integration/jsconfig-empty/test/index.test.js @@ -5,11 +5,13 @@ import { join } from 'path' const appDir = join(__dirname, '..') describe('Empty JSConfig Support', () => { - test('should compile successfully', async () => { - const { code, stdout } = await nextBuild(appDir, [], { - stdout: true, + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + test('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/) }) }) diff --git a/test/integration/jsconfig-paths/test/index.test.js b/test/integration/jsconfig-paths/test/index.test.js index bc3c635b9ce96..c5f408e029df6 100644 --- a/test/integration/jsconfig-paths/test/index.test.js +++ b/test/integration/jsconfig-paths/test/index.test.js @@ -85,60 +85,67 @@ function runTests() { }) describe('should build', () => { - beforeAll(async () => { - await nextBuild(appDir) - }) - it('should trace correctly', async () => { - const singleAliasTrace = await fs.readJSON( - join(appDir, '.next/server/pages/single-alias.js.nft.json') - ) - const wildcardAliasTrace = await fs.readJSON( - join(appDir, '.next/server/pages/wildcard-alias.js.nft.json') - ) - const resolveOrderTrace = await fs.readJSON( - join(appDir, '.next/server/pages/resolve-order.js.nft.json') - ) - const resolveFallbackTrace = await fs.readJSON( - join(appDir, '.next/server/pages/resolve-fallback.js.nft.json') - ) - const basicAliasTrace = await fs.readJSON( - join(appDir, '.next/server/pages/basic-alias.js.nft.json') - ) - - expect( - singleAliasTrace.files.some((file) => - file.includes('components/hello.js') - ) - ).toBe(false) - expect( - wildcardAliasTrace.files.some((file) => - file.includes('mypackage/myfile.js') - ) - ).toBe(true) - expect( - wildcardAliasTrace.files.some((file) => - file.includes('mypackage/data.js') - ) - ).toBe(false) - expect( - resolveOrderTrace.files.some((file) => file.includes('lib/a/api.js')) - ).toBe(false) - expect( - resolveOrderTrace.files.some((file) => - file.includes('mypackage/data.js') - ) - ).toBe(true) - expect( - resolveFallbackTrace.files.some((file) => - file.includes('lib/b/b-only.js') - ) - ).toBe(false) - expect( - basicAliasTrace.files.some((file) => - file.includes('components/world.js') - ) - ).toBe(false) - }) + ;(process.env.TURBOPACK ? describe.skip : describe)( + 'production mode', + () => { + beforeAll(async () => { + await nextBuild(appDir) + }) + it('should trace correctly', async () => { + const singleAliasTrace = await fs.readJSON( + join(appDir, '.next/server/pages/single-alias.js.nft.json') + ) + const wildcardAliasTrace = await fs.readJSON( + join(appDir, '.next/server/pages/wildcard-alias.js.nft.json') + ) + const resolveOrderTrace = await fs.readJSON( + join(appDir, '.next/server/pages/resolve-order.js.nft.json') + ) + const resolveFallbackTrace = await fs.readJSON( + join(appDir, '.next/server/pages/resolve-fallback.js.nft.json') + ) + const basicAliasTrace = await fs.readJSON( + join(appDir, '.next/server/pages/basic-alias.js.nft.json') + ) + + expect( + singleAliasTrace.files.some((file) => + file.includes('components/hello.js') + ) + ).toBe(false) + expect( + wildcardAliasTrace.files.some((file) => + file.includes('mypackage/myfile.js') + ) + ).toBe(true) + expect( + wildcardAliasTrace.files.some((file) => + file.includes('mypackage/data.js') + ) + ).toBe(false) + expect( + resolveOrderTrace.files.some((file) => + file.includes('lib/a/api.js') + ) + ).toBe(false) + expect( + resolveOrderTrace.files.some((file) => + file.includes('mypackage/data.js') + ) + ).toBe(true) + expect( + resolveFallbackTrace.files.some((file) => + file.includes('lib/b/b-only.js') + ) + ).toBe(false) + expect( + basicAliasTrace.files.some((file) => + file.includes('components/world.js') + ) + ).toBe(false) + }) + } + ) }) } diff --git a/test/integration/jsconfig/test/index.test.js b/test/integration/jsconfig/test/index.test.js index bf74ee6494117..6774060989875 100644 --- a/test/integration/jsconfig/test/index.test.js +++ b/test/integration/jsconfig/test/index.test.js @@ -7,27 +7,29 @@ import { nextBuild } from 'next-test-utils' const appDir = join(__dirname, '..') describe('jsconfig.json', () => { - it('should build normally', async () => { - const res = await await nextBuild(appDir, [], { stdout: true }) - expect(res.stdout).toMatch(/Compiled successfully/) - }) - - it('should fail on invalid jsconfig.json', async () => { - const jsconfigPath = join(appDir, 'jsconfig.json') - const originalJsconfig = await fs.readFile(jsconfigPath, { - encoding: 'utf-8', + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + it('should build normally', async () => { + const res = await await nextBuild(appDir, [], { stdout: true }) + expect(res.stdout).toMatch(/Compiled successfully/) }) - await fs.writeFile(jsconfigPath, '{', { - encoding: 'utf-8', - }) - try { - const res = await nextBuild(appDir, [], { stderr: true }) - expect(res.stderr).toMatch(/Error: Failed to parse "/) - expect(res.stderr).toMatch(/JSON5: invalid end of input at 1:2/) - } finally { - await fs.writeFile(jsconfigPath, originalJsconfig, { + + it('should fail on invalid jsconfig.json', async () => { + const jsconfigPath = join(appDir, 'jsconfig.json') + const originalJsconfig = await fs.readFile(jsconfigPath, { encoding: 'utf-8', }) - } + await fs.writeFile(jsconfigPath, '{', { + encoding: 'utf-8', + }) + try { + const res = await nextBuild(appDir, [], { stderr: true }) + expect(res.stderr).toMatch(/Error: Failed to parse "/) + expect(res.stderr).toMatch(/JSON5: invalid end of input at 1:2/) + } finally { + await fs.writeFile(jsconfigPath, originalJsconfig, { + encoding: 'utf-8', + }) + } + }) }) }) diff --git a/test/integration/json-serialize-original-error/test/index.test.js b/test/integration/json-serialize-original-error/test/index.test.js index 787834a0f577c..89a04b345e1ac 100644 --- a/test/integration/json-serialize-original-error/test/index.test.js +++ b/test/integration/json-serialize-original-error/test/index.test.js @@ -7,9 +7,11 @@ jest.setTimeout(1000 * 60 * 2) const appDir = join(__dirname, '..') describe('JSON Serialization', () => { - test('should fail with original error', async () => { - const { code, stderr } = await nextBuild(appDir, [], { stderr: true }) - expect(code).toBe(1) - expect(stderr).toContain('Do not know how to serialize a BigInt') + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + test('should fail with original error', async () => { + const { code, stderr } = await nextBuild(appDir, [], { stderr: true }) + expect(code).toBe(1) + expect(stderr).toContain('Do not know how to serialize a BigInt') + }) }) }) diff --git a/test/integration/middleware-basic/test/index.test.js b/test/integration/middleware-basic/test/index.test.js index 62a1c5ad1d93a..153c62dae5b41 100644 --- a/test/integration/middleware-basic/test/index.test.js +++ b/test/integration/middleware-basic/test/index.test.js @@ -34,7 +34,7 @@ describe('dev mode', () => { }) // TODO enable that once turbopack supports middleware in dev mode -describe.skip('production mode', () => { +;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { beforeAll(async () => { await nextBuild(appDir) diff --git a/test/integration/middleware-build-errors/test/index.test.js b/test/integration/middleware-build-errors/test/index.test.js index 99ab65ebf3d37..ae2661eb542a2 100644 --- a/test/integration/middleware-build-errors/test/index.test.js +++ b/test/integration/middleware-build-errors/test/index.test.js @@ -3,89 +3,91 @@ import { nextBuild } from 'next-test-utils' import { join } from 'path' describe('Middleware validation during build', () => { - const appDir = join(__dirname, '..') - const middlewareFile = join(appDir, 'middleware.js') - const middlewareError = 'Middleware is returning a response body' + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + const appDir = join(__dirname, '..') + const middlewareFile = join(appDir, 'middleware.js') + const middlewareError = 'Middleware is returning a response body' - beforeEach(() => remove(join(appDir, '.next'))) + beforeEach(() => remove(join(appDir, '.next'))) - afterEach(() => - writeFile(middlewareFile, '// this will be populated by each test\n') - ) + afterEach(() => + writeFile(middlewareFile, '// this will be populated by each test\n') + ) - describe.each([ - { - title: 'returning a text body', - code: `export default function () { + describe.each([ + { + title: 'returning a text body', + code: `export default function () { return new Response('this is not allowed') }`, - }, - { - title: 'building body with JSON.stringify', - code: `export default function () { + }, + { + title: 'building body with JSON.stringify', + code: `export default function () { return new Response(JSON.stringify({ error: 'this is not allowed' })) }`, - }, - { - title: 'building response body with a variable', - code: `export default function () { + }, + { + title: 'building response body with a variable', + code: `export default function () { const body = 'this is not allowed, but hard to detect with AST' return new Response(body) }`, - }, - { - title: 'building response body with custom code', - code: `function buildResponse() { + }, + { + title: 'building response body with custom code', + code: `function buildResponse() { return JSON.stringify({ message: 'this is not allowed, but hard to detect with AST' }) } export default function () { return new Response(buildResponse()) }`, - }, - { - title: 'returning a text body with NextResponse', - code: `import { NextResponse } from 'next/server' + }, + { + title: 'returning a text body with NextResponse', + code: `import { NextResponse } from 'next/server' export default function () { return new NextResponse('this is not allowed') }`, - }, - ])('given a middleware $title', ({ code }) => { - beforeAll(() => writeFile(middlewareFile, code)) + }, + ])('given a middleware $title', ({ code }) => { + beforeAll(() => writeFile(middlewareFile, code)) - it('does not throw an error', async () => { - const { stderr, code } = await nextBuild(appDir, [], { - stderr: true, - stdout: true, + it('does not throw an error', async () => { + const { stderr, code } = await nextBuild(appDir, [], { + stderr: true, + stdout: true, + }) + expect(stderr).not.toMatch(middlewareError) + expect(code).toBe(0) }) - expect(stderr).not.toMatch(middlewareError) - expect(code).toBe(0) }) - }) - describe.each([ - { - title: 'returning a null body', - code: `export default function () { + describe.each([ + { + title: 'returning a null body', + code: `export default function () { return new Response(null) }`, - }, - { - title: 'returning an undefined body', - code: `export default function () { + }, + { + title: 'returning an undefined body', + code: `export default function () { return new Response(undefined) }`, - }, - ])('given a middleware $title', ({ code }) => { - beforeAll(() => writeFile(middlewareFile, code)) + }, + ])('given a middleware $title', ({ code }) => { + beforeAll(() => writeFile(middlewareFile, code)) - it('builds successfully', async () => { - const { stderr, code } = await nextBuild(appDir, [], { - stderr: true, - stdout: true, + it('builds successfully', async () => { + const { stderr, code } = await nextBuild(appDir, [], { + stderr: true, + stdout: true, + }) + expect(stderr).not.toMatch(middlewareError) + expect(code).toBe(0) }) - expect(stderr).not.toMatch(middlewareError) - expect(code).toBe(0) }) }) }) diff --git a/test/integration/middleware-prefetch/tests/index.test.js b/test/integration/middleware-prefetch/tests/index.test.js index a42a121d64db8..2eba154d29a38 100644 --- a/test/integration/middleware-prefetch/tests/index.test.js +++ b/test/integration/middleware-prefetch/tests/index.test.js @@ -14,62 +14,64 @@ const context = { } describe('Middleware Production Prefetch', () => { - afterAll(() => killApp(context.app)) - beforeAll(async () => { - const build = await nextBuild(context.appDir, undefined, { - stderr: true, - stdout: true, - }) + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + afterAll(() => killApp(context.app)) + beforeAll(async () => { + const build = await nextBuild(context.appDir, undefined, { + stderr: true, + stdout: true, + }) - context.buildId = await fs.readFile( - join(context.appDir, '.next/BUILD_ID'), - 'utf8' - ) + context.buildId = await fs.readFile( + join(context.appDir, '.next/BUILD_ID'), + 'utf8' + ) - context.buildLogs = { - output: build.stdout + build.stderr, - stderr: build.stderr, - stdout: build.stdout, - } - context.dev = false + context.buildLogs = { + output: build.stdout + build.stderr, + stderr: build.stderr, + stdout: build.stdout, + } + context.dev = false - context.appPort = await findPort() - context.app = await nextStart(context.appDir, context.appPort, { - env: { - MIDDLEWARE_TEST: 'asdf', - }, - onStdout(msg) { - context.logs.output += msg - context.logs.stdout += msg - }, - onStderr(msg) { - context.logs.output += msg - context.logs.stderr += msg - }, + context.appPort = await findPort() + context.app = await nextStart(context.appDir, context.appPort, { + env: { + MIDDLEWARE_TEST: 'asdf', + }, + onStdout(msg) { + context.logs.output += msg + context.logs.stdout += msg + }, + onStderr(msg) { + context.logs.output += msg + context.logs.stderr += msg + }, + }) }) - }) - it(`prefetch correctly for unexistent routes`, async () => { - const browser = await webdriver(context.appPort, `/`) - await browser.elementByCss('#made-up-link').moveTo() - await check(async () => { - const scripts = await browser.elementsByCss('script') - const attrs = await Promise.all( - scripts.map((script) => script.getAttribute('src')) - ) - return attrs.find((src) => src.includes('/ssg-page')) ? 'yes' : 'nope' - }, 'yes') - }) + it(`prefetch correctly for unexistent routes`, async () => { + const browser = await webdriver(context.appPort, `/`) + await browser.elementByCss('#made-up-link').moveTo() + await check(async () => { + const scripts = await browser.elementsByCss('script') + const attrs = await Promise.all( + scripts.map((script) => script.getAttribute('src')) + ) + return attrs.find((src) => src.includes('/ssg-page')) ? 'yes' : 'nope' + }, 'yes') + }) - it(`does not prefetch provided path if it will be rewritten`, async () => { - const browser = await webdriver(context.appPort, `/`) - await browser.elementByCss('#ssg-page-2').moveTo() - await check(async () => { - const scripts = await browser.elementsByCss('script') - const attrs = await Promise.all( - scripts.map((script) => script.getAttribute('src')) - ) - return attrs.find((src) => src.includes('/ssg-page-2')) ? 'nope' : 'yes' - }, 'yes') + it(`does not prefetch provided path if it will be rewritten`, async () => { + const browser = await webdriver(context.appPort, `/`) + await browser.elementByCss('#ssg-page-2').moveTo() + await check(async () => { + const scripts = await browser.elementsByCss('script') + const attrs = await Promise.all( + scripts.map((script) => script.getAttribute('src')) + ) + return attrs.find((src) => src.includes('/ssg-page-2')) ? 'nope' : 'yes' + }, 'yes') + }) }) }) diff --git a/test/integration/next-image-legacy/basic/test/index.test.ts b/test/integration/next-image-legacy/basic/test/index.test.ts index 9f308f327e8cf..0d4f04fd7242d 100644 --- a/test/integration/next-image-legacy/basic/test/index.test.ts +++ b/test/integration/next-image-legacy/basic/test/index.test.ts @@ -264,101 +264,104 @@ async function hasImagePreloadBeforeCSSPreload() { } describe('Image Component Tests', () => { - beforeAll(async () => { - await nextBuild(appDir) - appPort = await findPort() - app = await nextStart(appDir, appPort) - }) - afterAll(() => killApp(app)) - describe('SSR Image Component Tests', () => { - beforeAll(async () => { - browser = await webdriver(appPort, '/') - }) - afterAll(async () => { - browser = null - }) - runTests() - it('should add a preload tag for a priority image', async () => { - expect( - await hasPreloadLinkMatchingUrl( - 'https://example.com/myaccount/withpriority.png?auto=format&fit=max&w=1024&q=60' - ) - ).toBe(true) - }) - it('should add a preload tag for a priority image with preceding slash', async () => { - expect( - await hasPreloadLinkMatchingUrl( - 'https://example.com/myaccount/fooslash.jpg?auto=format&fit=max&w=1024' - ) - ).toBe(true) - }) - it('should add a preload tag for a priority image, with arbitrary host', async () => { - expect( - await hasPreloadLinkMatchingUrl( - 'https://arbitraryurl.com/withpriority3.png' - ) - ).toBe(true) - }) - it('should add a preload tag for a priority image, with quality', async () => { - expect( - await hasPreloadLinkMatchingUrl( - 'https://example.com/myaccount/withpriority.png?auto=format&fit=max&w=1024&q=60' - ) - ).toBe(true) - }) - it('should not create any preload tags higher up the page than CSS preload tags', async () => { - expect(await hasImagePreloadBeforeCSSPreload()).toBe(false) - }) - it('should add data-nimg data attribute based on layout', async () => { - expect( - await browser.elementById('image-with-sizes').getAttribute('data-nimg') - ).toBe('responsive') - expect( - await browser.elementById('basic-image').getAttribute('data-nimg') - ).toBe('intrinsic') - }) - it('should not pass config to custom loader prop', async () => { - browser = await webdriver(appPort, '/loader-prop') - expect( - await browser.elementById('loader-prop-img').getAttribute('src') - ).toBe('https://example.vercel.sh/success/foo.jpg?width=1024') - expect( - await browser.elementById('loader-prop-img').getAttribute('srcset') - ).toBe( - 'https://example.vercel.sh/success/foo.jpg?width=480 1x, https://example.vercel.sh/success/foo.jpg?width=1024 2x' - ) - }) - }) - describe('Client-side Image Component Tests', () => { + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { beforeAll(async () => { - browser = await webdriver(appPort, '/') - await browser.waitForElementByCss('#clientlink').click() - }) - afterAll(async () => { - browser = null + await nextBuild(appDir) + appPort = await findPort() + app = await nextStart(appDir, appPort) }) - runTests() - // FIXME: this test - it.skip('should NOT add a preload tag for a priority image', async () => { - expect( - await hasPreloadLinkMatchingUrl( - 'https://example.com/myaccount/withpriorityclient.png?auto=format&fit=max' + afterAll(() => killApp(app)) + describe('SSR Image Component Tests', () => { + beforeAll(async () => { + browser = await webdriver(appPort, '/') + }) + afterAll(async () => { + browser = null + }) + runTests() + it('should add a preload tag for a priority image', async () => { + expect( + await hasPreloadLinkMatchingUrl( + 'https://example.com/myaccount/withpriority.png?auto=format&fit=max&w=1024&q=60' + ) + ).toBe(true) + }) + it('should add a preload tag for a priority image with preceding slash', async () => { + expect( + await hasPreloadLinkMatchingUrl( + 'https://example.com/myaccount/fooslash.jpg?auto=format&fit=max&w=1024' + ) + ).toBe(true) + }) + it('should add a preload tag for a priority image, with arbitrary host', async () => { + expect( + await hasPreloadLinkMatchingUrl( + 'https://arbitraryurl.com/withpriority3.png' + ) + ).toBe(true) + }) + it('should add a preload tag for a priority image, with quality', async () => { + expect( + await hasPreloadLinkMatchingUrl( + 'https://example.com/myaccount/withpriority.png?auto=format&fit=max&w=1024&q=60' + ) + ).toBe(true) + }) + it('should not create any preload tags higher up the page than CSS preload tags', async () => { + expect(await hasImagePreloadBeforeCSSPreload()).toBe(false) + }) + it('should add data-nimg data attribute based on layout', async () => { + expect( + await browser + .elementById('image-with-sizes') + .getAttribute('data-nimg') + ).toBe('responsive') + expect( + await browser.elementById('basic-image').getAttribute('data-nimg') + ).toBe('intrinsic') + }) + it('should not pass config to custom loader prop', async () => { + browser = await webdriver(appPort, '/loader-prop') + expect( + await browser.elementById('loader-prop-img').getAttribute('src') + ).toBe('https://example.vercel.sh/success/foo.jpg?width=1024') + expect( + await browser.elementById('loader-prop-img').getAttribute('srcset') + ).toBe( + 'https://example.vercel.sh/success/foo.jpg?width=480 1x, https://example.vercel.sh/success/foo.jpg?width=1024 2x' ) - ).toBe(false) + }) }) - it('should only be loaded once if `sizes` is set', async () => { - const numRequests = await browser.eval(`(function() { + describe('Client-side Image Component Tests', () => { + beforeAll(async () => { + browser = await webdriver(appPort, '/') + await browser.waitForElementByCss('#clientlink').click() + }) + afterAll(async () => { + browser = null + }) + runTests() + // FIXME: this test + it.skip('should NOT add a preload tag for a priority image', async () => { + expect( + await hasPreloadLinkMatchingUrl( + 'https://example.com/myaccount/withpriorityclient.png?auto=format&fit=max' + ) + ).toBe(false) + }) + it('should only be loaded once if `sizes` is set', async () => { + const numRequests = await browser.eval(`(function() { const entries = window.performance.getEntries() return entries.filter(function(entry) { return entry.name.includes('test-sizes.jpg') }).length })()`) - expect(numRequests).toBe(1) - }) - describe('Client-side Errors', () => { - beforeAll(async () => { - await browser.eval(`(function() { + expect(numRequests).toBe(1) + }) + describe('Client-side Errors', () => { + beforeAll(async () => { + await browser.eval(`(function() { window.gotHostError = false const origError = console.error window.console.error = function () { @@ -368,32 +371,33 @@ describe('Image Component Tests', () => { origError.apply(this, arguments) } })()`) - await browser.waitForElementByCss('#errorslink').click() - }) - it('Should not log an error when an unregistered host is used in production', async () => { - const foundError = await browser.eval('window.gotHostError') - expect(foundError).toBe(false) + await browser.waitForElementByCss('#errorslink').click() + }) + it('Should not log an error when an unregistered host is used in production', async () => { + const foundError = await browser.eval('window.gotHostError') + expect(foundError).toBe(false) + }) }) }) - }) - describe('SSR Lazy Loading Tests', () => { - beforeAll(async () => { - browser = await webdriver(appPort, '/lazy') - }) - afterAll(async () => { - browser = null - }) - lazyLoadingTests() - }) - describe('Client-side Lazy Loading Tests', () => { - beforeAll(async () => { - browser = await webdriver(appPort, '/') - await browser.waitForElementByCss('#lazylink').click() - await waitFor(500) + describe('SSR Lazy Loading Tests', () => { + beforeAll(async () => { + browser = await webdriver(appPort, '/lazy') + }) + afterAll(async () => { + browser = null + }) + lazyLoadingTests() }) - afterAll(async () => { - browser = null + describe('Client-side Lazy Loading Tests', () => { + beforeAll(async () => { + browser = await webdriver(appPort, '/') + await browser.waitForElementByCss('#lazylink').click() + await waitFor(500) + }) + afterAll(async () => { + browser = null + }) + lazyLoadingTests() }) - lazyLoadingTests() }) }) diff --git a/test/integration/next-image-legacy/custom-resolver/test/index.test.ts b/test/integration/next-image-legacy/custom-resolver/test/index.test.ts index c338ed6adeb36..568b50d54e4c2 100644 --- a/test/integration/next-image-legacy/custom-resolver/test/index.test.ts +++ b/test/integration/next-image-legacy/custom-resolver/test/index.test.ts @@ -30,32 +30,34 @@ function runTests() { } describe('Custom Resolver Tests', () => { - beforeAll(async () => { - await nextBuild(appDir) - appPort = await findPort() - app = await nextStart(appDir, appPort) - }) - afterAll(() => killApp(app)) - describe('SSR Custom Loader Tests', () => { + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { beforeAll(async () => { - browser = await webdriver(appPort, '/') - }) - afterAll(async () => { - browser = null + await nextBuild(appDir) + appPort = await findPort() + app = await nextStart(appDir, appPort) }) - runTests() - }) - describe('Client-side Custom Loader Tests', () => { - beforeAll(async () => { - browser = await webdriver(appPort, '/') - await browser - .elementByCss('#clientlink') - .click() - .waitForElementByCss('#client-side') + afterAll(() => killApp(app)) + describe('SSR Custom Loader Tests', () => { + beforeAll(async () => { + browser = await webdriver(appPort, '/') + }) + afterAll(async () => { + browser = null + }) + runTests() }) - afterAll(async () => { - browser = null + describe('Client-side Custom Loader Tests', () => { + beforeAll(async () => { + browser = await webdriver(appPort, '/') + await browser + .elementByCss('#clientlink') + .click() + .waitForElementByCss('#client-side') + }) + afterAll(async () => { + browser = null + }) + runTests() }) - runTests() }) }) diff --git a/test/integration/next-image-legacy/image-from-node-modules/test/index.test.ts b/test/integration/next-image-legacy/image-from-node-modules/test/index.test.ts index ab6a0fa75fe0f..f675602631c65 100644 --- a/test/integration/next-image-legacy/image-from-node-modules/test/index.test.ts +++ b/test/integration/next-image-legacy/image-from-node-modules/test/index.test.ts @@ -25,16 +25,18 @@ function runTests() { } describe('Image Component Tests In Prod Mode', () => { - beforeAll(async () => { - await nextBuild(appDir) - appPort = await findPort() - app = await nextStart(appDir, appPort) - }) - afterAll(async () => { - await killApp(app) - }) + ;(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() + runTests() + }) }) describe('Image Component Tests In Dev Mode', () => { diff --git a/test/integration/next-image-legacy/no-intersection-observer-fallback/test/index.test.ts b/test/integration/next-image-legacy/no-intersection-observer-fallback/test/index.test.ts index be89b8e476821..c0797539870f0 100644 --- a/test/integration/next-image-legacy/no-intersection-observer-fallback/test/index.test.ts +++ b/test/integration/next-image-legacy/no-intersection-observer-fallback/test/index.test.ts @@ -15,57 +15,59 @@ let app let browser describe('Image Component No IntersectionObserver test', () => { - beforeAll(async () => { - await nextBuild(appDir) - appPort = await findPort() - app = await nextStart(appDir, appPort) - }) - afterAll(() => killApp(app)) + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + beforeAll(async () => { + await nextBuild(appDir) + appPort = await findPort() + app = await nextStart(appDir, appPort) + }) + afterAll(() => killApp(app)) - describe('SSR Lazy Loading Tests', () => { - it('should automatically load images if observer does not exist', async () => { - browser = await webdriver(appPort, '/no-observer') + describe('SSR Lazy Loading Tests', () => { + it('should automatically load images if observer does not exist', async () => { + browser = await webdriver(appPort, '/no-observer') - // Make sure the IntersectionObserver is mocked to null during the test - await check(() => { - return browser.eval('IntersectionObserver') - }, /null/) + // Make sure the IntersectionObserver is mocked to null during the test + await check(() => { + return browser.eval('IntersectionObserver') + }, /null/) - expect( - await browser.elementById('lazy-no-observer').getAttribute('src') - ).toBe( - 'https://example.com/myaccount/foox.jpg?auto=format&fit=max&w=2000' - ) - expect( - await browser.elementById('lazy-no-observer').getAttribute('srcset') - ).toBe( - 'https://example.com/myaccount/foox.jpg?auto=format&fit=max&w=1024 1x, https://example.com/myaccount/foox.jpg?auto=format&fit=max&w=2000 2x' - ) + expect( + await browser.elementById('lazy-no-observer').getAttribute('src') + ).toBe( + 'https://example.com/myaccount/foox.jpg?auto=format&fit=max&w=2000' + ) + expect( + await browser.elementById('lazy-no-observer').getAttribute('srcset') + ).toBe( + 'https://example.com/myaccount/foox.jpg?auto=format&fit=max&w=1024 1x, https://example.com/myaccount/foox.jpg?auto=format&fit=max&w=2000 2x' + ) + }) }) - }) - describe('Client-side Lazy Loading Tests', () => { - it('should automatically load images if observer does not exist', async () => { - browser = await webdriver(appPort, '/') + describe('Client-side Lazy Loading Tests', () => { + it('should automatically load images if observer does not exist', async () => { + browser = await webdriver(appPort, '/') - // Make sure the IntersectionObserver is mocked to null during the test - await check(() => { - return browser.eval('IntersectionObserver') - }, /null/) + // Make sure the IntersectionObserver is mocked to null during the test + await check(() => { + return browser.eval('IntersectionObserver') + }, /null/) - await browser.waitForElementByCss('#link-no-observer').click() + await browser.waitForElementByCss('#link-no-observer').click() - await waitFor(1000) - expect( - await browser.elementById('lazy-no-observer').getAttribute('src') - ).toBe( - 'https://example.com/myaccount/foox.jpg?auto=format&fit=max&w=2000' - ) - expect( - await browser.elementById('lazy-no-observer').getAttribute('srcset') - ).toBe( - 'https://example.com/myaccount/foox.jpg?auto=format&fit=max&w=1024 1x, https://example.com/myaccount/foox.jpg?auto=format&fit=max&w=2000 2x' - ) + await waitFor(1000) + expect( + await browser.elementById('lazy-no-observer').getAttribute('src') + ).toBe( + 'https://example.com/myaccount/foox.jpg?auto=format&fit=max&w=2000' + ) + expect( + await browser.elementById('lazy-no-observer').getAttribute('srcset') + ).toBe( + 'https://example.com/myaccount/foox.jpg?auto=format&fit=max&w=1024 1x, https://example.com/myaccount/foox.jpg?auto=format&fit=max&w=2000 2x' + ) + }) }) }) }) diff --git a/test/integration/next-image-legacy/noscript/test/index.test.ts b/test/integration/next-image-legacy/noscript/test/index.test.ts index 2974fe6add1ee..df14ba64aad9c 100644 --- a/test/integration/next-image-legacy/noscript/test/index.test.ts +++ b/test/integration/next-image-legacy/noscript/test/index.test.ts @@ -15,28 +15,30 @@ let appPort let app describe('Noscript Tests', () => { - beforeAll(async () => { - await nextBuild(appDir) - appPort = await findPort() - app = await nextStart(appDir, appPort) - }) - afterAll(() => killApp(app)) - describe('Noscript page source tests', () => { - it('should use local API for noscript img#basic-image src attribute', async () => { - const html = await renderViaHTTP(appPort, '/') - const $ = cheerio.load(html) - - expect($('noscript > img#basic-image').attr('src')).toMatch( - /^\/_next\/image/ - ) + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + beforeAll(async () => { + await nextBuild(appDir) + appPort = await findPort() + app = await nextStart(appDir, appPort) }) - it('should use loader url for noscript img#image-with-loader src attribute', async () => { - const html = await renderViaHTTP(appPort, '/') - const $ = cheerio.load(html) + afterAll(() => killApp(app)) + describe('Noscript page source tests', () => { + it('should use local API for noscript img#basic-image src attribute', async () => { + const html = await renderViaHTTP(appPort, '/') + const $ = cheerio.load(html) + + expect($('noscript > img#basic-image').attr('src')).toMatch( + /^\/_next\/image/ + ) + }) + it('should use loader url for noscript img#image-with-loader src attribute', async () => { + const html = await renderViaHTTP(appPort, '/') + const $ = cheerio.load(html) - expect($('noscript > img#image-with-loader').attr('src')).toMatch( - /^https:\/\/customresolver.com/ - ) + expect($('noscript > img#image-with-loader').attr('src')).toMatch( + /^https:\/\/customresolver.com/ + ) + }) }) }) }) diff --git a/test/integration/next-image-legacy/svgo-webpack/test/index.test.ts b/test/integration/next-image-legacy/svgo-webpack/test/index.test.ts index 00e29fe50013e..a60e49c23319c 100644 --- a/test/integration/next-image-legacy/svgo-webpack/test/index.test.ts +++ b/test/integration/next-image-legacy/svgo-webpack/test/index.test.ts @@ -15,7 +15,7 @@ let app let devOutput describe('svgo-webpack with Image Component', () => { - describe('next build', () => { + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { it('should not fail to build invalid usage of the Image component', async () => { const { stderr, code } = await nextBuild(appDir, [], { stderr: true }) expect(stderr).toBeFalsy() @@ -23,7 +23,7 @@ describe('svgo-webpack with Image Component', () => { }) }) - describe('next dev', () => { + describe('development mode', () => { beforeAll(async () => { devOutput = { stdout: '', stderr: '' } appPort = await findPort() diff --git a/test/integration/next-image-legacy/typescript/test/index.test.ts b/test/integration/next-image-legacy/typescript/test/index.test.ts index d7012891a9fe7..2da9698e3bcc0 100644 --- a/test/integration/next-image-legacy/typescript/test/index.test.ts +++ b/test/integration/next-image-legacy/typescript/test/index.test.ts @@ -21,7 +21,7 @@ const handleOutput = (msg) => { } describe('TypeScript Image Component', () => { - describe('next build', () => { + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { it('should fail to build invalid usage of the Image component', async () => { const { stderr, code } = await nextBuild(appDir, [], { stderr: true }) expect(stderr).toMatch(/Failed to compile/) @@ -47,7 +47,7 @@ describe('TypeScript Image Component', () => { }) }) - describe('next dev', () => { + describe('development mode', () => { beforeAll(async () => { output = '' appPort = await findPort() @@ -75,16 +75,18 @@ describe('TypeScript Image Component', () => { }) }) - it('should remove global image types when disabled (dev)', async () => { - const content = await fs.readFile(nextConfig, 'utf8') - await fs.writeFile( - nextConfig, - content.replace('// disableStaticImages', 'disableStaticImages') - ) - const app = await launchApp(appDir, await findPort()) - await killApp(app) - await fs.writeFile(nextConfig, content) - const envTypes = await fs.readFile(join(appDir, 'next-env.d.ts'), 'utf8') - expect(envTypes).not.toContain('image-types/global') + describe('development mode 2', () => { + it('should remove global image types when disabled (dev)', async () => { + const content = await fs.readFile(nextConfig, 'utf8') + await fs.writeFile( + nextConfig, + content.replace('// disableStaticImages', 'disableStaticImages') + ) + const app = await launchApp(appDir, await findPort()) + await killApp(app) + await fs.writeFile(nextConfig, content) + const envTypes = await fs.readFile(join(appDir, 'next-env.d.ts'), 'utf8') + expect(envTypes).not.toContain('image-types/global') + }) }) }) diff --git a/test/integration/next-image-new/svgo-webpack/test/index.test.ts b/test/integration/next-image-new/svgo-webpack/test/index.test.ts index 0165a093fcbd9..825782d59febf 100644 --- a/test/integration/next-image-new/svgo-webpack/test/index.test.ts +++ b/test/integration/next-image-new/svgo-webpack/test/index.test.ts @@ -15,7 +15,7 @@ let app let devOutput describe('svgo-webpack with Image Component', () => { - describe('next build', () => { + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { it('should not fail to build invalid usage of the Image component', async () => { const { stderr, code } = await nextBuild(appDir, [], { stderr: true }) const errors = stderr @@ -26,7 +26,7 @@ describe('svgo-webpack with Image Component', () => { }) }) - describe('next dev', () => { + describe('development mode', () => { beforeAll(async () => { devOutput = { stdout: '', stderr: '' } appPort = await findPort() diff --git a/test/integration/next-image-new/typescript/test/index.test.ts b/test/integration/next-image-new/typescript/test/index.test.ts index d7012891a9fe7..6a83f4865a0d8 100644 --- a/test/integration/next-image-new/typescript/test/index.test.ts +++ b/test/integration/next-image-new/typescript/test/index.test.ts @@ -21,7 +21,7 @@ const handleOutput = (msg) => { } describe('TypeScript Image Component', () => { - describe('next build', () => { + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { it('should fail to build invalid usage of the Image component', async () => { const { stderr, code } = await nextBuild(appDir, [], { stderr: true }) expect(stderr).toMatch(/Failed to compile/) @@ -47,7 +47,7 @@ describe('TypeScript Image Component', () => { }) }) - describe('next dev', () => { + describe('development mode', () => { beforeAll(async () => { output = '' appPort = await findPort() diff --git a/test/integration/non-next-dist-exclude/test/index.test.js b/test/integration/non-next-dist-exclude/test/index.test.js index 90ddb994c58e5..236b12559f1d7 100644 --- a/test/integration/non-next-dist-exclude/test/index.test.js +++ b/test/integration/non-next-dist-exclude/test/index.test.js @@ -5,12 +5,14 @@ import { nextBuild, readNextBuildServerPageFile } from 'next-test-utils' const appDir = path.join(__dirname, '../app') describe('Non-Next externalization', () => { - beforeAll(async () => { - await nextBuild(appDir) - }) + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + beforeAll(async () => { + await nextBuild(appDir) + }) - it('Externalized non-Next dist-using package', async () => { - const content = readNextBuildServerPageFile(appDir, '/') - expect(content).not.toContain('BrokenExternalMarker') + it('Externalized non-Next dist-using package', async () => { + const content = readNextBuildServerPageFile(appDir, '/') + expect(content).not.toContain('BrokenExternalMarker') + }) }) }) diff --git a/test/integration/non-standard-node-env-warning/test/index.test.js b/test/integration/non-standard-node-env-warning/test/index.test.js index 253beba62deb5..ffac1ee45bc9e 100644 --- a/test/integration/non-standard-node-env-warning/test/index.test.js +++ b/test/integration/non-standard-node-env-warning/test/index.test.js @@ -79,28 +79,56 @@ describe('Non-Standard NODE_ENV', () => { await killApp(app) expect(output).not.toContain(warningText) }) + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + it('should still DCE NODE_ENV specific code', async () => { + await nextBuild(appDir, undefined, { + env: { + NODE_ENV: 'test', + }, + }) + + const staticFiles = glob.sync('**/*.js', { + cwd: join(appDir, '.next/static'), + }) + expect(staticFiles.length).toBeGreaterThan(0) + + for (const file of staticFiles) { + const content = await fs.readFile( + join(appDir, '.next/static', file), + 'utf8' + ) + if (content.match(/cannot find module(?! for page)/i)) { + throw new Error(`${file} contains module not found error`) + } + } + }) - it('should still DCE NODE_ENV specific code', async () => { - await nextBuild(appDir, undefined, { - env: { - NODE_ENV: 'test', - }, + it('should show the warning with NODE_ENV set to development with next build', async () => { + const { stderr } = await nextBuild(appDir, [], { + env: { + NODE_ENV: 'development', + }, + stderr: true, + }) + expect(stderr).toContain(warningText) }) - const staticFiles = glob.sync('**/*.js', { - cwd: join(appDir, '.next/static'), + it('should show the warning with NODE_ENV set to development with next start', async () => { + let output = '' + + await nextBuild(appDir) + app = await nextStart(appDir, await findPort(), { + env: { + NODE_ENV: 'development', + }, + onStderr(msg) { + output += msg || '' + }, + }) + await waitFor(2000) + await killApp(app) + expect(output).toContain(warningText) }) - expect(staticFiles.length).toBeGreaterThan(0) - - for (const file of staticFiles) { - const content = await fs.readFile( - join(appDir, '.next/static', file), - 'utf8' - ) - if (content.match(/cannot find module(?! for page)/i)) { - throw new Error(`${file} contains module not found error`) - } - } }) it('should show the warning with NODE_ENV set to invalid value', async () => { @@ -152,31 +180,4 @@ describe('Non-Standard NODE_ENV', () => { await killApp(app) expect(output).toContain(warningText) }) - - it('should show the warning with NODE_ENV set to development with next build', async () => { - const { stderr } = await nextBuild(appDir, [], { - env: { - NODE_ENV: 'development', - }, - stderr: true, - }) - expect(stderr).toContain(warningText) - }) - - it('should show the warning with NODE_ENV set to development with next start', async () => { - let output = '' - - await nextBuild(appDir) - app = await nextStart(appDir, await findPort(), { - env: { - NODE_ENV: 'development', - }, - onStderr(msg) { - output += msg || '' - }, - }) - await waitFor(2000) - await killApp(app) - expect(output).toContain(warningText) - }) }) diff --git a/test/integration/numeric-sep/test/index.test.js b/test/integration/numeric-sep/test/index.test.js index cc65ce35ff7e7..d9a0be66b9849 100644 --- a/test/integration/numeric-sep/test/index.test.js +++ b/test/integration/numeric-sep/test/index.test.js @@ -6,15 +6,17 @@ import { join } from 'path' const appDir = join(__dirname, '../') describe('Numeric Separator Support', () => { - it('should successfully build for a JavaScript file', async () => { - const { code, stdout, stderr } = await nextBuild(appDir, [], { - stdout: true, - stderr: true, - }) + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + it('should successfully build for a JavaScript file', async () => { + const { code, stdout, stderr } = await nextBuild(appDir, [], { + stdout: true, + stderr: true, + }) - expect(code).toBe(0) + expect(code).toBe(0) - expect(stdout).toContain('Compiled successfully') - expect(stderr).not.toContain('Failed to compile') + expect(stdout).toContain('Compiled successfully') + expect(stderr).not.toContain('Failed to compile') + }) }) }) diff --git a/test/integration/page-config/test/index.test.js b/test/integration/page-config/test/index.test.js index bdb276818bc7a..b4460e9de025e 100644 --- a/test/integration/page-config/test/index.test.js +++ b/test/integration/page-config/test/index.test.js @@ -17,85 +17,87 @@ async function uncommentExport(page) { } describe('Page Config', () => { - it('builds without error when export const config is used outside page', async () => { - const { stderr } = await nextBuild(appDir, undefined, { stderr: true }) - expect(stderr).not.toMatch(/Failed to compile\./) - }) - - it('shows valid error when page config is a string', async () => { - const reset = await uncommentExport('invalid/string-config.js') - - try { - const { stderr } = await nextBuild(appDir, undefined, { stderr: true }) - expect(stderr).toMatch(/\/invalid-page-config/) - } finally { - await reset() - } - }) - - it('shows valid error when page config has no init', async () => { - const reset = await uncommentExport('invalid/no-init.js') - - try { - const { stderr } = await nextBuild(appDir, undefined, { stderr: true }) - expect(stderr).toMatch(/\/invalid-page-config/) - } finally { - await reset() - } - }) - - it('shows error when page config has spread properties', async () => { - const reset = await uncommentExport('invalid/spread-config.js') - - try { - const { stderr } = await nextBuild(appDir, undefined, { stderr: true }) - expect(stderr).toMatch(/\/invalid-page-config/) - } finally { - await reset() - } - }) - - it('shows error when page config has invalid properties', async () => { - const reset = await uncommentExport('invalid/invalid-property.js') - - try { - const { stderr } = await nextBuild(appDir, undefined, { stderr: true }) - expect(stderr).toMatch(/\/invalid-page-config/) - } finally { - await reset() - } - }) - - it('shows error when page config has invalid property value', async () => { - const reset = await uncommentExport('invalid/invalid-value.js') - - try { - const { stderr } = await nextBuild(appDir, undefined, { stderr: true }) - expect(stderr).toMatch(/\/invalid-page-config/) - } finally { - await reset() - } - }) - - it('shows error when page config is export from', async () => { - const reset = await uncommentExport('invalid/export-from.js') - - try { - const { stderr } = await nextBuild(appDir, undefined, { stderr: true }) - expect(stderr).toMatch(/\/invalid-page-config/) - } finally { - await reset() - } - }) - - it('shows error when page config is imported and exported', async () => { - const reset = await uncommentExport('invalid/import-export.js') - - try { + ;(process.env.TURBOPACK ? describe.skip : describe)('production mode', () => { + it('builds without error when export const config is used outside page', async () => { const { stderr } = await nextBuild(appDir, undefined, { stderr: true }) - expect(stderr).toMatch(/\/invalid-page-config/) - } finally { - await reset() - } + expect(stderr).not.toMatch(/Failed to compile\./) + }) + + it('shows valid error when page config is a string', async () => { + const reset = await uncommentExport('invalid/string-config.js') + + try { + const { stderr } = await nextBuild(appDir, undefined, { stderr: true }) + expect(stderr).toMatch(/\/invalid-page-config/) + } finally { + await reset() + } + }) + + it('shows valid error when page config has no init', async () => { + const reset = await uncommentExport('invalid/no-init.js') + + try { + const { stderr } = await nextBuild(appDir, undefined, { stderr: true }) + expect(stderr).toMatch(/\/invalid-page-config/) + } finally { + await reset() + } + }) + + it('shows error when page config has spread properties', async () => { + const reset = await uncommentExport('invalid/spread-config.js') + + try { + const { stderr } = await nextBuild(appDir, undefined, { stderr: true }) + expect(stderr).toMatch(/\/invalid-page-config/) + } finally { + await reset() + } + }) + + it('shows error when page config has invalid properties', async () => { + const reset = await uncommentExport('invalid/invalid-property.js') + + try { + const { stderr } = await nextBuild(appDir, undefined, { stderr: true }) + expect(stderr).toMatch(/\/invalid-page-config/) + } finally { + await reset() + } + }) + + it('shows error when page config has invalid property value', async () => { + const reset = await uncommentExport('invalid/invalid-value.js') + + try { + const { stderr } = await nextBuild(appDir, undefined, { stderr: true }) + expect(stderr).toMatch(/\/invalid-page-config/) + } finally { + await reset() + } + }) + + it('shows error when page config is export from', async () => { + const reset = await uncommentExport('invalid/export-from.js') + + try { + const { stderr } = await nextBuild(appDir, undefined, { stderr: true }) + expect(stderr).toMatch(/\/invalid-page-config/) + } finally { + await reset() + } + }) + + it('shows error when page config is imported and exported', async () => { + const reset = await uncommentExport('invalid/import-export.js') + + try { + const { stderr } = await nextBuild(appDir, undefined, { stderr: true }) + expect(stderr).toMatch(/\/invalid-page-config/) + } finally { + await reset() + } + }) }) }) diff --git a/test/integration/plugin-mdx-rs/test/index.test.js b/test/integration/plugin-mdx-rs/test/index.test.js index e835069984eac..7bce086847b7e 100644 --- a/test/integration/plugin-mdx-rs/test/index.test.js +++ b/test/integration/plugin-mdx-rs/test/index.test.js @@ -5,7 +5,7 @@ import { renderViaHTTP, findPort, launchApp, killApp } from 'next-test-utils' const context = {} -describe('Configuration', () => { +describe('MDX-rs Configuration', () => { beforeAll(async () => { context.appPort = await findPort() context.server = await launchApp(join(__dirname, '../'), context.appPort) diff --git a/test/integration/preload-viewport/test/index.test.js b/test/integration/preload-viewport/test/index.test.js index 36f5e0ab875e7..22c4a85c65fb5 100644 --- a/test/integration/preload-viewport/test/index.test.js +++ b/test/integration/preload-viewport/test/index.test.js @@ -22,265 +22,231 @@ let proxyServer let nextDataRequests = [] describe('Prefetching Links in viewport', () => { - beforeAll(async () => { - 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 ? describe.skip : describe)('production mode', () => { + beforeAll(async () => { + 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 (stallJs && req.url.includes('chunks/pages/another')) { - console.log('stalling request for', req.url) - await new Promise((resolve) => setTimeout(resolve, 5 * 1000)) - } - if (req.url.startsWith('/_next/data')) { - nextDataRequests.push(req.url) - } - proxy.web(req, res) - }) + proxyServer = http.createServer(async (req, res) => { + if (stallJs && req.url.includes('chunks/pages/another')) { + console.log('stalling request for', req.url) + await new Promise((resolve) => setTimeout(resolve, 5 * 1000)) + } + if (req.url.startsWith('/_next/data')) { + nextDataRequests.push(req.url) + } + proxy.web(req, res) + }) - proxy.on('error', (err) => { - console.warn('Failed to proxy', err) + proxy.on('error', (err) => { + console.warn('Failed to proxy', err) + }) + + await new Promise((resolve) => { + proxyServer.listen(appPort, () => resolve()) + }) + }) + afterAll(async () => { + await killApp(app) + proxyServer.close() }) - await new Promise((resolve) => { - proxyServer.listen(appPort, () => resolve()) + it('should de-dupe inflight SSG requests', async () => { + nextDataRequests = [] + const browser = await webdriver(appPort, '/') + await browser.eval(function navigate() { + window.next.router.push('/ssg/slow') + window.next.router.push('/ssg/slow') + window.next.router.push('/ssg/slow') + }) + await browser.waitForElementByCss('#content') + expect( + nextDataRequests.filter((reqUrl) => reqUrl.includes('/ssg/slow.json')) + .length + ).toBe(2) }) - }) - afterAll(async () => { - await killApp(app) - proxyServer.close() - }) - it('should de-dupe inflight SSG requests', async () => { - nextDataRequests = [] - const browser = await webdriver(appPort, '/') - await browser.eval(function navigate() { - window.next.router.push('/ssg/slow') - window.next.router.push('/ssg/slow') - window.next.router.push('/ssg/slow') + it('should handle timed out prefetch correctly', async () => { + try { + stallJs = true + const browser = await webdriver(appPort, '/') + + await browser.elementByCss('#scroll-to-another').click() + // wait for preload to timeout + await waitFor(6 * 1000) + + await browser + .elementByCss('#link-another') + .click() + .waitForElementByCss('#another') + + expect(await browser.elementByCss('#another').text()).toBe( + 'Hello world' + ) + } finally { + stallJs = false + } }) - await browser.waitForElementByCss('#content') - expect( - nextDataRequests.filter((reqUrl) => reqUrl.includes('/ssg/slow.json')) - .length - ).toBe(2) - }) - it('should handle timed out prefetch correctly', async () => { - try { - stallJs = true - const browser = await webdriver(appPort, '/') + it('should prefetch with link in viewport onload', async () => { + let browser + try { + browser = await webdriver(appPort, '/') + + await check(async () => { + const links = await browser.elementsByCss('link[rel=prefetch]') + let found = false + + for (const link of links) { + const href = await link.getAttribute('href') + if (href.includes('first')) { + found = true + break + } + } + expect(found).toBe(true) + return 'success' + }, 'success') + } finally { + if (browser) await browser.close() + } + }) - await browser.elementByCss('#scroll-to-another').click() - // wait for preload to timeout - await waitFor(6 * 1000) + it('should prefetch with non-bot UA', async () => { + let browser + try { + browser = await webdriver( + appPort, + `/bot-user-agent?useragent=${encodeURIComponent( + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36' + )}` + ) + const links = await browser.elementsByCss('link[rel=prefetch]') + expect(links).toHaveLength(1) + } finally { + if (browser) await browser.close() + } + }) - await browser - .elementByCss('#link-another') - .click() - .waitForElementByCss('#another') + it('should not prefetch with bot UA', async () => { + let browser + try { + browser = await webdriver( + appPort, + `/bot-user-agent?useragent=${encodeURIComponent( + 'Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/W.X.Y.Z Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)' + )}` + ) + const links = await browser.elementsByCss('link[rel=prefetch]') + expect(links).toHaveLength(0) + } finally { + if (browser) await browser.close() + } + }) - expect(await browser.elementByCss('#another').text()).toBe('Hello world') - } finally { - stallJs = false - } - }) + it('should prefetch rewritten href with link in viewport onload', async () => { + let browser + try { + browser = await webdriver(appPort, '/rewrite-prefetch') + + await check(async () => { + const links = await browser.elementsByCss('link[rel=prefetch]') + let found = false + + for (const link of links) { + const href = await link.getAttribute('href') + if (href.includes('%5Bslug%5D')) { + found = true + break + } + } + expect(found).toBe(true) + return 'success' + }, 'success') + + const hrefs = await browser.eval(`Object.keys(window.next.router.sdc)`) + expect(hrefs.map((href) => new URL(href).pathname)).toEqual([ + '/_next/data/test-build/ssg/dynamic/one.json', + ]) + } finally { + if (browser) await browser.close() + } + }) - it('should prefetch with link in viewport onload', async () => { - let browser - try { - browser = await webdriver(appPort, '/') + it('should prefetch with link in viewport when href changes', async () => { + let browser + try { + browser = await webdriver(appPort, '/') + await browser.elementByCss('button').click() + await waitFor(2 * 1000) - await check(async () => { const links = await browser.elementsByCss('link[rel=prefetch]') - let found = false + let foundFirst = false + let foundAnother = false for (const link of links) { const href = await link.getAttribute('href') - if (href.includes('first')) { - found = true - break - } + if (href.includes('another')) foundAnother = true + if (href.includes('first')) foundFirst = true } - expect(found).toBe(true) - return 'success' - }, 'success') - } finally { - if (browser) await browser.close() - } - }) - - it('should prefetch with non-bot UA', async () => { - let browser - try { - browser = await webdriver( - appPort, - `/bot-user-agent?useragent=${encodeURIComponent( - 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36' - )}` - ) - const links = await browser.elementsByCss('link[rel=prefetch]') - expect(links).toHaveLength(1) - } finally { - if (browser) await browser.close() - } - }) - - it('should not prefetch with bot UA', async () => { - let browser - try { - browser = await webdriver( - appPort, - `/bot-user-agent?useragent=${encodeURIComponent( - 'Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/W.X.Y.Z Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)' - )}` - ) - const links = await browser.elementsByCss('link[rel=prefetch]') - expect(links).toHaveLength(0) - } finally { - if (browser) await browser.close() - } - }) + expect(foundFirst).toBe(true) + expect(foundAnother).toBe(true) + } finally { + if (browser) await browser.close() + } + }) - it('should prefetch rewritten href with link in viewport onload', async () => { - let browser - try { - browser = await webdriver(appPort, '/rewrite-prefetch') + it('should prefetch with link in viewport on scroll', async () => { + let browser + try { + browser = await webdriver(appPort, '/') + await browser.elementByCss('#scroll-to-another').click() + await waitFor(2 * 1000) - await check(async () => { const links = await browser.elementsByCss('link[rel=prefetch]') let found = false for (const link of links) { const href = await link.getAttribute('href') - if (href.includes('%5Bslug%5D')) { + if (href.includes('another')) { found = true break } } expect(found).toBe(true) - return 'success' - }, 'success') - - const hrefs = await browser.eval(`Object.keys(window.next.router.sdc)`) - expect(hrefs.map((href) => new URL(href).pathname)).toEqual([ - '/_next/data/test-build/ssg/dynamic/one.json', - ]) - } finally { - if (browser) await browser.close() - } - }) - - it('should prefetch with link in viewport when href changes', async () => { - let browser - try { - browser = await webdriver(appPort, '/') - await browser.elementByCss('button').click() - await waitFor(2 * 1000) - - const links = await browser.elementsByCss('link[rel=prefetch]') - let foundFirst = false - let foundAnother = false - - for (const link of links) { - const href = await link.getAttribute('href') - if (href.includes('another')) foundAnother = true - if (href.includes('first')) foundFirst = true - } - expect(foundFirst).toBe(true) - expect(foundAnother).toBe(true) - } finally { - if (browser) await browser.close() - } - }) - - it('should prefetch with link in viewport on scroll', async () => { - let browser - try { - browser = await webdriver(appPort, '/') - await browser.elementByCss('#scroll-to-another').click() - await waitFor(2 * 1000) - - const links = await browser.elementsByCss('link[rel=prefetch]') - let found = false - - for (const link of links) { - const href = await link.getAttribute('href') - if (href.includes('another')) { - found = true - break - } + } finally { + if (browser) await browser.close() } - expect(found).toBe(true) - } finally { - if (browser) await browser.close() - } - }) - - it('should prefetch with link in viewport and inject script on hover', async () => { - let browser - try { - browser = await webdriver(appPort, '/') - await browser.elementByCss('#scroll-to-another').click() - await waitFor(2 * 1000) + }) - const links = await browser.elementsByCss('link[rel=prefetch]') - let foundLink = false + it('should prefetch with link in viewport and inject script on hover', async () => { + let browser + try { + browser = await webdriver(appPort, '/') + await browser.elementByCss('#scroll-to-another').click() + await waitFor(2 * 1000) - for (const link of links) { - const href = await link.getAttribute('href') - if (href.includes('another')) { - foundLink = true - break - } - } - expect(foundLink).toBe(true) - - await browser.elementByCss('#link-another').moveTo() - await waitFor(2 * 1000) + const links = await browser.elementsByCss('link[rel=prefetch]') + let foundLink = false - const scripts = await browser.elementsByCss( - // Mouse hover is a high-priority fetch - 'script:not([async])' - ) - let scriptFound = false - for (const aScript of scripts) { - const href = await aScript.getAttribute('src') - if (href.includes('another')) { - scriptFound = true - break + for (const link of links) { + const href = await link.getAttribute('href') + if (href.includes('another')) { + foundLink = true + break + } } - } - expect(scriptFound).toBe(true) - } finally { - if (browser) await browser.close() - } - }) + expect(foundLink).toBe(true) - it('should inject script on hover with prefetching disabled', async () => { - let browser - try { - browser = await webdriver(appPort, '/prefetch-disabled') - await waitFor(2 * 1000) + await browser.elementByCss('#link-another').moveTo() + await waitFor(2 * 1000) - const links = await browser.elementsByCss('link[rel=prefetch]') - let foundLink = false - - for (const link of links) { - const href = await link.getAttribute('href') - if (href.includes('another')) { - foundLink = true - break - } - } - expect(foundLink).toBe(false) - - async function hasAnotherScript() { const scripts = await browser.elementsByCss( // Mouse hover is a high-priority fetch 'script:not([async])' @@ -293,24 +259,99 @@ describe('Prefetching Links in viewport', () => { break } } - return scriptFound + expect(scriptFound).toBe(true) + } finally { + if (browser) await browser.close() } + }) - expect(await hasAnotherScript()).toBe(false) - await browser.elementByCss('#link-another').moveTo() - await waitFor(2 * 1000) - expect(await hasAnotherScript()).toBe(true) - } finally { - if (browser) await browser.close() - } - }) + it('should inject script on hover with prefetching disabled', async () => { + let browser + try { + browser = await webdriver(appPort, '/prefetch-disabled') + await waitFor(2 * 1000) + + const links = await browser.elementsByCss('link[rel=prefetch]') + let foundLink = false + + for (const link of links) { + const href = await link.getAttribute('href') + if (href.includes('another')) { + foundLink = true + break + } + } + expect(foundLink).toBe(false) + + async function hasAnotherScript() { + const scripts = await browser.elementsByCss( + // Mouse hover is a high-priority fetch + 'script:not([async])' + ) + let scriptFound = false + for (const aScript of scripts) { + const href = await aScript.getAttribute('src') + if (href.includes('another')) { + scriptFound = true + break + } + } + return scriptFound + } + + expect(await hasAnotherScript()).toBe(false) + await browser.elementByCss('#link-another').moveTo() + await waitFor(2 * 1000) + expect(await hasAnotherScript()).toBe(true) + } finally { + if (browser) await browser.close() + } + }) + + it('should inject script on hover with prefetching disabled and fetch data', async () => { + let browser + try { + browser = await webdriver(appPort, '/prefetch-disabled-ssg') + + async function hasSsgScript() { + const scripts = await browser.elementsByCss( + // Mouse hover is a high-priority fetch + 'script:not([async])' + ) + let scriptFound = false + for (const aScript of scripts) { + const href = await aScript.getAttribute('src') + if (href.includes('basic')) { + scriptFound = true + break + } + } + return scriptFound + } + + await waitFor(2 * 1000) + expect(await hasSsgScript()).toBe(false) + const hrefs = await browser.eval(`Object.keys(window.next.router.sdc)`) + expect(hrefs.map((href) => new URL(href).pathname)).toEqual([]) + await browser.elementByCss('#link-ssg').moveTo() + await waitFor(2 * 1000) + expect(await hasSsgScript()).toBe(true) + const hrefs2 = await browser.eval(`Object.keys(window.next.router.sdc)`) + expect(hrefs2.map((href) => new URL(href).pathname)).toEqual([ + '/_next/data/test-build/ssg/basic.json', + ]) + } finally { + if (browser) await browser.close() + } + }) - it('should inject script on hover with prefetching disabled and fetch data', async () => { - let browser - try { - browser = await webdriver(appPort, '/prefetch-disabled-ssg') + it('should inject a