From 9bdaf07233574b6a090c523d1be255549ba8bc92 Mon Sep 17 00:00:00 2001 From: Tim Neutkens Date: Thu, 11 Jan 2024 10:23:20 +0100 Subject: [PATCH] Add --ci to jest tests in CI (#60432) ## What? Ensures snapshot tests fail instead of being written in CI. Closes NEXT-2035 --- run-tests.js | 1 + .../acceptance-app/ReactRefreshLogBox.test.ts | 34 +++++++-- .../ReactRefreshLogBox.test.ts.snap | 74 +++++++++++++++++++ .../acceptance/ReactRefreshLogBox.test.ts | 33 +++++++-- .../ReactRefreshLogBox.test.ts.snap | 46 ++++++++++++ .../test/index.test.js | 18 +++-- test/lib/next-modes/base.ts | 4 +- test/lib/next-webdriver.ts | 9 ++- 8 files changed, 195 insertions(+), 24 deletions(-) diff --git a/run-tests.js b/run-tests.js index c270b72ef78d4..6fa7bdfb236d6 100644 --- a/run-tests.js +++ b/run-tests.js @@ -422,6 +422,7 @@ ${ENDGROUP}`) ...(shouldRecordTestWithReplay ? [`--config=jest.replay.config.js`] : []), + ...(process.env.CI ? ['--ci'] : []), '--runInBand', '--forceExit', '--verbose', diff --git a/test/development/acceptance-app/ReactRefreshLogBox.test.ts b/test/development/acceptance-app/ReactRefreshLogBox.test.ts index ee98f29cc5e5b..0c4a63a2e09eb 100644 --- a/test/development/acceptance-app/ReactRefreshLogBox.test.ts +++ b/test/development/acceptance-app/ReactRefreshLogBox.test.ts @@ -5,6 +5,8 @@ import { check, describeVariants as describe } from 'next-test-utils' import path from 'path' import { outdent } from 'outdent' +const IS_TURBOPACK = Boolean(process.env.TURBOPACK) + describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => { const { next } = nextTestSetup({ files: new FileRef(path.join(__dirname, 'fixtures', 'default-template')), @@ -220,7 +222,19 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => { const source = await session.getRedboxSource() expect(next.normalizeTestDirContent(source)).toMatchInlineSnapshot( - next.normalizeSnapshot(` + next.normalizeSnapshot( + IS_TURBOPACK + ? ` + "./index.js:7:1 + Parsing ecmascript source code failed + 5 | div + 6 | ) + > 7 | } + | ^ + + Unexpected eof" + ` + : ` "./index.js Error: x Unexpected token. Did you mean \`{'}'}\` or \`}\`? @@ -246,7 +260,8 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => { Import trace for requested module: ./index.js ./app/page.js" - `) + ` + ) ) await cleanup() @@ -344,13 +359,18 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox app %s', () => { await session.patch('index.module.css', `.button {`) expect(await session.hasRedbox(true)).toBe(true) const source = await session.getRedboxSource() - expect(source).toMatch('./index.module.css:1:1') - expect(source).toMatch('Syntax error: ') - expect(source).toMatch('Unclosed block') + expect(source).toMatch( + IS_TURBOPACK ? './index.module.css:1:8' : './index.module.css:1:1' + ) + if (!IS_TURBOPACK) { + expect(source).toMatch('Syntax error: ') + expect(source).toMatch('Unclosed block') + } expect(source).toMatch('> 1 | .button {') - expect(source).toMatch(' | ^') + expect(source).toMatch(IS_TURBOPACK ? ' | ^' : ' | ^') - // Not local error + // Checks for selectors that can't be prefixed. + // Selector "button" is not pure (pure selectors must contain at least one local class or id) await session.patch('index.module.css', `button {}`) expect(await session.hasRedbox(true)).toBe(true) const source2 = await session.getRedboxSource() diff --git a/test/development/acceptance-app/__snapshots__/ReactRefreshLogBox.test.ts.snap b/test/development/acceptance-app/__snapshots__/ReactRefreshLogBox.test.ts.snap index 64be47456117e..817b1b323fe2d 100644 --- a/test/development/acceptance-app/__snapshots__/ReactRefreshLogBox.test.ts.snap +++ b/test/development/acceptance-app/__snapshots__/ReactRefreshLogBox.test.ts.snap @@ -98,3 +98,77 @@ exports[`ReactRefreshLogBox app default should strip whitespace correctly with n 10 | click me 11 | " `; + +exports[`ReactRefreshLogBox app turbo Can't resolve @import in CSS file 1`] = ` +"./app/styles1.css:1:0 +Parsing css source code failed +> 1 | @import "./styles2.css" + | ^^^^^^^^^^^^^^^^^^^^^^^ + +Unexpected end of file, but expected ';' or '{'" +`; + +exports[`ReactRefreshLogBox app turbo Import trace when module not found in layout 1`] = ` +"./app/module.js:1:0 +Module not found: Can't resolve 'non-existing-module' +> 1 | import "non-existing-module" + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +https://nextjs.org/docs/messages/module-not-found" +`; + +exports[`ReactRefreshLogBox app turbo Should not show __webpack_exports__ when exporting anonymous arrow function 1`] = ` +"index.js (1:13) @ __TURBOPACK__default__export__ + +> 1 | export default () => { + | ^ + 2 | if (typeof window !== 'undefined') { + 3 | throw new Error('test') + 4 | }" +`; + +exports[`ReactRefreshLogBox app turbo boundaries 1`] = ` +"FunctionDefault.js (0:24) @ FunctionDefault + + 1 | export default function FunctionDefault() { throw new Error('no'); }" +`; + +exports[`ReactRefreshLogBox app turbo logbox: anchors links in error messages 1`] = `"Error: end http://nextjs.org"`; + +exports[`ReactRefreshLogBox app turbo logbox: anchors links in error messages 2`] = `"http://nextjs.org/"`; + +exports[`ReactRefreshLogBox app turbo logbox: anchors links in error messages 3`] = `"Error: http://nextjs.org start"`; + +exports[`ReactRefreshLogBox app turbo logbox: anchors links in error messages 4`] = `"http://nextjs.org/"`; + +exports[`ReactRefreshLogBox app turbo logbox: anchors links in error messages 5`] = `"Error: middle http://nextjs.org end"`; + +exports[`ReactRefreshLogBox app turbo logbox: anchors links in error messages 6`] = `"http://nextjs.org/"`; + +exports[`ReactRefreshLogBox app turbo logbox: anchors links in error messages 8`] = `"http://nextjs.org/"`; + +exports[`ReactRefreshLogBox app turbo logbox: anchors links in error messages 9`] = `"http://example.com/"`; + +exports[`ReactRefreshLogBox app turbo module init error not shown 1`] = ` +"index.js (3:6) @ + + 1 | // top offset for snapshot + 2 | import * as React from 'react'; +> 3 | throw new Error('no') + | ^ + 4 | class ClassDefault extends React.Component { + 5 | render() { + 6 | return

Default Export

;" +`; + +exports[`ReactRefreshLogBox app turbo should strip whitespace correctly with newline 1`] = ` +"index.js (6:30) @ onClick + + 4 | + 5 |

index page

+> 6 | + | ^ + 7 | { + 8 | throw new Error('idk') + 9 | }}>" +`; diff --git a/test/development/acceptance/ReactRefreshLogBox.test.ts b/test/development/acceptance/ReactRefreshLogBox.test.ts index 19cf64b5aa1a5..abdc445c8560a 100644 --- a/test/development/acceptance/ReactRefreshLogBox.test.ts +++ b/test/development/acceptance/ReactRefreshLogBox.test.ts @@ -5,6 +5,8 @@ import { describeVariants as describe } from 'next-test-utils' import path from 'path' import { outdent } from 'outdent' +const IS_TURBOPACK = Boolean(process.env.TURBOPACK) + describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => { const { next } = nextTestSetup({ files: new FileRef(path.join(__dirname, 'fixtures', 'default-template')), @@ -211,7 +213,18 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => { const source = await session.getRedboxSource() expect(next.normalizeTestDirContent(source)).toMatchInlineSnapshot( - next.normalizeSnapshot(` + next.normalizeSnapshot( + IS_TURBOPACK + ? ` + "./index.js:7:1 + Parsing ecmascript source code failed + 5 | div + 6 | ) + > 7 | } + | ^ + Unexpected eof" + ` + : ` "./index.js Error: x Unexpected token. Did you mean \`{'}'}\` or \`}\`? @@ -237,7 +250,8 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => { Import trace for requested module: ./index.js ./pages/index.js" - `) + ` + ) ) await cleanup() @@ -335,13 +349,18 @@ describe.each(['default', 'turbo'])('ReactRefreshLogBox %s', () => { await session.patch('index.module.css', `.button {`) expect(await session.hasRedbox(true)).toBe(true) const source = await session.getRedboxSource() - expect(source).toMatch('./index.module.css:1:1') - expect(source).toMatch('Syntax error: ') - expect(source).toMatch('Unclosed block') + expect(source).toMatch( + IS_TURBOPACK ? './index.module.css:1:8' : './index.module.css:1:1' + ) + if (!IS_TURBOPACK) { + expect(source).toMatch('Syntax error: ') + expect(source).toMatch('Unclosed block') + } expect(source).toMatch('> 1 | .button {') - expect(source).toMatch(' | ^') + expect(source).toMatch(IS_TURBOPACK ? ' | ^' : ' | ^') - // Not local error + // Checks for selectors that can't be prefixed. + // Selector "button" is not pure (pure selectors must contain at least one local class or id) await session.patch('index.module.css', `button {}`) expect(await session.hasRedbox(true)).toBe(true) const source2 = await session.getRedboxSource() diff --git a/test/development/acceptance/__snapshots__/ReactRefreshLogBox.test.ts.snap b/test/development/acceptance/__snapshots__/ReactRefreshLogBox.test.ts.snap index 9e6f0d9e59998..97b5c4c3195f7 100644 --- a/test/development/acceptance/__snapshots__/ReactRefreshLogBox.test.ts.snap +++ b/test/development/acceptance/__snapshots__/ReactRefreshLogBox.test.ts.snap @@ -69,3 +69,49 @@ exports[`ReactRefreshLogBox default should strip whitespace correctly with newli 10 | click me 11 | " `; + +exports[`ReactRefreshLogBox turbo boundaries 1`] = `null`; + +exports[`ReactRefreshLogBox turbo logbox: anchors links in error messages 1`] = `"Error: end http://nextjs.org"`; + +exports[`ReactRefreshLogBox turbo logbox: anchors links in error messages 2`] = `"http://nextjs.org/"`; + +exports[`ReactRefreshLogBox turbo logbox: anchors links in error messages 3`] = `"Error: http://nextjs.org start"`; + +exports[`ReactRefreshLogBox turbo logbox: anchors links in error messages 4`] = `"http://nextjs.org/"`; + +exports[`ReactRefreshLogBox turbo logbox: anchors links in error messages 5`] = `"Error: middle http://nextjs.org end"`; + +exports[`ReactRefreshLogBox turbo logbox: anchors links in error messages 6`] = `"http://nextjs.org/"`; + +exports[`ReactRefreshLogBox turbo logbox: anchors links in error messages 8`] = `"http://nextjs.org/"`; + +exports[`ReactRefreshLogBox turbo logbox: anchors links in error messages 9`] = `"http://example.com/"`; + +exports[`ReactRefreshLogBox turbo logbox: anchors links in error messages 11`] = `"http://nextjs.org/"`; + +exports[`ReactRefreshLogBox turbo logbox: anchors links in error messages 12`] = `"http://example.com/"`; + +exports[`ReactRefreshLogBox turbo module init error not shown 1`] = ` +"index.js (3:6) @ + + 1 | // top offset for snapshot + 2 | import * as React from 'react'; +> 3 | throw new Error('no') + | ^ + 4 | class ClassDefault extends React.Component { + 5 | render() { + 6 | return

Default Export

;" +`; + +exports[`ReactRefreshLogBox turbo should strip whitespace correctly with newline 1`] = ` +"index.js (8:18) @ onClick + + 6 | + 7 | { +> 8 | throw new Error('idk') + |^ + 9 | }}> + 10 | click me + 11 | " +`; diff --git a/test/integration/edge-runtime-configurable-guards/test/index.test.js b/test/integration/edge-runtime-configurable-guards/test/index.test.js index 153da589e0126..6bbf4e25bf9b1 100644 --- a/test/integration/edge-runtime-configurable-guards/test/index.test.js +++ b/test/integration/edge-runtime-configurable-guards/test/index.test.js @@ -9,6 +9,7 @@ import { launchApp, nextBuild, nextStart, + retry, waitFor, } from 'next-test-utils' import { remove } from 'fs-extra' @@ -83,19 +84,22 @@ describe('Edge runtime configurable guards', () => { const res = await fetchViaHTTP(context.appPort, middlewareUrl) await waitFor(500) expect(res.status).toBe(200) - expect(context.logs.output).toContain( - `Dynamic Code Evaluation (e. g. 'eval', 'new Function') not allowed in Edge Runtime` - ) + await retry(async () => { + expect(context.logs.output).toContain( + `Dynamic Code Evaluation (e. g. 'eval', 'new Function') not allowed in Edge Runtime` + ) + }) }) it('warns in dev for unallowed code', async () => { context.app = await launchApp(context.appDir, context.appPort, appOption) const res = await fetchViaHTTP(context.appPort, routeUrl) - await waitFor(500) expect(res.status).toBe(200) - expect(context.logs.output).toContain( - `Dynamic Code Evaluation (e. g. 'eval', 'new Function') not allowed in Edge Runtime` - ) + await retry(async () => { + expect(context.logs.output).toContain( + `Dynamic Code Evaluation (e. g. 'eval', 'new Function') not allowed in Edge Runtime` + ) + }) }) ;(process.env.TURBOPACK ? describe.skip : describe)( 'production mode', diff --git a/test/lib/next-modes/base.ts b/test/lib/next-modes/base.ts index 7597f25d8c935..530d280fa8f98 100644 --- a/test/lib/next-modes/base.ts +++ b/test/lib/next-modes/base.ts @@ -8,7 +8,7 @@ import { ChildProcess } from 'child_process' import { createNextInstall } from '../create-next-install' import { Span } from 'next/src/trace' import webdriver from '../next-webdriver' -import { renderViaHTTP, fetchViaHTTP } from 'next-test-utils' +import { renderViaHTTP, fetchViaHTTP, waitFor } from 'next-test-utils' import cheerio from 'cheerio' import { BrowserInterface } from '../browsers/base' import escapeStringRegexp from 'escape-string-regexp' @@ -447,7 +447,7 @@ export class NextInstance { // to connect the WebSocket and start watching. if (process.env.TURBOPACK) { require('console').log('fs dev delay before', filename) - await new Promise((resolve) => setTimeout(resolve, 500)) + await waitFor(500) } } private async handleDevWatchDelayAfterChange(filename: string) { diff --git a/test/lib/next-webdriver.ts b/test/lib/next-webdriver.ts index b9ff4ce2e3c50..000921dcb2aad 100644 --- a/test/lib/next-webdriver.ts +++ b/test/lib/next-webdriver.ts @@ -1,4 +1,4 @@ -import { getFullUrl } from 'next-test-utils' +import { getFullUrl, waitFor } from 'next-test-utils' import os from 'os' import { BrowserInterface } from './browsers/base' @@ -186,5 +186,12 @@ export default async function webdriver( console.log(`\n> Hydration complete for ${fullUrl}\n`) } + + // This is a temporary workaround for turbopack starting watching too late. + // So we delay file changes by 500ms to give it some time + // to connect the WebSocket and start watching. + if (process.env.TURBOPACK) { + await waitFor(1000) + } return browser }