From 711e5c45ba3091a0f24edf93d0d32ec6c7d584ef Mon Sep 17 00:00:00 2001 From: Jan Potoms <2109932+Janpot@users.noreply.github.com> Date: Sun, 17 May 2020 12:03:03 +0200 Subject: [PATCH 01/16] Fix missing matcher --- test/integration/404-page-custom-error/test/index.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/404-page-custom-error/test/index.test.js b/test/integration/404-page-custom-error/test/index.test.js index c99f46768afd5..033ff09a1a4f0 100644 --- a/test/integration/404-page-custom-error/test/index.test.js +++ b/test/integration/404-page-custom-error/test/index.test.js @@ -61,7 +61,7 @@ const runTests = mode => { ) .then(() => true) .catch(() => false) - ) + ).toBe(true) }) } } From 3c813b1305b65db6ae978e2c9f69714c6a5c4a0f Mon Sep 17 00:00:00 2001 From: Jan Potoms <2109932+Janpot@users.noreply.github.com> Date: Sun, 17 May 2020 12:38:02 +0200 Subject: [PATCH 02/16] Fix missing matcher in tests --- test/integration/amphtml/test/index.test.js | 2 +- test/integration/app-document/test/rendering.js | 10 +++++----- test/integration/config/test/rendering.js | 12 ++++++------ test/integration/conformance/test/index.test.js | 2 +- test/integration/css-modules/test/index.test.js | 2 +- .../getserversideprops-preview/test/index.test.js | 2 +- .../integration/prerender-preview/test/index.test.js | 4 ++-- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/test/integration/amphtml/test/index.test.js b/test/integration/amphtml/test/index.test.js index 22601ef188027..a1d32b93053ac 100644 --- a/test/integration/amphtml/test/index.test.js +++ b/test/integration/amphtml/test/index.test.js @@ -62,7 +62,7 @@ describe('AMP Usage', () => { expect(html).toMatch(/Hello World/) const $ = cheerio.load(html) - expect($('.abc').length === 1) + expect($('.abc')).toHaveLength(1) }) it('should render the page without leaving render target', async () => { diff --git a/test/integration/app-document/test/rendering.js b/test/integration/app-document/test/rendering.js index 2cb27077bf489..869fd0563a8e4 100644 --- a/test/integration/app-document/test/rendering.js +++ b/test/integration/app-document/test/rendering.js @@ -14,12 +14,12 @@ export default function({ app }, suiteName, render, fetch) { describe('_document', () => { test('It has a custom html class', async () => { const $ = await get$('/') - expect($('html').hasClass('test-html-props')) + expect($('html').hasClass('test-html-props')).toBe(true) }) test('It has a custom body class', async () => { const $ = await get$('/') - expect($('body').hasClass('custom_class')) + expect($('body').hasClass('custom_class')).toBe(true) }) test('It injects custom head tags', async () => { @@ -27,13 +27,13 @@ export default function({ app }, suiteName, render, fetch) { expect( $('head') .text() - .includes('body { margin: 0 }') - ) + .includes() + ).toMatch('body { margin: 0 }') }) test('It passes props from Document.getInitialProps to Document', async () => { const $ = await get$('/') - expect($('#custom-property').text() === 'Hello Document') + expect($('#custom-property').text()).toBe('Hello Document') }) test('It adds nonces to all scripts and preload links', async () => { diff --git a/test/integration/config/test/rendering.js b/test/integration/config/test/rendering.js index ad382079e2645..5f77b87475e06 100644 --- a/test/integration/config/test/rendering.js +++ b/test/integration/config/test/rendering.js @@ -11,32 +11,32 @@ export default function({ app }, suiteName, render, fetch) { describe(suiteName, () => { test('renders css imports', async () => { const $ = await get$('/webpack-css') - expect($('._46QtCORzC4BWRnIseSbG-').text() === 'Hello World') + expect($('._46QtCORzC4BWRnIseSbG-').text()).toBe('Hello World kut') }) test('renders non-js imports from node_modules', async () => { const $ = await get$('/webpack-css') - expect($('._2pRSkKTPDMGLMnmsEkP__J').text() === 'Hello World') + expect($('._2pRSkKTPDMGLMnmsEkP__J').text()).toBe('Hello World') }) test('renders server config on the server only', async () => { const $ = await get$('/next-config') - expect($('#server-only').text() === 'mySecret') + expect($('#server-only').text()).toBe('mySecret') }) test('renders public config on the server only', async () => { const $ = await get$('/next-config') - expect($('#server-and-client').text() === '/static') + expect($('#server-and-client').text()).toBe('/static') }) test('renders the build id in development mode', async () => { const $ = await get$('/build-id') - expect($('#buildId').text() === '-') + expect($('#buildId').text()).toBe('-') }) test('correctly imports a package that defines `module` but no `main` in package.json', async () => { const $ = await get$('/module-only-content') - expect($('#messageInAPackage').text() === 'OK') + expect($('#messageInAPackage').text()).toBe('OK') }) }) } diff --git a/test/integration/conformance/test/index.test.js b/test/integration/conformance/test/index.test.js index 5e3aadb881b3e..3db30cd0039db 100644 --- a/test/integration/conformance/test/index.test.js +++ b/test/integration/conformance/test/index.test.js @@ -22,7 +22,7 @@ describe('Conformance system', () => { ) }) - it('Should warn about sync external sync scripts', async () => { + it('Should warn about using polyfill.io for fetch', async () => { const { stderr } = build expect(stderr).toContain( '[BUILD CONFORMANCE WARNING]: Found polyfill.io loading polyfill for fetch.' diff --git a/test/integration/css-modules/test/index.test.js b/test/integration/css-modules/test/index.test.js index 02b786cf37313..a48b0999440c2 100644 --- a/test/integration/css-modules/test/index.test.js +++ b/test/integration/css-modules/test/index.test.js @@ -257,7 +257,7 @@ describe('Invalid CSS Module Usage in node_modules', () => { }) }) -describe('Invalid CSS Module Usage in node_modules', () => { +describe('Invalid Global CSS Module Usage in node_modules', () => { const appDir = join(fixturesDir, 'invalid-global-module') beforeAll(async () => { diff --git a/test/integration/getserversideprops-preview/test/index.test.js b/test/integration/getserversideprops-preview/test/index.test.js index 720d08bcd9a36..33f2c706096db 100644 --- a/test/integration/getserversideprops-preview/test/index.test.js +++ b/test/integration/getserversideprops-preview/test/index.test.js @@ -71,7 +71,7 @@ function runTests(startServer = nextStart) { const originalCookies = res.headers.get('set-cookie').split(',') const cookies = originalCookies.map(cookie.parse) - expect(originalCookies.every(c => c.includes('; Secure;'))) + expect(originalCookies.every(c => c.includes('; Secure;'))).toBe(true) expect(cookies.length).toBe(2) expect(cookies[0]).toMatchObject({ Path: '/', SameSite: 'None' }) diff --git a/test/integration/prerender-preview/test/index.test.js b/test/integration/prerender-preview/test/index.test.js index c609a3cfead0b..05ee89e204e45 100644 --- a/test/integration/prerender-preview/test/index.test.js +++ b/test/integration/prerender-preview/test/index.test.js @@ -77,7 +77,7 @@ function runTests(startServer = nextStart) { const originalCookies = res.headers.get('set-cookie').split(',') const cookies = originalCookies.map(cookie.parse) - expect(originalCookies.every(c => c.includes('; Secure;'))) + expect(originalCookies.every(c => c.includes('; Secure;'))).toBe(true) expect(cookies.length).toBe(2) expect(cookies[0]).toMatchObject({ Path: '/', SameSite: 'None' }) @@ -103,7 +103,7 @@ function runTests(startServer = nextStart) { const originalCookies = res.headers.get('set-cookie').split(',') const cookies = originalCookies.map(cookie.parse) - expect(originalCookies.every(c => c.includes('; Secure;'))) + expect(originalCookies.every(c => c.includes('; Secure;'))).toBe(true) expect(cookies.length).toBe(2) expect(cookies[0]).toMatchObject({ Path: '/', SameSite: 'None' }) From e6de3fa53f8f4dbe56c2d5cf6db57c0bb3e9df3e Mon Sep 17 00:00:00 2001 From: Jan Potoms <2109932+Janpot@users.noreply.github.com> Date: Sun, 17 May 2020 12:52:41 +0200 Subject: [PATCH 03/16] oops --- test/integration/config/test/rendering.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/config/test/rendering.js b/test/integration/config/test/rendering.js index 5f77b87475e06..56a9a651f9402 100644 --- a/test/integration/config/test/rendering.js +++ b/test/integration/config/test/rendering.js @@ -11,7 +11,7 @@ export default function({ app }, suiteName, render, fetch) { describe(suiteName, () => { test('renders css imports', async () => { const $ = await get$('/webpack-css') - expect($('._46QtCORzC4BWRnIseSbG-').text()).toBe('Hello World kut') + expect($('._46QtCORzC4BWRnIseSbG-').text()).toBe('Hello World') }) test('renders non-js imports from node_modules', async () => { From 9e4782c0e2d9ff17ce652b32d0dcb5fd87b29e43 Mon Sep 17 00:00:00 2001 From: Jan Potoms <2109932+Janpot@users.noreply.github.com> Date: Sun, 17 May 2020 12:58:25 +0200 Subject: [PATCH 04/16] oops 2 --- test/integration/app-document/test/rendering.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/test/integration/app-document/test/rendering.js b/test/integration/app-document/test/rendering.js index 869fd0563a8e4..2b0cbb8c2e0f0 100644 --- a/test/integration/app-document/test/rendering.js +++ b/test/integration/app-document/test/rendering.js @@ -24,11 +24,7 @@ export default function({ app }, suiteName, render, fetch) { test('It injects custom head tags', async () => { const $ = await get$('/') - expect( - $('head') - .text() - .includes() - ).toMatch('body { margin: 0 }') + expect($('head').text()).toMatch('body { margin: 0 }') }) test('It passes props from Document.getInitialProps to Document', async () => { From e82c931e73135d68cdd98d801b7f17a5f99d9f59 Mon Sep 17 00:00:00 2001 From: Jan Potoms <2109932+Janpot@users.noreply.github.com> Date: Sun, 17 May 2020 13:51:44 +0200 Subject: [PATCH 05/16] This is not a regression --- test/integration/config/test/index.test.js | 15 +++------------ test/integration/config/test/rendering.js | 4 ++-- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/test/integration/config/test/index.test.js b/test/integration/config/test/index.test.js index 1f6283c6e7ae8..c1f7ede23c779 100644 --- a/test/integration/config/test/index.test.js +++ b/test/integration/config/test/index.test.js @@ -1,13 +1,7 @@ /* eslint-env jest */ import { join } from 'path' -import { - renderViaHTTP, - fetchViaHTTP, - findPort, - launchApp, - killApp, -} from 'next-test-utils' +import { renderViaHTTP, findPort, launchApp, killApp } from 'next-test-utils' import fetch from 'node-fetch' // test suits @@ -41,11 +35,8 @@ describe('Configuration', () => { killApp(context.server) }) - rendering( - context, - 'Rendering via HTTP', - (p, q) => renderViaHTTP(context.appPort, p, q), - (p, q) => fetchViaHTTP(context.appPort, p, q) + rendering(context, 'Rendering via HTTP', (p, q) => + renderViaHTTP(context.appPort, p, q) ) client(context, (p, q) => renderViaHTTP(context.appPort, p, q)) }) diff --git a/test/integration/config/test/rendering.js b/test/integration/config/test/rendering.js index 56a9a651f9402..21ad9fa0631b6 100644 --- a/test/integration/config/test/rendering.js +++ b/test/integration/config/test/rendering.js @@ -2,7 +2,7 @@ import cheerio from 'cheerio' -export default function({ app }, suiteName, render, fetch) { +export default function({ app }, suiteName, render) { async function get$(path, query) { const html = await render(path, query) return cheerio.load(html) @@ -21,7 +21,7 @@ export default function({ app }, suiteName, render, fetch) { test('renders server config on the server only', async () => { const $ = await get$('/next-config') - expect($('#server-only').text()).toBe('mySecret') + expect($('#server-only').text()).toBe('secret') }) test('renders public config on the server only', async () => { From 7e2c0d8c4908e72245ef4dffb6ac439156045240 Mon Sep 17 00:00:00 2001 From: Jan Potoms <2109932+Janpot@users.noreply.github.com> Date: Sun, 17 May 2020 14:25:13 +0200 Subject: [PATCH 06/16] Update test to reflect reality --- test/integration/config/test/rendering.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/config/test/rendering.js b/test/integration/config/test/rendering.js index 21ad9fa0631b6..ad783680b1680 100644 --- a/test/integration/config/test/rendering.js +++ b/test/integration/config/test/rendering.js @@ -31,7 +31,7 @@ export default function({ app }, suiteName, render) { test('renders the build id in development mode', async () => { const $ = await get$('/build-id') - expect($('#buildId').text()).toBe('-') + expect($('#buildId').text()).toBe('development') }) test('correctly imports a package that defines `module` but no `main` in package.json', async () => { From 95d2c8f03ec18b94cee6af157e326a5e22cc46aa Mon Sep 17 00:00:00 2001 From: Jan Potoms <2109932+Janpot@users.noreply.github.com> Date: Sun, 17 May 2020 15:13:54 +0200 Subject: [PATCH 07/16] fix test naming and skipping --- .../custom-error/test/index.test.js | 4 +-- .../dynamic-routing/test/index.test.js | 26 +++++++++---------- .../firebase-grpc/test/index.test.js | 2 +- .../jsconfig-paths/test/index.test.js | 4 +-- .../test/index.test.js | 2 +- test/integration/prerender/test/index.test.js | 2 +- .../scss-modules/test/index.test.js | 2 +- .../typescript-paths/test/index.test.js | 2 +- test/unit/next-babel-loader.test.js | 16 ++++++------ test/unit/page-route-sorter.test.js | 4 +-- 10 files changed, 32 insertions(+), 32 deletions(-) diff --git a/test/integration/custom-error/test/index.test.js b/test/integration/custom-error/test/index.test.js index 55c478125da0a..49f16ebd4412d 100644 --- a/test/integration/custom-error/test/index.test.js +++ b/test/integration/custom-error/test/index.test.js @@ -28,7 +28,7 @@ const runTests = () => { const customErrNo404Match = /You have added a custom \/_error page without a custom \/404 page/ describe('Custom _error', () => { - describe('dev mode', () => { + describe('dev mode 1', () => { let stderr = '' beforeAll(async () => { @@ -51,7 +51,7 @@ describe('Custom _error', () => { }) }) - describe('dev mode', () => { + describe('dev mode 2', () => { let stderr = '' beforeAll(async () => { diff --git a/test/integration/dynamic-routing/test/index.test.js b/test/integration/dynamic-routing/test/index.test.js index 9ba0b450a67e3..edddcaf86c130 100644 --- a/test/integration/dynamic-routing/test/index.test.js +++ b/test/integration/dynamic-routing/test/index.test.js @@ -96,19 +96,19 @@ function runTests(dev) { expect(await browser.elementByCss('h3').text()).toBe('My blog') }) - // it('should navigate optional dynamic page', async () => { - // let browser - // try { - // browser = await webdriver(appPort, '/') - // await browser.elementByCss('#view-blog-post-1-comments').click() - // await browser.waitForElementByCss('p') - - // const text = await browser.elementByCss('p').text() - // expect(text).toMatch(/blog post.*543.*comment.*\(all\)/i) - // } finally { - // if (browser) await browser.close() - // } - // }) + it.skip('should navigate optional dynamic page', async () => { + let browser + try { + browser = await webdriver(appPort, '/') + await browser.elementByCss('#view-blog-post-1-comments').click() + await browser.waitForElementByCss('p') + + const text = await browser.elementByCss('p').text() + expect(text).toMatch(/blog post.*543.*comment.*\(all\)/i) + } finally { + if (browser) await browser.close() + } + }) it('should navigate optional dynamic page with value', async () => { let browser diff --git a/test/integration/firebase-grpc/test/index.test.js b/test/integration/firebase-grpc/test/index.test.js index fbfc8c30ef0ea..087f631593357 100644 --- a/test/integration/firebase-grpc/test/index.test.js +++ b/test/integration/firebase-grpc/test/index.test.js @@ -10,7 +10,7 @@ const nextConfig = path.join(appDir, 'next.config.js') describe('Building Firebase', () => { // TODO: investigate re-enabling this test in node 12 environment - xit('Throws an error when building with firebase dependency with worker_threads', async () => { + it.skip('Throws an error when building with firebase dependency with worker_threads', async () => { await fs.writeFile( nextConfig, `module.exports = { experimental: { workerThreads: true } }` diff --git a/test/integration/jsconfig-paths/test/index.test.js b/test/integration/jsconfig-paths/test/index.test.js index b0bda3a567b4b..9a871f2d97031 100644 --- a/test/integration/jsconfig-paths/test/index.test.js +++ b/test/integration/jsconfig-paths/test/index.test.js @@ -49,7 +49,7 @@ describe('TypeScript Features', () => { expect($('body').text()).toMatch(/Hello from a/) }) - it('should resolve the first item in the array first', async () => { + it('should resolve the second item as fallback', async () => { const $ = await get$('/resolve-fallback') expect($('body').text()).toMatch(/Hello from only b/) }) @@ -59,7 +59,7 @@ describe('TypeScript Features', () => { expect($('body').text()).toMatch(/Hello/) }) - it('should resolve a single matching alias', async () => { + it('should resolve a wildcard alias', async () => { const $ = await get$('/wildcard-alias') expect($('body').text()).toMatch(/world/) }) diff --git a/test/integration/legacy-ssg-methods-error/test/index.test.js b/test/integration/legacy-ssg-methods-error/test/index.test.js index 4d0bec9799d1e..bc3f988d7d1a6 100644 --- a/test/integration/legacy-ssg-methods-error/test/index.test.js +++ b/test/integration/legacy-ssg-methods-error/test/index.test.js @@ -50,7 +50,7 @@ const runTests = (serverless = false) => { ) }) - it('should error when legacy unstable_getServerProps', async () => { + it('should error when legacy unstable_getStaticPaths', async () => { await fs.writeFile( indexPage, origIndexPage.replace('getStaticProps', 'getStaticPaths') diff --git a/test/integration/prerender/test/index.test.js b/test/integration/prerender/test/index.test.js index b0140312aa56c..934ae333e345d 100644 --- a/test/integration/prerender/test/index.test.js +++ b/test/integration/prerender/test/index.test.js @@ -739,7 +739,7 @@ const runTests = (dev = false, looseMode = false) => { await check(() => getBrowserBodyText(browser), /hello /) }) - it('should show error for invalid JSON returned from getStaticProps on CST', async () => { + it('should not show error for invalid JSON returned from getStaticProps on CST', async () => { const browser = await webdriver(appPort, '/') await browser.elementByCss('#non-json').click() await check(() => getBrowserBodyText(browser), /hello /) diff --git a/test/integration/scss-modules/test/index.test.js b/test/integration/scss-modules/test/index.test.js index 605ea4c83921f..75d1e609de157 100644 --- a/test/integration/scss-modules/test/index.test.js +++ b/test/integration/scss-modules/test/index.test.js @@ -256,7 +256,7 @@ describe('Invalid CSS Module Usage in node_modules', () => { }) }) -describe('Invalid CSS Module Usage in node_modules', () => { +describe('Invalid CSS Global Module Usage in node_modules', () => { const appDir = join(fixturesDir, 'invalid-global-module') beforeAll(async () => { diff --git a/test/integration/typescript-paths/test/index.test.js b/test/integration/typescript-paths/test/index.test.js index 1c56bad2edf9f..30116ff3264fe 100644 --- a/test/integration/typescript-paths/test/index.test.js +++ b/test/integration/typescript-paths/test/index.test.js @@ -33,7 +33,7 @@ describe('TypeScript Features', () => { expect($('body').text()).toMatch(/Hello from a/) }) - it('should resolve the first item in the array first', async () => { + it('should resolve the second item in as a fallback', async () => { const $ = await get$('/resolve-fallback') expect($('body').text()).toMatch(/Hello from only b/) }) diff --git a/test/unit/next-babel-loader.test.js b/test/unit/next-babel-loader.test.js index 098af9db2c498..5f40cbeb3ac56 100644 --- a/test/unit/next-babel-loader.test.js +++ b/test/unit/next-babel-loader.test.js @@ -86,7 +86,7 @@ describe('next-babel-loader', () => { expect(code).toMatchInlineSnapshot(`"\\"undefined\\";"`) }) - it('should replace typeof window expression nested', async () => { + it('should replace typeof window in === expression nested', async () => { const code = await babel( `function a(){console.log(typeof window === 'undefined')}` ) @@ -98,29 +98,29 @@ describe('next-babel-loader', () => { expect(code).toMatchInlineSnapshot(`"false;"`) }) - it('should replace typeof window expression top level', async () => { + it('should replace typeof window in === expression top level', async () => { const code = await babel(`typeof window === 'object';`) expect(code).toMatchInlineSnapshot(`"true;"`) }) - it('should replace typeof window expression top level', async () => { + it('should replace typeof window in !== expression top level', async () => { const code = await babel(`typeof window !== 'undefined';`) expect(code).toMatchInlineSnapshot(`"true;"`) }) - it('should replace typeof window expression top level', async () => { + it('should replace typeof window expression !== object top level', async () => { const code = await babel(`typeof window !== 'object';`) expect(code).toMatchInlineSnapshot(`"false;"`) }) - it('should replace typeof window expression top level', async () => { + it('should replace typeof window expression top level serverside', async () => { const code = await babel(`typeof window !== 'undefined';`, { isServer: true, }) expect(code).toMatchInlineSnapshot(`"false;"`) }) - it('should replace typeof window expression top level', async () => { + it('should replace typeof window expression !== object top level serverside', async () => { const code = await babel(`typeof window !== 'object';`, { isServer: true, }) @@ -193,12 +193,12 @@ describe('next-babel-loader', () => { expect(code).toMatchInlineSnapshot(`"if(true){}"`) }) - it('should replace NODE_ENV in statement (prod)', async () => { + it('should replace NODE_ENV in === statement (prod)', async () => { const code = await babel(`if (process.env.NODE_ENV === 'production') {}`) expect(code).toMatchInlineSnapshot(`"if(true){}"`) }) - it('should replace NODE_ENV in statement (prod)', async () => { + it('should replace NODE_ENV in !== statement (prod)', async () => { const code = await babel(`if (process.env.NODE_ENV !== 'production') {}`) expect(code).toMatchInlineSnapshot(`"if(false){}"`) }) diff --git a/test/unit/page-route-sorter.test.js b/test/unit/page-route-sorter.test.js index 28240cc482efd..6bebda44ad190 100644 --- a/test/unit/page-route-sorter.test.js +++ b/test/unit/page-route-sorter.test.js @@ -57,13 +57,13 @@ describe('getSortedRoutes', () => { ).toThrowError(/the same slug name/) }) - it('catches reused param names', () => { + it('catches reused param names with catch-all', () => { expect(() => getSortedRoutes(['/blog/[id]', '/blog/[id]/[...id]']) ).toThrowError(/the same slug name/) }) - it('catches middle catch-all', () => { + it('catches middle catch-all before catch-all', () => { expect(() => getSortedRoutes(['/blog/[...id]/[...id2]'])).toThrowError( /must be the last part/ ) From c9d355f713baccc38060cbf602816a0bd7de79e4 Mon Sep 17 00:00:00 2001 From: Jan Potoms <2109932+Janpot@users.noreply.github.com> Date: Sun, 17 May 2020 15:28:52 +0200 Subject: [PATCH 08/16] replace commented test with .skip --- test/integration/prerender/test/index.test.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/integration/prerender/test/index.test.js b/test/integration/prerender/test/index.test.js index 934ae333e345d..69abdd857d0a3 100644 --- a/test/integration/prerender/test/index.test.js +++ b/test/integration/prerender/test/index.test.js @@ -498,13 +498,13 @@ const runTests = (dev = false, looseMode = false) => { if (dev) { // TODO: re-enable when this is supported in dev - // it('should show error when rewriting to dynamic SSG page', async () => { - // const item = Math.round(Math.random() * 100) - // const html = await renderViaHTTP(appPort, `/some-rewrite/${item}`) - // expect(html).toContain( - // `Rewrites don't support dynamic pages with getStaticProps yet. Using this will cause the page to fail to parse the params on the client for the fallback page` - // ) - // }) + it.skip('should show error when rewriting to dynamic SSG page', async () => { + const item = Math.round(Math.random() * 100) + const html = await renderViaHTTP(appPort, `/some-rewrite/${item}`) + expect(html).toContain( + `Rewrites don't support dynamic pages with getStaticProps yet. Using this will cause the page to fail to parse the params on the client for the fallback page` + ) + }) it('should not show warning from url prop being returned', async () => { const urlPropPage = join(appDir, 'pages/url-prop.js') From 270a9b82b267aa628a83bb5466c8dc5dd99733ae Mon Sep 17 00:00:00 2001 From: Jan Potoms <2109932+Janpot@users.noreply.github.com> Date: Sun, 17 May 2020 16:01:40 +0200 Subject: [PATCH 09/16] Remove done callback --- test/unit/mitt.test.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test/unit/mitt.test.js b/test/unit/mitt.test.js index 3bcb13b78d142..b77ceaa66649a 100644 --- a/test/unit/mitt.test.js +++ b/test/unit/mitt.test.js @@ -3,10 +3,12 @@ import mitt from 'next/dist/next-server/lib/mitt' describe('mitt', () => { describe('With listeners', () => { - it('should listen to a event', done => { - const ev = mitt() - ev.on('sample', done) - ev.emit('sample') + it('should listen to a event', () => { + return new Promise(resolve => { + const ev = mitt() + ev.on('sample', resolve) + ev.emit('sample') + }) }) it('should listen to multiple listeners', () => { From c83438d30eeb2a06e03d9be7573d3fda24ebf03a Mon Sep 17 00:00:00 2001 From: Jan Potoms <2109932+Janpot@users.noreply.github.com> Date: Sun, 17 May 2020 16:39:09 +0200 Subject: [PATCH 10/16] Add eslint config --- .eslintrc.json | 11 +++++- package.json | 3 ++ .../file-serving/test/index.test.js | 2 + yarn.lock | 37 +++++++++++++++++++ 4 files changed, 52 insertions(+), 1 deletion(-) diff --git a/.eslintrc.json b/.eslintrc.json index e0e871115f83c..97c7a3b57ccba 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,7 +1,7 @@ { "root": true, "parser": "babel-eslint", - "plugins": ["react", "react-hooks"], + "plugins": ["react", "react-hooks", "jest"], "env": { "browser": true, "commonjs": true, @@ -21,6 +21,15 @@ } }, "overrides": [ + { + "files": ["test/**/*.test.js"], + "extends": ["plugin:jest/recommended"], + "rules": { + "jest/expect-expect": "off", + "jest/no-disabled-tests": "off", + "jest/no-try-expect": "off" + } + }, { "files": ["**/__tests__/**"], "env": { "jest": true } }, { "files": ["**/*.ts", "**/*.tsx"], diff --git a/package.json b/package.json index 863e8c2f42023..3e05d590c8a14 100644 --- a/package.json +++ b/package.json @@ -121,5 +121,8 @@ }, "engines": { "node": ">= 10.13.0" + }, + "dependencies": { + "eslint-plugin-jest": "23.13.1" } } diff --git a/test/integration/file-serving/test/index.test.js b/test/integration/file-serving/test/index.test.js index f6380ac4f432f..cdf19561712ce 100644 --- a/test/integration/file-serving/test/index.test.js +++ b/test/integration/file-serving/test/index.test.js @@ -1,5 +1,7 @@ /* eslint-env jest */ +/* eslint-disable jest/no-identical-title */ + import fs from 'fs-extra' import { join } from 'path' import { diff --git a/yarn.lock b/yarn.lock index 30740eda0054d..1f8024d83f6df 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3307,6 +3307,16 @@ "@typescript-eslint/typescript-estree" "2.17.0" eslint-scope "^5.0.0" +"@typescript-eslint/experimental-utils@^2.5.0": + version "2.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.33.0.tgz#000f1e5f344fbea1323dc91cc174805d75f99a03" + integrity sha512-qzPM2AuxtMrRq78LwyZa8Qn6gcY8obkIrBs1ehqmQADwkYzTE1Pb4y2W+U3rE/iFkSWcWHG2LS6MJfj6SmHApg== + dependencies: + "@types/json-schema" "^7.0.3" + "@typescript-eslint/typescript-estree" "2.33.0" + eslint-scope "^5.0.0" + eslint-utils "^2.0.0" + "@typescript-eslint/parser@2.17.0": version "2.17.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.17.0.tgz#627f79586d868edbab55f46a6b183cdc341aea1d" @@ -3330,6 +3340,19 @@ semver "^6.3.0" tsutils "^3.17.1" +"@typescript-eslint/typescript-estree@2.33.0": + version "2.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.33.0.tgz#33504c050ccafd38f397a645d4e9534d2eccbb5c" + integrity sha512-d8rY6/yUxb0+mEwTShCQF2zYQdLlqihukNfG9IUlLYz5y1CH6G/9XYbrxQLq3Z14RNvkCC6oe+OcFlyUpwUbkg== + dependencies: + debug "^4.1.1" + eslint-visitor-keys "^1.1.0" + glob "^7.1.6" + is-glob "^4.0.1" + lodash "^4.17.15" + semver "^7.3.2" + tsutils "^3.17.1" + "@webassemblyjs/ast@1.9.0": version "1.9.0" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" @@ -7101,6 +7124,13 @@ escodegen@^1.9.1: optionalDependencies: source-map "~0.6.1" +eslint-plugin-jest@23.13.1: + version "23.13.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-23.13.1.tgz#b2ce83f76064ad8ba1f1f26f322b86a86e44148e" + integrity sha512-TRLJH6M6EDvGocD98a7yVThrAOCK9WJfo9phuUb0MJptcrOYZeCKzC9aOzZCD93sxXCsiJVZywaTHdI/mAi0FQ== + dependencies: + "@typescript-eslint/experimental-utils" "^2.5.0" + eslint-plugin-react-hooks@2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-2.3.0.tgz#53e073961f1f5ccf8dd19558036c1fac8c29d99a" @@ -7144,6 +7174,13 @@ eslint-utils@^1.4.3: dependencies: eslint-visitor-keys "^1.1.0" +eslint-utils@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.0.0.tgz#7be1cc70f27a72a76cd14aa698bcabed6890e1cd" + integrity sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA== + dependencies: + eslint-visitor-keys "^1.1.0" + eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" From ed8254df41926b716e9915db81667ba43ea6f97a Mon Sep 17 00:00:00 2001 From: Jan Potoms <2109932+Janpot@users.noreply.github.com> Date: Sun, 17 May 2020 16:58:55 +0200 Subject: [PATCH 11/16] skip faulty test for now --- test/integration/config/test/rendering.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/config/test/rendering.js b/test/integration/config/test/rendering.js index ad783680b1680..58bd9d1a57a98 100644 --- a/test/integration/config/test/rendering.js +++ b/test/integration/config/test/rendering.js @@ -34,7 +34,7 @@ export default function({ app }, suiteName, render) { expect($('#buildId').text()).toBe('development') }) - test('correctly imports a package that defines `module` but no `main` in package.json', async () => { + test.skip('correctly imports a package that defines `module` but no `main` in package.json', async () => { const $ = await get$('/module-only-content') expect($('#messageInAPackage').text()).toBe('OK') }) From 2c66cefcaa17d6800b1efe064ad02d459ac5bd4a Mon Sep 17 00:00:00 2001 From: Jan Potoms <2109932+Janpot@users.noreply.github.com> Date: Sun, 17 May 2020 18:40:38 +0200 Subject: [PATCH 12/16] it should be a dev dependency --- package.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/package.json b/package.json index 3e05d590c8a14..b787be970c1c5 100644 --- a/package.json +++ b/package.json @@ -68,6 +68,7 @@ "cross-spawn": "6.0.5", "escape-string-regexp": "2.0.0", "eslint": "6.8.0", + "eslint-plugin-jest": "23.13.1", "eslint-plugin-react": "7.18.0", "eslint-plugin-react-hooks": "2.3.0", "execa": "2.0.3", @@ -121,8 +122,5 @@ }, "engines": { "node": ">= 10.13.0" - }, - "dependencies": { - "eslint-plugin-jest": "23.13.1" } } From a017a17e7207b87685b0252de5298cd1dfb0af1f Mon Sep 17 00:00:00 2001 From: Jan Potoms <2109932+Janpot@users.noreply.github.com> Date: Sun, 17 May 2020 19:53:48 +0200 Subject: [PATCH 13/16] fix test --- .../config/node_modules/module-only-package/index.js | 1 - test/integration/config/test/rendering.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 100644 test/integration/config/node_modules/module-only-package/index.js diff --git a/test/integration/config/node_modules/module-only-package/index.js b/test/integration/config/node_modules/module-only-package/index.js deleted file mode 100644 index 8f067cba3ad40..0000000000000 --- a/test/integration/config/node_modules/module-only-package/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = "I am sometimes found by tooling. I shouldn't be." diff --git a/test/integration/config/test/rendering.js b/test/integration/config/test/rendering.js index 58bd9d1a57a98..ad783680b1680 100644 --- a/test/integration/config/test/rendering.js +++ b/test/integration/config/test/rendering.js @@ -34,7 +34,7 @@ export default function({ app }, suiteName, render) { expect($('#buildId').text()).toBe('development') }) - test.skip('correctly imports a package that defines `module` but no `main` in package.json', async () => { + test('correctly imports a package that defines `module` but no `main` in package.json', async () => { const $ = await get$('/module-only-content') expect($('#messageInAPackage').text()).toBe('OK') }) From 114d4373820d8993270e3cbae14714d1771321f5 Mon Sep 17 00:00:00 2001 From: Jan Potoms <2109932+Janpot@users.noreply.github.com> Date: Sun, 17 May 2020 20:32:12 +0200 Subject: [PATCH 14/16] log the output of the failing tests --- test/integration/config/test/rendering.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/integration/config/test/rendering.js b/test/integration/config/test/rendering.js index ad783680b1680..87652bb542141 100644 --- a/test/integration/config/test/rendering.js +++ b/test/integration/config/test/rendering.js @@ -11,11 +11,13 @@ export default function({ app }, suiteName, render) { describe(suiteName, () => { test('renders css imports', async () => { const $ = await get$('/webpack-css') + console.log($.html()) expect($('._46QtCORzC4BWRnIseSbG-').text()).toBe('Hello World') }) test('renders non-js imports from node_modules', async () => { const $ = await get$('/webpack-css') + console.log($.html()) expect($('._2pRSkKTPDMGLMnmsEkP__J').text()).toBe('Hello World') }) From 6b354b8f5152c7fde27e2dbccebaccd7a2fb6bd6 Mon Sep 17 00:00:00 2001 From: Jan Potoms <2109932+Janpot@users.noreply.github.com> Date: Mon, 18 May 2020 10:29:45 +0200 Subject: [PATCH 15/16] Fix windows tests --- test/integration/config/test/client.js | 115 ------------- test/integration/config/test/index.test.js | 181 +++++++++++++++++++-- test/integration/config/test/rendering.js | 44 ----- 3 files changed, 170 insertions(+), 170 deletions(-) delete mode 100644 test/integration/config/test/client.js delete mode 100644 test/integration/config/test/rendering.js diff --git a/test/integration/config/test/client.js b/test/integration/config/test/client.js deleted file mode 100644 index 5181256e2381e..0000000000000 --- a/test/integration/config/test/client.js +++ /dev/null @@ -1,115 +0,0 @@ -/* eslint-env jest */ -import webdriver from 'next-webdriver' -import { waitFor } from 'next-test-utils' /* check, File */ -import { readFileSync, writeFileSync } from 'fs' -import { join } from 'path' - -export default (context, render) => { - describe('Configuration', () => { - it('should have config available on the client', async () => { - const browser = await webdriver(context.appPort, '/next-config') - - const serverText = await browser.elementByCss('#server-only').text() - const serverClientText = await browser - .elementByCss('#server-and-client') - .text() - const envValue = await browser.elementByCss('#env').text() - - expect(serverText).toBe('') - expect(serverClientText).toBe('/static') - expect(envValue).toBe('hello') - await browser.close() - }) - - it('should update css styles using hmr', async () => { - let browser - try { - browser = await webdriver(context.appPort, '/webpack-css') - const pTag = await browser.elementByCss('.hello-world') - const initialFontSize = await pTag.getComputedCss('font-size') - - expect(initialFontSize).toBe('100px') - - const pagePath = join( - __dirname, - '../', - 'components', - 'hello-webpack-css.css' - ) - - const originalContent = readFileSync(pagePath, 'utf8') - const editedContent = originalContent.replace('100px', '200px') - - // Change the page - writeFileSync(pagePath, editedContent, 'utf8') - - await waitFor(10000) - - try { - // Check whether the this page has reloaded or not. - const editedPTag = await browser.elementByCss('.hello-world') - const editedFontSize = await editedPTag.getComputedCss('font-size') - - expect(editedFontSize).toBe('200px') - } finally { - // Finally is used so that we revert the content back to the original regardless of the test outcome - // restore the about page content. - writeFileSync(pagePath, originalContent, 'utf8') - } - } finally { - if (browser) { - await browser.close() - } - } - }) - - // it('should update sass styles using hmr', async () => { - // const file = new File(join(__dirname, '../', 'components', 'hello-webpack-sass.scss')) - // let browser - // try { - // browser = await webdriver(context.appPort, '/webpack-css') - - // expect( - // await browser.elementByCss('.hello-world').getComputedCss('color') - // ).toBe('rgba(255, 255, 0, 1)') - - // file.replace('yellow', 'red') - - // await waitFor(10000) - - // await check( - // async () => { - // const tag = await browser.elementByCss('.hello-world') - // const prop = await tag.getComputedCss('color') - - // expect(prop).toBe('rgba(255, 0, 0, 1)') - // return 'works' - // }, - // /works/ - // ) - - // file.restore() - - // await waitFor(10000) - - // await check( - // async () => { - // const tag = await browser.elementByCss('.hello-world') - // const prop = await tag.getComputedCss('color') - // expect(prop).toBe('rgba(255, 255, 0, 1)') - // return 'works' - // }, - // /works/ - // ) - // } catch (err) { - // file.restore() - - // throw err - // } finally { - // if (browser) { - // await browser.close() - // } - // } - // }) - }) -} diff --git a/test/integration/config/test/index.test.js b/test/integration/config/test/index.test.js index c1f7ede23c779..e876ae39326cc 100644 --- a/test/integration/config/test/index.test.js +++ b/test/integration/config/test/index.test.js @@ -1,12 +1,19 @@ /* eslint-env jest */ import { join } from 'path' -import { renderViaHTTP, findPort, launchApp, killApp } from 'next-test-utils' +import { + renderViaHTTP, + findPort, + launchApp, + killApp, + waitFor, + File, + check, +} from 'next-test-utils' import fetch from 'node-fetch' - -// test suits -import rendering from './rendering' -import client from './client' +import cheerio from 'cheerio' +import webdriver from 'next-webdriver' +import { readFileSync, writeFileSync } from 'fs' const context = {} jest.setTimeout(1000 * 60 * 5) @@ -25,18 +32,170 @@ describe('Configuration', () => { ]) }) + afterAll(() => { + killApp(context.server) + }) + + async function get$(path, query) { + const html = await renderViaHTTP(context.appPort, path, query) + return cheerio.load(html) + } + it('should disable X-Powered-By header support', async () => { const url = `http://localhost:${context.appPort}/` const header = (await fetch(url)).headers.get('X-Powered-By') expect(header).not.toBe('Next.js') }) - afterAll(() => { - killApp(context.server) + test('renders css imports', async () => { + let browser + try { + browser = await webdriver(context.appPort, '/webpack-css') + const fontSize = await browser + .elementByCss('.hello-world') + .getComputedCss('font-size') + expect(fontSize).toBe('100px') + } finally { + if (browser) { + await browser.close() + } + } }) - rendering(context, 'Rendering via HTTP', (p, q) => - renderViaHTTP(context.appPort, p, q) - ) - client(context, (p, q) => renderViaHTTP(context.appPort, p, q)) + test('renders non-js imports from node_modules', async () => { + let browser + try { + browser = await webdriver(context.appPort, '/webpack-css') + const backgroundColor = await browser + .elementByCss('.hello-world') + .getComputedCss('background-color') + expect(backgroundColor).toBe('rgba(0, 0, 255, 1)') + } finally { + if (browser) { + await browser.close() + } + } + }) + + test('renders server config on the server only', async () => { + const $ = await get$('/next-config') + expect($('#server-only').text()).toBe('secret') + }) + + test('renders public config on the server only', async () => { + const $ = await get$('/next-config') + expect($('#server-and-client').text()).toBe('/static') + }) + + test('renders the build id in development mode', async () => { + const $ = await get$('/build-id') + expect($('#buildId').text()).toBe('development') + }) + + test('correctly imports a package that defines `module` but no `main` in package.json', async () => { + const $ = await get$('/module-only-content') + expect($('#messageInAPackage').text()).toBe('OK') + }) + + it('should have config available on the client', async () => { + const browser = await webdriver(context.appPort, '/next-config') + + const serverText = await browser.elementByCss('#server-only').text() + const serverClientText = await browser + .elementByCss('#server-and-client') + .text() + const envValue = await browser.elementByCss('#env').text() + + expect(serverText).toBe('') + expect(serverClientText).toBe('/static') + expect(envValue).toBe('hello') + await browser.close() + }) + + it('should update css styles using hmr', async () => { + let browser + try { + browser = await webdriver(context.appPort, '/webpack-css') + const pTag = await browser.elementByCss('.hello-world') + const initialFontSize = await pTag.getComputedCss('font-size') + + expect(initialFontSize).toBe('100px') + + const pagePath = join( + __dirname, + '../', + 'components', + 'hello-webpack-css.css' + ) + + const originalContent = readFileSync(pagePath, 'utf8') + const editedContent = originalContent.replace('100px', '200px') + + // Change the page + writeFileSync(pagePath, editedContent, 'utf8') + + await waitFor(10000) + + try { + // Check whether the this page has reloaded or not. + const editedPTag = await browser.elementByCss('.hello-world') + const editedFontSize = await editedPTag.getComputedCss('font-size') + + expect(editedFontSize).toBe('200px') + } finally { + // Finally is used so that we revert the content back to the original regardless of the test outcome + // restore the about page content. + writeFileSync(pagePath, originalContent, 'utf8') + } + } finally { + if (browser) { + await browser.close() + } + } + }) + + it.skip('should update sass styles using hmr', async () => { + const file = new File( + join(__dirname, '../', 'components', 'hello-webpack-sass.scss') + ) + let browser + try { + browser = await webdriver(context.appPort, '/webpack-css') + + expect( + await browser.elementByCss('.hello-world').getComputedCss('color') + ).toBe('rgba(255, 255, 0, 1)') + + file.replace('yellow', 'red') + + await waitFor(10000) + + await check(async () => { + const tag = await browser.elementByCss('.hello-world') + const prop = await tag.getComputedCss('color') + + expect(prop).toBe('rgba(255, 0, 0, 1)') + return 'works' + }, /works/) + + file.restore() + + await waitFor(10000) + + await check(async () => { + const tag = await browser.elementByCss('.hello-world') + const prop = await tag.getComputedCss('color') + expect(prop).toBe('rgba(255, 255, 0, 1)') + return 'works' + }, /works/) + } catch (err) { + file.restore() + + throw err + } finally { + if (browser) { + await browser.close() + } + } + }) }) diff --git a/test/integration/config/test/rendering.js b/test/integration/config/test/rendering.js deleted file mode 100644 index 87652bb542141..0000000000000 --- a/test/integration/config/test/rendering.js +++ /dev/null @@ -1,44 +0,0 @@ -/* eslint-env jest */ - -import cheerio from 'cheerio' - -export default function({ app }, suiteName, render) { - async function get$(path, query) { - const html = await render(path, query) - return cheerio.load(html) - } - - describe(suiteName, () => { - test('renders css imports', async () => { - const $ = await get$('/webpack-css') - console.log($.html()) - expect($('._46QtCORzC4BWRnIseSbG-').text()).toBe('Hello World') - }) - - test('renders non-js imports from node_modules', async () => { - const $ = await get$('/webpack-css') - console.log($.html()) - expect($('._2pRSkKTPDMGLMnmsEkP__J').text()).toBe('Hello World') - }) - - test('renders server config on the server only', async () => { - const $ = await get$('/next-config') - expect($('#server-only').text()).toBe('secret') - }) - - test('renders public config on the server only', async () => { - const $ = await get$('/next-config') - expect($('#server-and-client').text()).toBe('/static') - }) - - test('renders the build id in development mode', async () => { - const $ = await get$('/build-id') - expect($('#buildId').text()).toBe('development') - }) - - test('correctly imports a package that defines `module` but no `main` in package.json', async () => { - const $ = await get$('/module-only-content') - expect($('#messageInAPackage').text()).toBe('OK') - }) - }) -} From 9078e768db49399dfc0770aa990f5c1314d5ffbf Mon Sep 17 00:00:00 2001 From: Jan Potoms <2109932+Janpot@users.noreply.github.com> Date: Mon, 18 May 2020 11:30:30 +0200 Subject: [PATCH 16/16] reenable test and remove waitFors --- test/integration/config/test/index.test.js | 70 ++++++++++------------ test/lib/next-test-utils.js | 17 ++++++ 2 files changed, 50 insertions(+), 37 deletions(-) diff --git a/test/integration/config/test/index.test.js b/test/integration/config/test/index.test.js index e876ae39326cc..2af5e2bf3010e 100644 --- a/test/integration/config/test/index.test.js +++ b/test/integration/config/test/index.test.js @@ -6,9 +6,8 @@ import { findPort, launchApp, killApp, - waitFor, File, - check, + checkExpectations, } from 'next-test-utils' import fetch from 'node-fetch' import cheerio from 'cheerio' @@ -134,18 +133,25 @@ describe('Configuration', () => { // Change the page writeFileSync(pagePath, editedContent, 'utf8') - await waitFor(10000) - try { - // Check whether the this page has reloaded or not. - const editedPTag = await browser.elementByCss('.hello-world') - const editedFontSize = await editedPTag.getComputedCss('font-size') - - expect(editedFontSize).toBe('200px') + await checkExpectations(async () => { + // Check whether the this page has reloaded or not. + const editedFontSize = await browser + .elementByCss('.hello-world') + .getComputedCss('font-size') + expect(editedFontSize).toBe('200px') + }) } finally { // Finally is used so that we revert the content back to the original regardless of the test outcome // restore the about page content. writeFileSync(pagePath, originalContent, 'utf8') + await checkExpectations(async () => { + // This also make sure that the change is reverted when the etst ends + const editedFontSize = await browser + .elementByCss('.hello-world') + .getComputedCss('font-size') + expect(editedFontSize).toBe('100px') + }) } } finally { if (browser) { @@ -154,44 +160,34 @@ describe('Configuration', () => { } }) - it.skip('should update sass styles using hmr', async () => { + it('should update sass styles using hmr', async () => { const file = new File( join(__dirname, '../', 'components', 'hello-webpack-sass.scss') ) let browser try { browser = await webdriver(context.appPort, '/webpack-css') - expect( await browser.elementByCss('.hello-world').getComputedCss('color') ).toBe('rgba(255, 255, 0, 1)') - file.replace('yellow', 'red') - - await waitFor(10000) - - await check(async () => { - const tag = await browser.elementByCss('.hello-world') - const prop = await tag.getComputedCss('color') - - expect(prop).toBe('rgba(255, 0, 0, 1)') - return 'works' - }, /works/) - - file.restore() - - await waitFor(10000) - - await check(async () => { - const tag = await browser.elementByCss('.hello-world') - const prop = await tag.getComputedCss('color') - expect(prop).toBe('rgba(255, 255, 0, 1)') - return 'works' - }, /works/) - } catch (err) { - file.restore() - - throw err + try { + file.replace('yellow', 'red') + await checkExpectations(async () => { + const color = await browser + .elementByCss('.hello-world') + .getComputedCss('color') + expect(color).toBe('rgba(255, 0, 0, 1)') + }) + } finally { + file.restore() + await checkExpectations(async () => { + const color = await browser + .elementByCss('.hello-world') + .getComputedCss('color') + expect(color).toBe('rgba(255, 255, 0, 1)') + }) + } } finally { if (browser) { await browser.close() diff --git a/test/lib/next-test-utils.js b/test/lib/next-test-utils.js index 4fde40f654771..e7a6444436d05 100644 --- a/test/lib/next-test-utils.js +++ b/test/lib/next-test-utils.js @@ -365,6 +365,23 @@ export async function check(contentFn, regex, hardError = true) { return false } +// Runs the provided expectations periodically until they pass or time out +export async function checkExpectations(runExpectations) { + const interval = 250 + const timeout = 30000 + const startTime = Date.now() + while (true) { + try { + return await runExpectations() + } catch (err) { + if (Date.now() - startTime > timeout) { + throw err + } + } + await waitFor(interval) + } +} + export class File { constructor(path) { this.path = path