From 7d0919a7848e34f6d68ee97fcc61f7487472e666 Mon Sep 17 00:00:00 2001 From: JJ Kasper <22380829+ijjk@users.noreply.github.com> Date: Wed, 20 Mar 2019 05:01:32 -0500 Subject: [PATCH] Break up basic test suite (#6730) * Break out client-navigation and rendering test from basic test * Try with parallelism dialed back to 3 * Update jest-junit for more compatible timings in CircleCI * Bump to test timings * Use filepath for suitename in jest-junit * Store reports as artifacts * Try using classname for timings * Bump * Remove reports from artifacts --- .circleci/config.yml | 5 +- package.json | 4 +- .../basic/test/client-navigation.js | 776 ---------------- test/integration/basic/test/index.test.js | 34 - .../components/hello.jsx | 0 .../client-navigation/components/hello1.js | 3 + .../components/world.jsx | 0 .../lib/async-function.js | 0 .../{basic => client-navigation}/lib/cdm.js | 0 .../lib/data.json | 0 .../client-navigation/next.config.js | 6 + .../pages/async-props.js | 0 .../pages/circular-json-error.js | 0 .../pages/custom-encoding.js | 0 .../pages/custom-extension.jsx | 0 .../pages/default-head.js | 0 .../client-navigation/pages/dynamic/ssr.js | 5 + .../pages/empty-get-initial-props.js | 0 .../error-in-the-browser-global-scope.js | 0 .../pages/error-in-the-global-scope.js | 0 .../pages/error-inside-browser-page.js | 0 .../pages/error-inside-page.js | 0 .../pages/exports.js | 0 .../pages/forwardRef-component.js | 0 .../pages/fragment-syntax.js | 0 .../pages/head.js | 0 .../pages/index.js | 0 .../pages/instance-get-initial-props.js | 0 .../pages/json.js | 0 .../pages/link.js | 0 .../pages/memo-component.js | 0 .../pages/nav/about.js | 0 .../pages/nav/as-path-pushstate.js | 0 .../pages/nav/as-path-query.js | 0 .../pages/nav/as-path-using-router.js | 0 .../pages/nav/as-path.js | 0 .../pages/nav/hash-changes.js | 0 .../pages/nav/head-1.js | 0 .../pages/nav/head-2.js | 0 .../pages/nav/index.js | 0 .../pages/nav/on-click.js | 0 .../pages/nav/pass-href-prop.js | 0 .../pages/nav/querystring.js | 0 .../pages/nav/redirect.js | 0 .../pages/nav/self-reload.js | 0 .../pages/nav/shallow-routing.js | 0 .../pages/nav/url-prop-change.js | 0 .../pages/nav/with-hoc.js | 0 .../pages/nested-cdm/index.js | 0 .../pages/nested-index/index/index.js | 0 .../pages/no-default-export.js | 0 .../pages/read-only-object-error.js | 0 .../pages/stateless.js | 0 .../pages/styled-jsx.js | 0 .../pages/throw-undefined.js | 2 +- .../pages/url-prop-override.js | 0 .../pages/url-prop.js | 0 .../pages/with-cdm.js | 0 .../client-navigation/test/index.test.js | 830 ++++++++++++++++++ .../test/rendering.js | 4 +- yarn.lock | 63 +- 61 files changed, 908 insertions(+), 824 deletions(-) delete mode 100644 test/integration/basic/test/client-navigation.js rename test/integration/{basic => client-navigation}/components/hello.jsx (100%) create mode 100644 test/integration/client-navigation/components/hello1.js rename test/integration/{basic => client-navigation}/components/world.jsx (100%) rename test/integration/{basic => client-navigation}/lib/async-function.js (100%) rename test/integration/{basic => client-navigation}/lib/cdm.js (100%) rename test/integration/{basic => client-navigation}/lib/data.json (100%) create mode 100644 test/integration/client-navigation/next.config.js rename test/integration/{basic => client-navigation}/pages/async-props.js (100%) rename test/integration/{basic => client-navigation}/pages/circular-json-error.js (100%) rename test/integration/{basic => client-navigation}/pages/custom-encoding.js (100%) rename test/integration/{basic => client-navigation}/pages/custom-extension.jsx (100%) rename test/integration/{basic => client-navigation}/pages/default-head.js (100%) create mode 100644 test/integration/client-navigation/pages/dynamic/ssr.js rename test/integration/{basic => client-navigation}/pages/empty-get-initial-props.js (100%) rename test/integration/{basic => client-navigation}/pages/error-in-the-browser-global-scope.js (100%) rename test/integration/{basic => client-navigation}/pages/error-in-the-global-scope.js (100%) rename test/integration/{basic => client-navigation}/pages/error-inside-browser-page.js (100%) rename test/integration/{basic => client-navigation}/pages/error-inside-page.js (100%) rename test/integration/{basic => client-navigation}/pages/exports.js (100%) rename test/integration/{basic => client-navigation}/pages/forwardRef-component.js (100%) rename test/integration/{basic => client-navigation}/pages/fragment-syntax.js (100%) rename test/integration/{basic => client-navigation}/pages/head.js (100%) rename test/integration/{basic => client-navigation}/pages/index.js (100%) rename test/integration/{basic => client-navigation}/pages/instance-get-initial-props.js (100%) rename test/integration/{basic => client-navigation}/pages/json.js (100%) rename test/integration/{basic => client-navigation}/pages/link.js (100%) rename test/integration/{basic => client-navigation}/pages/memo-component.js (100%) rename test/integration/{basic => client-navigation}/pages/nav/about.js (100%) rename test/integration/{basic => client-navigation}/pages/nav/as-path-pushstate.js (100%) rename test/integration/{basic => client-navigation}/pages/nav/as-path-query.js (100%) rename test/integration/{basic => client-navigation}/pages/nav/as-path-using-router.js (100%) rename test/integration/{basic => client-navigation}/pages/nav/as-path.js (100%) rename test/integration/{basic => client-navigation}/pages/nav/hash-changes.js (100%) rename test/integration/{basic => client-navigation}/pages/nav/head-1.js (100%) rename test/integration/{basic => client-navigation}/pages/nav/head-2.js (100%) rename test/integration/{basic => client-navigation}/pages/nav/index.js (100%) rename test/integration/{basic => client-navigation}/pages/nav/on-click.js (100%) rename test/integration/{basic => client-navigation}/pages/nav/pass-href-prop.js (100%) rename test/integration/{basic => client-navigation}/pages/nav/querystring.js (100%) rename test/integration/{basic => client-navigation}/pages/nav/redirect.js (100%) rename test/integration/{basic => client-navigation}/pages/nav/self-reload.js (100%) rename test/integration/{basic => client-navigation}/pages/nav/shallow-routing.js (100%) rename test/integration/{basic => client-navigation}/pages/nav/url-prop-change.js (100%) rename test/integration/{basic => client-navigation}/pages/nav/with-hoc.js (100%) rename test/integration/{basic => client-navigation}/pages/nested-cdm/index.js (100%) rename test/integration/{basic => client-navigation}/pages/nested-index/index/index.js (100%) rename test/integration/{basic => client-navigation}/pages/no-default-export.js (100%) rename test/integration/{basic => client-navigation}/pages/read-only-object-error.js (100%) rename test/integration/{basic => client-navigation}/pages/stateless.js (100%) rename test/integration/{basic => client-navigation}/pages/styled-jsx.js (100%) rename test/integration/{basic => client-navigation}/pages/throw-undefined.js (82%) rename test/integration/{basic => client-navigation}/pages/url-prop-override.js (100%) rename test/integration/{basic => client-navigation}/pages/url-prop.js (100%) rename test/integration/{basic => client-navigation}/pages/with-cdm.js (100%) create mode 100644 test/integration/client-navigation/test/index.test.js rename test/integration/{basic => client-navigation}/test/rendering.js (99%) diff --git a/.circleci/config.yml b/.circleci/config.yml index a1c557a9da..1522ea8f21 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -16,7 +16,7 @@ jobs: root: ~/repo paths: ['.'] test: - parallelism: 6 + parallelism: 3 docker: - image: circleci/node:8-browsers working_directory: ~/repo @@ -25,9 +25,10 @@ jobs: at: . - run: name: Tests - command: yarn testall $(circleci tests glob "test/**/*.test.*" | circleci tests split --split-by=timings) + command: yarn testall $(circleci tests glob "test/**/*.test.*" | circleci tests split --split-by=timings --timings-type=classname) environment: JEST_JUNIT_OUTPUT: 'reports/junit/js-test-results.xml' + JEST_JUNIT_CLASSNAME: '{filepath}' - store_test_results: path: ~/repo/reports deploy: diff --git a/package.json b/package.json index b10e7c8367..b70007a883 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "examples/with-ioc/**", "examples/with-kea/**", "examples/with-mobx/**", - "test/integration/basic/pages/throw-undefined.js" + "test/integration/client-navigation/pages/throw-undefined.js" ] }, "devDependencies": { @@ -82,7 +82,7 @@ "get-port": "3.2.0", "isomorphic-unfetch": "3.0.0", "jest-cli": "23.6.0", - "jest-junit": "^5.0.0", + "jest-junit": "6.3.0", "lerna": "^3.4.0", "lint-staged": "4.2.3", "mkdirp": "0.5.1", diff --git a/test/integration/basic/test/client-navigation.js b/test/integration/basic/test/client-navigation.js deleted file mode 100644 index c0584d449e..0000000000 --- a/test/integration/basic/test/client-navigation.js +++ /dev/null @@ -1,776 +0,0 @@ -/* eslint-env jest */ - -import webdriver from 'next-webdriver' -import { waitFor, getReactErrorOverlayContent } from 'next-test-utils' - -export default (context) => { - describe('Client Navigation', () => { - describe('with ', () => { - it('should navigate the page', async () => { - const browser = await webdriver(context.appPort, '/nav') - const text = await browser - .elementByCss('#about-link').click() - .waitForElementByCss('.nav-about') - .elementByCss('p').text() - - expect(text).toBe('This is the about page.') - await browser.close() - }) - - it('should navigate via the client side', async () => { - const browser = await webdriver(context.appPort, '/nav') - - const counterText = await browser - .elementByCss('#increase').click() - .elementByCss('#about-link').click() - .waitForElementByCss('.nav-about') - .elementByCss('#home-link').click() - .waitForElementByCss('.nav-home') - .elementByCss('#counter').text() - - expect(counterText).toBe('Counter: 1') - await browser.close() - }) - }) - - describe('With url property', () => { - it('Should keep immutable pathname, asPath and query', async () => { - const browser = await webdriver(context.appPort, '/nav/url-prop-change') - await browser.elementByCss('#add-query').click() - const urlResult = await browser.elementByCss('#url-result').text() - const previousUrlResult = await browser.elementByCss('#previous-url-result').text() - - expect(JSON.parse(urlResult)).toMatchObject({ 'query': { 'added': 'yes' }, 'pathname': '/nav/url-prop-change', 'asPath': '/nav/url-prop-change?added=yes' }) - expect(JSON.parse(previousUrlResult)).toMatchObject({ 'query': {}, 'pathname': '/nav/url-prop-change', 'asPath': '/nav/url-prop-change' }) - - await browser.close() - }) - }) - - describe('with tag inside the ', () => { - it('should navigate the page', async () => { - const browser = await webdriver(context.appPort, '/nav/about') - const text = await browser - .elementByCss('#home-link').click() - .waitForElementByCss('.nav-home') - .elementByCss('p').text() - - expect(text).toBe('This is the home.') - await browser.close() - }) - - it('should not navigate if the tag has a target', async () => { - const browser = await webdriver(context.appPort, '/nav') - - const counterText = await browser - .elementByCss('#increase').click() - .elementByCss('#target-link').click() - .elementByCss('#counter').text() - - expect(counterText).toBe('Counter: 1') - await browser.close() - }) - }) - - describe('with unexpected nested tag', () => { - it('should not redirect if passHref prop is not defined in Link', async () => { - const browser = await webdriver(context.appPort, '/nav/pass-href-prop') - const text = await browser - .elementByCss('#without-href').click() - .waitForElementByCss('.nav-pass-href-prop') - .elementByCss('p').text() - - expect(text).toBe('This is the passHref prop page.') - await browser.close() - }) - - it('should redirect if passHref prop is defined in Link', async () => { - const browser = await webdriver(context.appPort, '/nav/pass-href-prop') - const text = await browser - .elementByCss('#with-href').click() - .waitForElementByCss('.nav-home') - .elementByCss('p').text() - - expect(text).toBe('This is the home.') - await browser.close() - }) - }) - - describe('with empty getInitialProps()', () => { - it('should render an error', async () => { - let browser - try { - browser = await webdriver(context.appPort, '/nav') - await browser.elementByCss('#empty-props').click() - - await waitFor(3000) - - expect(await getReactErrorOverlayContent(browser)).toMatch( - /should resolve to an object\. But found "null" instead\./ - ) - } finally { - if (browser) { - await browser.close() - } - } - }) - }) - - describe('with the same page but different querystring', () => { - it('should navigate the page', async () => { - const browser = await webdriver(context.appPort, '/nav/querystring?id=1') - const text = await browser - .elementByCss('#next-id-link').click() - .waitForElementByCss('.nav-id-2') - .elementByCss('p').text() - - expect(text).toBe('2') - await browser.close() - }) - - it('should remove querystring', async () => { - const browser = await webdriver(context.appPort, '/nav/querystring?id=1') - const text = await browser - .elementByCss('#main-page').click() - .waitForElementByCss('.nav-id-0') - .elementByCss('p').text() - - expect(text).toBe('0') - await browser.close() - }) - }) - - describe('with the current url', () => { - it('should reload the page', async () => { - const browser = await webdriver(context.appPort, '/nav/self-reload') - const defaultCount = await browser.elementByCss('p').text() - expect(defaultCount).toBe('COUNT: 0') - - const countAfterClicked = await browser - .elementByCss('#self-reload-link').click() - .elementByCss('p').text() - - expect(countAfterClicked).toBe('COUNT: 1') - await browser.close() - }) - - it('should always replace the state', async () => { - const browser = await webdriver(context.appPort, '/nav') - - const countAfterClicked = await browser - .elementByCss('#self-reload-link').click() - .waitForElementByCss('#self-reload-page') - .elementByCss('#self-reload-link').click() - .elementByCss('#self-reload-link').click() - .elementByCss('p').text() - - // counts (page change + two clicks) - expect(countAfterClicked).toBe('COUNT: 3') - - // Since we replace the state, back button would simply go us back to /nav - await browser - .back() - .waitForElementByCss('.nav-home') - - await browser.close() - }) - }) - - describe('with onClick action', () => { - it('should reload the page and perform additional action', async () => { - let browser - try { - browser = await webdriver(context.appPort, '/nav/on-click') - const defaultCountQuery = await browser.elementByCss('#query-count').text() - const defaultCountState = await browser.elementByCss('#state-count').text() - expect(defaultCountQuery).toBe('QUERY COUNT: 0') - expect(defaultCountState).toBe('STATE COUNT: 0') - - await browser.elementByCss('#on-click-link').click() - - const countQueryAfterClicked = await browser.elementByCss('#query-count').text() - const countStateAfterClicked = await browser.elementByCss('#state-count').text() - expect(countQueryAfterClicked).toBe('QUERY COUNT: 1') - expect(countStateAfterClicked).toBe('STATE COUNT: 1') - } finally { - if (browser) { - await browser.close() - } - } - }) - - it('should not reload if default was prevented', async () => { - let browser - try { - browser = await webdriver(context.appPort, '/nav/on-click') - const defaultCountQuery = await browser.elementByCss('#query-count').text() - const defaultCountState = await browser.elementByCss('#state-count').text() - expect(defaultCountQuery).toBe('QUERY COUNT: 0') - expect(defaultCountState).toBe('STATE COUNT: 0') - - await browser.elementByCss('#on-click-link-prevent-default').click() - - const countQueryAfterClicked = await browser.elementByCss('#query-count').text() - const countStateAfterClicked = await browser.elementByCss('#state-count').text() - expect(countQueryAfterClicked).toBe('QUERY COUNT: 0') - expect(countStateAfterClicked).toBe('STATE COUNT: 1') - - await browser.elementByCss('#on-click-link').click() - - const countQueryAfterClickedAgain = await browser.elementByCss('#query-count').text() - const countStateAfterClickedAgain = await browser.elementByCss('#state-count').text() - expect(countQueryAfterClickedAgain).toBe('QUERY COUNT: 1') - expect(countStateAfterClickedAgain).toBe('STATE COUNT: 2') - } finally { - if (browser) { - await browser.close() - } - } - }) - - it('should always replace the state and perform additional action', async () => { - let browser - try { - browser = await webdriver(context.appPort, '/nav') - - await browser.elementByCss('#on-click-link').click().waitForElementByCss('#on-click-page') - - const defaultCountQuery = await browser.elementByCss('#query-count').text() - expect(defaultCountQuery).toBe('QUERY COUNT: 1') - - await browser.elementByCss('#on-click-link').click() - const countQueryAfterClicked = await browser.elementByCss('#query-count').text() - const countStateAfterClicked = await browser.elementByCss('#state-count').text() - expect(countQueryAfterClicked).toBe('QUERY COUNT: 2') - expect(countStateAfterClicked).toBe('STATE COUNT: 1') - - // Since we replace the state, back button would simply go us back to /nav - await browser.back().waitForElementByCss('.nav-home') - } finally { - if (browser) { - await browser.close() - } - } - }) - }) - - describe('with hash changes', () => { - describe('when hash change via Link', () => { - it('should not run getInitialProps', async () => { - const browser = await webdriver(context.appPort, '/nav/hash-changes') - - const counter = await browser - .elementByCss('#via-link').click() - .elementByCss('p').text() - - expect(counter).toBe('COUNT: 0') - - await browser.close() - }) - - it('should scroll to the specified position on the same page', async () => { - let browser - try { - browser = await webdriver(context.appPort, '/nav/hash-changes') - - // Scrolls to item 400 on the page - const scrollPosition = await browser - .elementByCss('#scroll-to-item-400').click() - .eval('window.pageYOffset') - - expect(scrollPosition).toBe(7258) - - // Scrolls back to top when scrolling to `#` with no value. - const scrollPositionAfterEmptyHash = await browser - .elementByCss('#via-empty-hash').click() - .eval('window.pageYOffset') - - expect(scrollPositionAfterEmptyHash).toBe(0) - } finally { - if (browser) { - await browser.close() - } - } - }) - - it('should scroll to the specified position on the same page with a name property', async () => { - let browser - try { - browser = await webdriver(context.appPort, '/nav/hash-changes') - - // Scrolls to item 400 with name="name-item-400" on the page - const scrollPosition = await browser - .elementByCss('#scroll-to-name-item-400').click() - .eval('window.pageYOffset') - - console.log(scrollPosition) - - expect(scrollPosition).toBe(16258) - - // Scrolls back to top when scrolling to `#` with no value. - const scrollPositionAfterEmptyHash = await browser - .elementByCss('#via-empty-hash').click() - .eval('window.pageYOffset') - - expect(scrollPositionAfterEmptyHash).toBe(0) - } finally { - if (browser) { - await browser.close() - } - } - }) - - it('should scroll to the specified position to a new page', async () => { - let browser - try { - browser = await webdriver(context.appPort, '/nav') - - // Scrolls to item 400 on the page - await browser - .elementByCss('#scroll-to-hash').click() - .waitForElementByCss('#hash-changes-page') - - const scrollPosition = await browser.eval('window.pageYOffset') - expect(scrollPosition).toBe(7258) - } finally { - if (browser) { - await browser.close() - } - } - }) - }) - - describe('when hash change via A tag', () => { - it('should not run getInitialProps', async () => { - const browser = await webdriver(context.appPort, '/nav/hash-changes') - - const counter = await browser - .elementByCss('#via-a').click() - .elementByCss('p').text() - - expect(counter).toBe('COUNT: 0') - - await browser.close() - }) - }) - - describe('when hash get removed', () => { - it('should not run getInitialProps', async () => { - const browser = await webdriver(context.appPort, '/nav/hash-changes') - - const counter = await browser - .elementByCss('#via-a').click() - .elementByCss('#page-url').click() - .elementByCss('p').text() - - expect(counter).toBe('COUNT: 1') - - await browser.close() - }) - }) - - describe('when hash set to empty', () => { - it('should not run getInitialProps', async () => { - const browser = await webdriver(context.appPort, '/nav/hash-changes') - - const counter = await browser - .elementByCss('#via-a').click() - .elementByCss('#via-empty-hash').click() - .elementByCss('p').text() - - expect(counter).toBe('COUNT: 0') - - await browser.close() - }) - }) - - describe('when hash changed to a different hash', () => { - it('should not run getInitialProps', async () => { - const browser = await webdriver(context.appPort, '/nav/hash-changes') - - const counter = await browser - .elementByCss('#via-a').click() - .elementByCss('#via-link').click() - .elementByCss('p').text() - - expect(counter).toBe('COUNT: 0') - - await browser.close() - }) - }) - }) - - describe('with shallow routing', () => { - it('should update the url without running getInitialProps', async () => { - const browser = await webdriver(context.appPort, '/nav/shallow-routing') - const counter = await browser - .elementByCss('#increase').click() - .elementByCss('#increase').click() - .elementByCss('#counter').text() - expect(counter).toBe('Counter: 2') - - const getInitialPropsRunCount = await browser - .elementByCss('#get-initial-props-run-count').text() - expect(getInitialPropsRunCount).toBe('getInitialProps run count: 1') - - await browser.close() - }) - - it('should handle the back button and should not run getInitialProps', async () => { - const browser = await webdriver(context.appPort, '/nav/shallow-routing') - let counter = await browser - .elementByCss('#increase').click() - .elementByCss('#increase').click() - .elementByCss('#counter').text() - expect(counter).toBe('Counter: 2') - - counter = await browser - .back() - .elementByCss('#counter').text() - expect(counter).toBe('Counter: 1') - - const getInitialPropsRunCount = await browser - .elementByCss('#get-initial-props-run-count').text() - expect(getInitialPropsRunCount).toBe('getInitialProps run count: 1') - - await browser.close() - }) - - it('should run getInitialProps always when rending the page to the screen', async () => { - const browser = await webdriver(context.appPort, '/nav/shallow-routing') - - const counter = await browser - .elementByCss('#increase').click() - .elementByCss('#increase').click() - .elementByCss('#home-link').click() - .waitForElementByCss('.nav-home') - .back() - .waitForElementByCss('.shallow-routing') - .elementByCss('#counter').text() - expect(counter).toBe('Counter: 2') - - const getInitialPropsRunCount = await browser - .elementByCss('#get-initial-props-run-count').text() - expect(getInitialPropsRunCount).toBe('getInitialProps run count: 2') - - await browser.close() - }) - }) - - describe('with URL objects', () => { - it('should work with ', async () => { - const browser = await webdriver(context.appPort, '/nav') - const text = await browser - .elementByCss('#query-string-link').click() - .waitForElementByCss('.nav-querystring') - .elementByCss('p').text() - expect(text).toBe('10') - - expect(await browser.url()) - .toBe(`http://localhost:${context.appPort}/nav/querystring/10#10`) - await browser.close() - }) - - it('should work with "Router.push"', async () => { - const browser = await webdriver(context.appPort, '/nav') - const text = await browser - .elementByCss('#query-string-button').click() - .waitForElementByCss('.nav-querystring') - .elementByCss('p').text() - expect(text).toBe('10') - - expect(await browser.url()) - .toBe(`http://localhost:${context.appPort}/nav/querystring/10#10`) - await browser.close() - }) - - it('should work with the "replace" prop', async () => { - const browser = await webdriver(context.appPort, '/nav') - - let stackLength = await browser - .eval('window.history.length') - - expect(stackLength).toBe(2) - - // Navigation to /about using a replace link should maintain the url stack length - const text = await browser - .elementByCss('#about-replace-link').click() - .waitForElementByCss('.nav-about') - .elementByCss('p').text() - - expect(text).toBe('This is the about page.') - - stackLength = await browser - .eval('window.history.length') - - expect(stackLength).toBe(2) - - // Going back to the home with a regular link will augment the history count - await browser - .elementByCss('#home-link').click() - .waitForElementByCss('.nav-home') - - stackLength = await browser - .eval('window.history.length') - - expect(stackLength).toBe(3) - - await browser.close() - }) - }) - - describe('with getInitialProp redirect', () => { - it('should redirect the page via client side', async () => { - const browser = await webdriver(context.appPort, '/nav') - const text = await browser - .elementByCss('#redirect-link').click() - .waitForElementByCss('.nav-about') - .elementByCss('p').text() - - expect(text).toBe('This is the about page.') - await browser.close() - }) - - it('should redirect the page when loading', async () => { - const browser = await webdriver(context.appPort, '/nav/redirect') - const text = await browser - .waitForElementByCss('.nav-about') - .elementByCss('p').text() - - expect(text).toBe('This is the about page.') - await browser.close() - }) - }) - - describe('with different types of urls', () => { - it('should work with normal page', async () => { - const browser = await webdriver(context.appPort, '/with-cdm') - const text = await browser.elementByCss('p').text() - - expect(text).toBe('ComponentDidMount executed on client.') - await browser.close() - }) - - it('should work with dir/ page', async () => { - const browser = await webdriver(context.appPort, '/nested-cdm') - const text = await browser.elementByCss('p').text() - - expect(text).toBe('ComponentDidMount executed on client.') - await browser.close() - }) - - it('should work with /index page', async () => { - const browser = await webdriver(context.appPort, '/index') - const text = await browser.elementByCss('p').text() - - expect(text).toBe('ComponentDidMount executed on client.') - await browser.close() - }) - - it('should work with / page', async () => { - const browser = await webdriver(context.appPort, '/') - const text = await browser.elementByCss('p').text() - - expect(text).toBe('ComponentDidMount executed on client.') - await browser.close() - }) - }) - - describe('with the HOC based router', () => { - it('should navigate as expected', async () => { - const browser = await webdriver(context.appPort, '/nav/with-hoc') - - const pathname = await browser.elementByCss('#pathname').text() - expect(pathname).toBe('Current path: /nav/with-hoc') - - const asPath = await browser.elementByCss('#asPath').text() - expect(asPath).toBe('Current asPath: /nav/with-hoc') - - const text = await browser - .elementByCss('.nav-with-hoc a').click() - .waitForElementByCss('.nav-home') - .elementByCss('p').text() - - expect(text).toBe('This is the home.') - await browser.close() - }) - }) - - describe('with asPath', () => { - describe('inside getInitialProps', () => { - it('should show the correct asPath with a Link with as prop', async () => { - const browser = await webdriver(context.appPort, '/nav') - const asPath = await browser - .elementByCss('#as-path-link').click() - .waitForElementByCss('.as-path-content') - .elementByCss('.as-path-content').text() - - expect(asPath).toBe('/as/path') - await browser.close() - }) - - it('should show the correct asPath with a Link without the as prop', async () => { - const browser = await webdriver(context.appPort, '/nav') - const asPath = await browser - .elementByCss('#as-path-link-no-as').click() - .waitForElementByCss('.as-path-content') - .elementByCss('.as-path-content').text() - - expect(asPath).toBe('/nav/as-path') - await browser.close() - }) - }) - - describe('with next/router', () => { - it('should show the correct asPath', async () => { - const browser = await webdriver(context.appPort, '/nav') - const asPath = await browser - .elementByCss('#as-path-using-router-link').click() - .waitForElementByCss('.as-path-content') - .elementByCss('.as-path-content').text() - - expect(asPath).toBe('/nav/as-path-using-router') - await browser.close() - }) - }) - - describe('with next/link', () => { - it('should use pushState with same href and different asPath', async () => { - let browser - try { - browser = await webdriver(context.appPort, '/nav/as-path-pushstate') - await browser.elementByCss('#hello').click().waitForElementByCss('#something-hello') - const queryOne = JSON.parse(await browser.elementByCss('#router-query').text()) - expect(queryOne.something).toBe('hello') - await browser.elementByCss('#same-query').click().waitForElementByCss('#something-same-query') - const queryTwo = JSON.parse(await browser.elementByCss('#router-query').text()) - expect(queryTwo.something).toBe('hello') - await browser.back().waitForElementByCss('#something-hello') - const queryThree = JSON.parse(await browser.elementByCss('#router-query').text()) - expect(queryThree.something).toBe('hello') - await browser.elementByCss('#else').click().waitForElementByCss('#something-else') - await browser.elementByCss('#hello2').click().waitForElementByCss('#nav-as-path-pushstate') - await browser.back().waitForElementByCss('#something-else') - const queryFour = JSON.parse(await browser.elementByCss('#router-query').text()) - expect(queryFour.something).toBe(undefined) - } finally { - if (browser) { - await browser.close() - } - } - }) - - it('should detect asPath query changes correctly', async () => { - let browser - try { - browser = await webdriver(context.appPort, '/nav/as-path-query') - await browser.elementByCss('#hello').click().waitForElementByCss('#something-hello-something-hello') - const queryOne = JSON.parse(await browser.elementByCss('#router-query').text()) - expect(queryOne.something).toBe('hello') - await browser.elementByCss('#hello2').click().waitForElementByCss('#something-hello-something-else') - const queryTwo = JSON.parse(await browser.elementByCss('#router-query').text()) - expect(queryTwo.something).toBe('else') - } finally { - if (browser) { - await browser.close() - } - } - }) - }) - }) - - describe('runtime errors', () => { - it('should show react-error-overlay when a client side error is thrown inside a component', async () => { - let browser - try { - browser = await webdriver(context.appPort, '/error-inside-browser-page') - await waitFor(3000) - const text = await getReactErrorOverlayContent(browser) - expect(text).toMatch(/An Expected error occurred/) - expect(text).toMatch(/pages\/error-inside-browser-page\.js:5/) - } finally { - if (browser) { - await browser.close() - } - } - }) - - it('should show react-error-overlay when a client side error is thrown outside a component', async () => { - let browser - try { - browser = await webdriver(context.appPort, '/error-in-the-browser-global-scope') - await waitFor(3000) - const text = await getReactErrorOverlayContent(browser) - expect(text).toMatch(/An Expected error occurred/) - expect(text).toMatch(/error-in-the-browser-global-scope\.js:2/) - } finally { - if (browser) { - await browser.close() - } - } - }) - }) - - describe('with 404 pages', () => { - it('should 404 on not existent page', async () => { - const browser = await webdriver(context.appPort, '/non-existent') - expect(await browser.elementByCss('h1').text()).toBe('404') - expect(await browser.elementByCss('h2').text()).toBe('This page could not be found.') - await browser.close() - }) - - it('should 404 for /', async () => { - const browser = await webdriver(context.appPort, '/nav/about/') - expect(await browser.elementByCss('h1').text()).toBe('404') - expect(await browser.elementByCss('h2').text()).toBe('This page could not be found.') - await browser.close() - }) - - it('should should not contain a page script in a 404 page', async () => { - const browser = await webdriver(context.appPort, '/non-existent') - const scripts = await browser.elementsByCss('script[src]') - for (const script of scripts) { - const src = await script.getAttribute('src') - expect(src.includes('/non-existent')).toBeFalsy() - } - await browser.close() - }) - }) - - describe('updating head while client routing', () => { - it('should update head during client routing', async () => { - let browser - try { - browser = await webdriver(context.appPort, '/nav/head-1') - expect(await browser.elementByCss('meta[name="description"]').getAttribute('content')).toBe('Head One') - await browser.elementByCss('#to-head-2').click().waitForElementByCss('#head-2') - expect(await browser.elementByCss('meta[name="description"]').getAttribute('content')).toBe('Head Two') - await browser.elementByCss('#to-head-1').click().waitForElementByCss('#head-1') - expect(await browser.elementByCss('meta[name="description"]').getAttribute('content')).toBe('Head One') - } finally { - if (browser) { - await browser.close() - } - } - }) - }) - - it('should not error on module.exports + polyfills', async () => { - let browser - try { - browser = await webdriver(context.appPort, '/read-only-object-error') - expect(await browser.elementByCss('body').text()).toBe('this is just a placeholder component') - } finally { - if (browser) { - await browser.close() - } - } - }) - - it('should work on nested /index/index.js', async () => { - const browser = await webdriver(context.appPort, '/nested-index/index') - expect(await browser.elementByCss('p').text()).toBe('This is an index.js nested in an index/ folder.') - await browser.close() - }) - }) -} diff --git a/test/integration/basic/test/index.test.js b/test/integration/basic/test/index.test.js index 0c01551989..7db1cd4cec 100644 --- a/test/integration/basic/test/index.test.js +++ b/test/integration/basic/test/index.test.js @@ -3,15 +3,12 @@ import { join } from 'path' import { renderViaHTTP, - fetchViaHTTP, findPort, launchApp, killApp } from 'next-test-utils' // test suits -import rendering from './rendering' -import clientNavigation from './client-navigation' import hmr from './hmr' import errorRecovery from './error-recovery' import dynamic from './dynamic' @@ -27,37 +24,8 @@ describe('Basic Features', () => { // pre-build all pages at the start await Promise.all([ - renderViaHTTP(context.appPort, '/async-props'), - renderViaHTTP(context.appPort, '/default-head'), - renderViaHTTP(context.appPort, '/empty-get-initial-props'), - renderViaHTTP(context.appPort, '/error'), - renderViaHTTP(context.appPort, '/finish-response'), - renderViaHTTP(context.appPort, '/head'), - renderViaHTTP(context.appPort, '/json'), - renderViaHTTP(context.appPort, '/link'), - renderViaHTTP(context.appPort, '/stateless'), - renderViaHTTP(context.appPort, '/fragment-syntax'), - renderViaHTTP(context.appPort, '/custom-extension'), - renderViaHTTP(context.appPort, '/styled-jsx'), - renderViaHTTP(context.appPort, '/with-cdm'), - renderViaHTTP(context.appPort, '/url-prop'), - renderViaHTTP(context.appPort, '/url-prop-override'), renderViaHTTP(context.appPort, '/process-env'), - renderViaHTTP(context.appPort, '/nav'), - renderViaHTTP(context.appPort, '/nav/about'), - renderViaHTTP(context.appPort, '/nav/on-click'), - renderViaHTTP(context.appPort, '/nav/querystring'), - renderViaHTTP(context.appPort, '/nav/self-reload'), - renderViaHTTP(context.appPort, '/nav/hash-changes'), - renderViaHTTP(context.appPort, '/nav/shallow-routing'), - renderViaHTTP(context.appPort, '/nav/redirect'), - renderViaHTTP(context.appPort, '/nav/as-path'), - renderViaHTTP(context.appPort, '/nav/as-path-using-router'), - renderViaHTTP(context.appPort, '/nav/url-prop-change'), - - renderViaHTTP(context.appPort, '/nested-cdm/index'), - renderViaHTTP(context.appPort, '/hmr/about'), renderViaHTTP(context.appPort, '/hmr/style'), renderViaHTTP(context.appPort, '/hmr/contact'), @@ -66,8 +34,6 @@ describe('Basic Features', () => { }) afterAll(() => killApp(context.server)) - rendering(context, 'Rendering via HTTP', (p, q) => renderViaHTTP(context.appPort, p, q), (p, q) => fetchViaHTTP(context.appPort, p, q)) - clientNavigation(context, (p, q) => renderViaHTTP(context.appPort, p, q)) dynamic(context, (p, q) => renderViaHTTP(context.appPort, p, q)) hmr(context, (p, q) => renderViaHTTP(context.appPort, p, q)) errorRecovery(context, (p, q) => renderViaHTTP(context.appPort, p, q)) diff --git a/test/integration/basic/components/hello.jsx b/test/integration/client-navigation/components/hello.jsx similarity index 100% rename from test/integration/basic/components/hello.jsx rename to test/integration/client-navigation/components/hello.jsx diff --git a/test/integration/client-navigation/components/hello1.js b/test/integration/client-navigation/components/hello1.js new file mode 100644 index 0000000000..a896f64f5c --- /dev/null +++ b/test/integration/client-navigation/components/hello1.js @@ -0,0 +1,3 @@ +export default () => ( +

Hello World 1

+) diff --git a/test/integration/basic/components/world.jsx b/test/integration/client-navigation/components/world.jsx similarity index 100% rename from test/integration/basic/components/world.jsx rename to test/integration/client-navigation/components/world.jsx diff --git a/test/integration/basic/lib/async-function.js b/test/integration/client-navigation/lib/async-function.js similarity index 100% rename from test/integration/basic/lib/async-function.js rename to test/integration/client-navigation/lib/async-function.js diff --git a/test/integration/basic/lib/cdm.js b/test/integration/client-navigation/lib/cdm.js similarity index 100% rename from test/integration/basic/lib/cdm.js rename to test/integration/client-navigation/lib/cdm.js diff --git a/test/integration/basic/lib/data.json b/test/integration/client-navigation/lib/data.json similarity index 100% rename from test/integration/basic/lib/data.json rename to test/integration/client-navigation/lib/data.json diff --git a/test/integration/client-navigation/next.config.js b/test/integration/client-navigation/next.config.js new file mode 100644 index 0000000000..35dcf0f6b8 --- /dev/null +++ b/test/integration/client-navigation/next.config.js @@ -0,0 +1,6 @@ +module.exports = { + onDemandEntries: { + // Make sure entries are not getting disposed. + maxInactiveAge: 1000 * 60 * 60 + } +} diff --git a/test/integration/basic/pages/async-props.js b/test/integration/client-navigation/pages/async-props.js similarity index 100% rename from test/integration/basic/pages/async-props.js rename to test/integration/client-navigation/pages/async-props.js diff --git a/test/integration/basic/pages/circular-json-error.js b/test/integration/client-navigation/pages/circular-json-error.js similarity index 100% rename from test/integration/basic/pages/circular-json-error.js rename to test/integration/client-navigation/pages/circular-json-error.js diff --git a/test/integration/basic/pages/custom-encoding.js b/test/integration/client-navigation/pages/custom-encoding.js similarity index 100% rename from test/integration/basic/pages/custom-encoding.js rename to test/integration/client-navigation/pages/custom-encoding.js diff --git a/test/integration/basic/pages/custom-extension.jsx b/test/integration/client-navigation/pages/custom-extension.jsx similarity index 100% rename from test/integration/basic/pages/custom-extension.jsx rename to test/integration/client-navigation/pages/custom-extension.jsx diff --git a/test/integration/basic/pages/default-head.js b/test/integration/client-navigation/pages/default-head.js similarity index 100% rename from test/integration/basic/pages/default-head.js rename to test/integration/client-navigation/pages/default-head.js diff --git a/test/integration/client-navigation/pages/dynamic/ssr.js b/test/integration/client-navigation/pages/dynamic/ssr.js new file mode 100644 index 0000000000..6bec25ce24 --- /dev/null +++ b/test/integration/client-navigation/pages/dynamic/ssr.js @@ -0,0 +1,5 @@ +import dynamic from 'next/dynamic' + +const Hello = dynamic(import('../../components/hello1')) + +export default Hello diff --git a/test/integration/basic/pages/empty-get-initial-props.js b/test/integration/client-navigation/pages/empty-get-initial-props.js similarity index 100% rename from test/integration/basic/pages/empty-get-initial-props.js rename to test/integration/client-navigation/pages/empty-get-initial-props.js diff --git a/test/integration/basic/pages/error-in-the-browser-global-scope.js b/test/integration/client-navigation/pages/error-in-the-browser-global-scope.js similarity index 100% rename from test/integration/basic/pages/error-in-the-browser-global-scope.js rename to test/integration/client-navigation/pages/error-in-the-browser-global-scope.js diff --git a/test/integration/basic/pages/error-in-the-global-scope.js b/test/integration/client-navigation/pages/error-in-the-global-scope.js similarity index 100% rename from test/integration/basic/pages/error-in-the-global-scope.js rename to test/integration/client-navigation/pages/error-in-the-global-scope.js diff --git a/test/integration/basic/pages/error-inside-browser-page.js b/test/integration/client-navigation/pages/error-inside-browser-page.js similarity index 100% rename from test/integration/basic/pages/error-inside-browser-page.js rename to test/integration/client-navigation/pages/error-inside-browser-page.js diff --git a/test/integration/basic/pages/error-inside-page.js b/test/integration/client-navigation/pages/error-inside-page.js similarity index 100% rename from test/integration/basic/pages/error-inside-page.js rename to test/integration/client-navigation/pages/error-inside-page.js diff --git a/test/integration/basic/pages/exports.js b/test/integration/client-navigation/pages/exports.js similarity index 100% rename from test/integration/basic/pages/exports.js rename to test/integration/client-navigation/pages/exports.js diff --git a/test/integration/basic/pages/forwardRef-component.js b/test/integration/client-navigation/pages/forwardRef-component.js similarity index 100% rename from test/integration/basic/pages/forwardRef-component.js rename to test/integration/client-navigation/pages/forwardRef-component.js diff --git a/test/integration/basic/pages/fragment-syntax.js b/test/integration/client-navigation/pages/fragment-syntax.js similarity index 100% rename from test/integration/basic/pages/fragment-syntax.js rename to test/integration/client-navigation/pages/fragment-syntax.js diff --git a/test/integration/basic/pages/head.js b/test/integration/client-navigation/pages/head.js similarity index 100% rename from test/integration/basic/pages/head.js rename to test/integration/client-navigation/pages/head.js diff --git a/test/integration/basic/pages/index.js b/test/integration/client-navigation/pages/index.js similarity index 100% rename from test/integration/basic/pages/index.js rename to test/integration/client-navigation/pages/index.js diff --git a/test/integration/basic/pages/instance-get-initial-props.js b/test/integration/client-navigation/pages/instance-get-initial-props.js similarity index 100% rename from test/integration/basic/pages/instance-get-initial-props.js rename to test/integration/client-navigation/pages/instance-get-initial-props.js diff --git a/test/integration/basic/pages/json.js b/test/integration/client-navigation/pages/json.js similarity index 100% rename from test/integration/basic/pages/json.js rename to test/integration/client-navigation/pages/json.js diff --git a/test/integration/basic/pages/link.js b/test/integration/client-navigation/pages/link.js similarity index 100% rename from test/integration/basic/pages/link.js rename to test/integration/client-navigation/pages/link.js diff --git a/test/integration/basic/pages/memo-component.js b/test/integration/client-navigation/pages/memo-component.js similarity index 100% rename from test/integration/basic/pages/memo-component.js rename to test/integration/client-navigation/pages/memo-component.js diff --git a/test/integration/basic/pages/nav/about.js b/test/integration/client-navigation/pages/nav/about.js similarity index 100% rename from test/integration/basic/pages/nav/about.js rename to test/integration/client-navigation/pages/nav/about.js diff --git a/test/integration/basic/pages/nav/as-path-pushstate.js b/test/integration/client-navigation/pages/nav/as-path-pushstate.js similarity index 100% rename from test/integration/basic/pages/nav/as-path-pushstate.js rename to test/integration/client-navigation/pages/nav/as-path-pushstate.js diff --git a/test/integration/basic/pages/nav/as-path-query.js b/test/integration/client-navigation/pages/nav/as-path-query.js similarity index 100% rename from test/integration/basic/pages/nav/as-path-query.js rename to test/integration/client-navigation/pages/nav/as-path-query.js diff --git a/test/integration/basic/pages/nav/as-path-using-router.js b/test/integration/client-navigation/pages/nav/as-path-using-router.js similarity index 100% rename from test/integration/basic/pages/nav/as-path-using-router.js rename to test/integration/client-navigation/pages/nav/as-path-using-router.js diff --git a/test/integration/basic/pages/nav/as-path.js b/test/integration/client-navigation/pages/nav/as-path.js similarity index 100% rename from test/integration/basic/pages/nav/as-path.js rename to test/integration/client-navigation/pages/nav/as-path.js diff --git a/test/integration/basic/pages/nav/hash-changes.js b/test/integration/client-navigation/pages/nav/hash-changes.js similarity index 100% rename from test/integration/basic/pages/nav/hash-changes.js rename to test/integration/client-navigation/pages/nav/hash-changes.js diff --git a/test/integration/basic/pages/nav/head-1.js b/test/integration/client-navigation/pages/nav/head-1.js similarity index 100% rename from test/integration/basic/pages/nav/head-1.js rename to test/integration/client-navigation/pages/nav/head-1.js diff --git a/test/integration/basic/pages/nav/head-2.js b/test/integration/client-navigation/pages/nav/head-2.js similarity index 100% rename from test/integration/basic/pages/nav/head-2.js rename to test/integration/client-navigation/pages/nav/head-2.js diff --git a/test/integration/basic/pages/nav/index.js b/test/integration/client-navigation/pages/nav/index.js similarity index 100% rename from test/integration/basic/pages/nav/index.js rename to test/integration/client-navigation/pages/nav/index.js diff --git a/test/integration/basic/pages/nav/on-click.js b/test/integration/client-navigation/pages/nav/on-click.js similarity index 100% rename from test/integration/basic/pages/nav/on-click.js rename to test/integration/client-navigation/pages/nav/on-click.js diff --git a/test/integration/basic/pages/nav/pass-href-prop.js b/test/integration/client-navigation/pages/nav/pass-href-prop.js similarity index 100% rename from test/integration/basic/pages/nav/pass-href-prop.js rename to test/integration/client-navigation/pages/nav/pass-href-prop.js diff --git a/test/integration/basic/pages/nav/querystring.js b/test/integration/client-navigation/pages/nav/querystring.js similarity index 100% rename from test/integration/basic/pages/nav/querystring.js rename to test/integration/client-navigation/pages/nav/querystring.js diff --git a/test/integration/basic/pages/nav/redirect.js b/test/integration/client-navigation/pages/nav/redirect.js similarity index 100% rename from test/integration/basic/pages/nav/redirect.js rename to test/integration/client-navigation/pages/nav/redirect.js diff --git a/test/integration/basic/pages/nav/self-reload.js b/test/integration/client-navigation/pages/nav/self-reload.js similarity index 100% rename from test/integration/basic/pages/nav/self-reload.js rename to test/integration/client-navigation/pages/nav/self-reload.js diff --git a/test/integration/basic/pages/nav/shallow-routing.js b/test/integration/client-navigation/pages/nav/shallow-routing.js similarity index 100% rename from test/integration/basic/pages/nav/shallow-routing.js rename to test/integration/client-navigation/pages/nav/shallow-routing.js diff --git a/test/integration/basic/pages/nav/url-prop-change.js b/test/integration/client-navigation/pages/nav/url-prop-change.js similarity index 100% rename from test/integration/basic/pages/nav/url-prop-change.js rename to test/integration/client-navigation/pages/nav/url-prop-change.js diff --git a/test/integration/basic/pages/nav/with-hoc.js b/test/integration/client-navigation/pages/nav/with-hoc.js similarity index 100% rename from test/integration/basic/pages/nav/with-hoc.js rename to test/integration/client-navigation/pages/nav/with-hoc.js diff --git a/test/integration/basic/pages/nested-cdm/index.js b/test/integration/client-navigation/pages/nested-cdm/index.js similarity index 100% rename from test/integration/basic/pages/nested-cdm/index.js rename to test/integration/client-navigation/pages/nested-cdm/index.js diff --git a/test/integration/basic/pages/nested-index/index/index.js b/test/integration/client-navigation/pages/nested-index/index/index.js similarity index 100% rename from test/integration/basic/pages/nested-index/index/index.js rename to test/integration/client-navigation/pages/nested-index/index/index.js diff --git a/test/integration/basic/pages/no-default-export.js b/test/integration/client-navigation/pages/no-default-export.js similarity index 100% rename from test/integration/basic/pages/no-default-export.js rename to test/integration/client-navigation/pages/no-default-export.js diff --git a/test/integration/basic/pages/read-only-object-error.js b/test/integration/client-navigation/pages/read-only-object-error.js similarity index 100% rename from test/integration/basic/pages/read-only-object-error.js rename to test/integration/client-navigation/pages/read-only-object-error.js diff --git a/test/integration/basic/pages/stateless.js b/test/integration/client-navigation/pages/stateless.js similarity index 100% rename from test/integration/basic/pages/stateless.js rename to test/integration/client-navigation/pages/stateless.js diff --git a/test/integration/basic/pages/styled-jsx.js b/test/integration/client-navigation/pages/styled-jsx.js similarity index 100% rename from test/integration/basic/pages/styled-jsx.js rename to test/integration/client-navigation/pages/styled-jsx.js diff --git a/test/integration/basic/pages/throw-undefined.js b/test/integration/client-navigation/pages/throw-undefined.js similarity index 82% rename from test/integration/basic/pages/throw-undefined.js rename to test/integration/client-navigation/pages/throw-undefined.js index 6309859fb7..b129f35a15 100644 --- a/test/integration/basic/pages/throw-undefined.js +++ b/test/integration/client-navigation/pages/throw-undefined.js @@ -8,4 +8,4 @@ ThrowUndefined.getInitialProps = () => { throw undefined } -export default ThrowUndefined \ No newline at end of file +export default ThrowUndefined diff --git a/test/integration/basic/pages/url-prop-override.js b/test/integration/client-navigation/pages/url-prop-override.js similarity index 100% rename from test/integration/basic/pages/url-prop-override.js rename to test/integration/client-navigation/pages/url-prop-override.js diff --git a/test/integration/basic/pages/url-prop.js b/test/integration/client-navigation/pages/url-prop.js similarity index 100% rename from test/integration/basic/pages/url-prop.js rename to test/integration/client-navigation/pages/url-prop.js diff --git a/test/integration/basic/pages/with-cdm.js b/test/integration/client-navigation/pages/with-cdm.js similarity index 100% rename from test/integration/basic/pages/with-cdm.js rename to test/integration/client-navigation/pages/with-cdm.js diff --git a/test/integration/client-navigation/test/index.test.js b/test/integration/client-navigation/test/index.test.js new file mode 100644 index 0000000000..6ec4ffab08 --- /dev/null +++ b/test/integration/client-navigation/test/index.test.js @@ -0,0 +1,830 @@ +/* eslint-env jest */ +/* global jasmine */ +import { join } from 'path' +import webdriver from 'next-webdriver' +import renderingSuite from './rendering' +import { + waitFor, + findPort, + killApp, + launchApp, + fetchViaHTTP, + renderViaHTTP, + getReactErrorOverlayContent +} from 'next-test-utils' + +const context = {} +jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 60 * 5 + +describe('Client Navigation', () => { + beforeAll(async () => { + context.appPort = await findPort() + context.server = await launchApp(join(__dirname, '../'), context.appPort) + + const prerender = [ + '/async-props', + '/default-head', + '/empty-get-initial-props', + '/error', + '/finish-response', + '/head', + '/json', + '/link', + '/stateless', + '/fragment-syntax', + '/custom-extension', + '/styled-jsx', + '/with-cdm', + '/url-prop', + '/url-prop-override', + + '/dynamic/ssr', + + '/nav', + '/nav/about', + '/nav/on-click', + '/nav/querystring', + '/nav/self-reload', + '/nav/hash-changes', + '/nav/shallow-routing', + '/nav/redirect', + '/nav/as-path', + '/nav/as-path-using-router', + '/nav/url-prop-change', + + '/nested-cdm/index' + ] + await Promise.all(prerender.map(route => renderViaHTTP(context.appPort, route))) + }) + afterAll(() => killApp(context.server)) + + describe('with ', () => { + it('should navigate the page', async () => { + const browser = await webdriver(context.appPort, '/nav') + const text = await browser + .elementByCss('#about-link').click() + .waitForElementByCss('.nav-about') + .elementByCss('p').text() + + expect(text).toBe('This is the about page.') + await browser.close() + }) + + it('should navigate via the client side', async () => { + const browser = await webdriver(context.appPort, '/nav') + + const counterText = await browser + .elementByCss('#increase').click() + .elementByCss('#about-link').click() + .waitForElementByCss('.nav-about') + .elementByCss('#home-link').click() + .waitForElementByCss('.nav-home') + .elementByCss('#counter').text() + + expect(counterText).toBe('Counter: 1') + await browser.close() + }) + }) + + describe('With url property', () => { + it('Should keep immutable pathname, asPath and query', async () => { + const browser = await webdriver(context.appPort, '/nav/url-prop-change') + await browser.elementByCss('#add-query').click() + const urlResult = await browser.elementByCss('#url-result').text() + const previousUrlResult = await browser.elementByCss('#previous-url-result').text() + + expect(JSON.parse(urlResult)).toMatchObject({ 'query': { 'added': 'yes' }, 'pathname': '/nav/url-prop-change', 'asPath': '/nav/url-prop-change?added=yes' }) + expect(JSON.parse(previousUrlResult)).toMatchObject({ 'query': {}, 'pathname': '/nav/url-prop-change', 'asPath': '/nav/url-prop-change' }) + + await browser.close() + }) + }) + + describe('with
tag inside the ', () => { + it('should navigate the page', async () => { + const browser = await webdriver(context.appPort, '/nav/about') + const text = await browser + .elementByCss('#home-link').click() + .waitForElementByCss('.nav-home') + .elementByCss('p').text() + + expect(text).toBe('This is the home.') + await browser.close() + }) + + it('should not navigate if the tag has a target', async () => { + const browser = await webdriver(context.appPort, '/nav') + + const counterText = await browser + .elementByCss('#increase').click() + .elementByCss('#target-link').click() + .elementByCss('#counter').text() + + expect(counterText).toBe('Counter: 1') + await browser.close() + }) + }) + + describe('with unexpected nested tag', () => { + it('should not redirect if passHref prop is not defined in Link', async () => { + const browser = await webdriver(context.appPort, '/nav/pass-href-prop') + const text = await browser + .elementByCss('#without-href').click() + .waitForElementByCss('.nav-pass-href-prop') + .elementByCss('p').text() + + expect(text).toBe('This is the passHref prop page.') + await browser.close() + }) + + it('should redirect if passHref prop is defined in Link', async () => { + const browser = await webdriver(context.appPort, '/nav/pass-href-prop') + const text = await browser + .elementByCss('#with-href').click() + .waitForElementByCss('.nav-home') + .elementByCss('p').text() + + expect(text).toBe('This is the home.') + await browser.close() + }) + }) + + describe('with empty getInitialProps()', () => { + it('should render an error', async () => { + let browser + try { + browser = await webdriver(context.appPort, '/nav') + await browser.elementByCss('#empty-props').click() + + await waitFor(3000) + + expect(await getReactErrorOverlayContent(browser)).toMatch( + /should resolve to an object\. But found "null" instead\./ + ) + } finally { + if (browser) { + await browser.close() + } + } + }) + }) + + describe('with the same page but different querystring', () => { + it('should navigate the page', async () => { + const browser = await webdriver(context.appPort, '/nav/querystring?id=1') + const text = await browser + .elementByCss('#next-id-link').click() + .waitForElementByCss('.nav-id-2') + .elementByCss('p').text() + + expect(text).toBe('2') + await browser.close() + }) + + it('should remove querystring', async () => { + const browser = await webdriver(context.appPort, '/nav/querystring?id=1') + const text = await browser + .elementByCss('#main-page').click() + .waitForElementByCss('.nav-id-0') + .elementByCss('p').text() + + expect(text).toBe('0') + await browser.close() + }) + }) + + describe('with the current url', () => { + it('should reload the page', async () => { + const browser = await webdriver(context.appPort, '/nav/self-reload') + const defaultCount = await browser.elementByCss('p').text() + expect(defaultCount).toBe('COUNT: 0') + + const countAfterClicked = await browser + .elementByCss('#self-reload-link').click() + .elementByCss('p').text() + + expect(countAfterClicked).toBe('COUNT: 1') + await browser.close() + }) + + it('should always replace the state', async () => { + const browser = await webdriver(context.appPort, '/nav') + + const countAfterClicked = await browser + .elementByCss('#self-reload-link').click() + .waitForElementByCss('#self-reload-page') + .elementByCss('#self-reload-link').click() + .elementByCss('#self-reload-link').click() + .elementByCss('p').text() + + // counts (page change + two clicks) + expect(countAfterClicked).toBe('COUNT: 3') + + // Since we replace the state, back button would simply go us back to /nav + await browser + .back() + .waitForElementByCss('.nav-home') + + await browser.close() + }) + }) + + describe('with onClick action', () => { + it('should reload the page and perform additional action', async () => { + let browser + try { + browser = await webdriver(context.appPort, '/nav/on-click') + const defaultCountQuery = await browser.elementByCss('#query-count').text() + const defaultCountState = await browser.elementByCss('#state-count').text() + expect(defaultCountQuery).toBe('QUERY COUNT: 0') + expect(defaultCountState).toBe('STATE COUNT: 0') + + await browser.elementByCss('#on-click-link').click() + + const countQueryAfterClicked = await browser.elementByCss('#query-count').text() + const countStateAfterClicked = await browser.elementByCss('#state-count').text() + expect(countQueryAfterClicked).toBe('QUERY COUNT: 1') + expect(countStateAfterClicked).toBe('STATE COUNT: 1') + } finally { + if (browser) { + await browser.close() + } + } + }) + + it('should not reload if default was prevented', async () => { + let browser + try { + browser = await webdriver(context.appPort, '/nav/on-click') + const defaultCountQuery = await browser.elementByCss('#query-count').text() + const defaultCountState = await browser.elementByCss('#state-count').text() + expect(defaultCountQuery).toBe('QUERY COUNT: 0') + expect(defaultCountState).toBe('STATE COUNT: 0') + + await browser.elementByCss('#on-click-link-prevent-default').click() + + const countQueryAfterClicked = await browser.elementByCss('#query-count').text() + const countStateAfterClicked = await browser.elementByCss('#state-count').text() + expect(countQueryAfterClicked).toBe('QUERY COUNT: 0') + expect(countStateAfterClicked).toBe('STATE COUNT: 1') + + await browser.elementByCss('#on-click-link').click() + + const countQueryAfterClickedAgain = await browser.elementByCss('#query-count').text() + const countStateAfterClickedAgain = await browser.elementByCss('#state-count').text() + expect(countQueryAfterClickedAgain).toBe('QUERY COUNT: 1') + expect(countStateAfterClickedAgain).toBe('STATE COUNT: 2') + } finally { + if (browser) { + await browser.close() + } + } + }) + + it('should always replace the state and perform additional action', async () => { + let browser + try { + browser = await webdriver(context.appPort, '/nav') + + await browser.elementByCss('#on-click-link').click().waitForElementByCss('#on-click-page') + + const defaultCountQuery = await browser.elementByCss('#query-count').text() + expect(defaultCountQuery).toBe('QUERY COUNT: 1') + + await browser.elementByCss('#on-click-link').click() + const countQueryAfterClicked = await browser.elementByCss('#query-count').text() + const countStateAfterClicked = await browser.elementByCss('#state-count').text() + expect(countQueryAfterClicked).toBe('QUERY COUNT: 2') + expect(countStateAfterClicked).toBe('STATE COUNT: 1') + + // Since we replace the state, back button would simply go us back to /nav + await browser.back().waitForElementByCss('.nav-home') + } finally { + if (browser) { + await browser.close() + } + } + }) + }) + + describe('with hash changes', () => { + describe('when hash change via Link', () => { + it('should not run getInitialProps', async () => { + const browser = await webdriver(context.appPort, '/nav/hash-changes') + + const counter = await browser + .elementByCss('#via-link').click() + .elementByCss('p').text() + + expect(counter).toBe('COUNT: 0') + + await browser.close() + }) + + it('should scroll to the specified position on the same page', async () => { + let browser + try { + browser = await webdriver(context.appPort, '/nav/hash-changes') + + // Scrolls to item 400 on the page + const scrollPosition = await browser + .elementByCss('#scroll-to-item-400').click() + .eval('window.pageYOffset') + + expect(scrollPosition).toBe(7258) + + // Scrolls back to top when scrolling to `#` with no value. + const scrollPositionAfterEmptyHash = await browser + .elementByCss('#via-empty-hash').click() + .eval('window.pageYOffset') + + expect(scrollPositionAfterEmptyHash).toBe(0) + } finally { + if (browser) { + await browser.close() + } + } + }) + + it('should scroll to the specified position on the same page with a name property', async () => { + let browser + try { + browser = await webdriver(context.appPort, '/nav/hash-changes') + + // Scrolls to item 400 with name="name-item-400" on the page + const scrollPosition = await browser + .elementByCss('#scroll-to-name-item-400').click() + .eval('window.pageYOffset') + + console.log(scrollPosition) + + expect(scrollPosition).toBe(16258) + + // Scrolls back to top when scrolling to `#` with no value. + const scrollPositionAfterEmptyHash = await browser + .elementByCss('#via-empty-hash').click() + .eval('window.pageYOffset') + + expect(scrollPositionAfterEmptyHash).toBe(0) + } finally { + if (browser) { + await browser.close() + } + } + }) + + it('should scroll to the specified position to a new page', async () => { + let browser + try { + browser = await webdriver(context.appPort, '/nav') + + // Scrolls to item 400 on the page + await browser + .elementByCss('#scroll-to-hash').click() + .waitForElementByCss('#hash-changes-page') + + const scrollPosition = await browser.eval('window.pageYOffset') + expect(scrollPosition).toBe(7258) + } finally { + if (browser) { + await browser.close() + } + } + }) + }) + + describe('when hash change via A tag', () => { + it('should not run getInitialProps', async () => { + const browser = await webdriver(context.appPort, '/nav/hash-changes') + + const counter = await browser + .elementByCss('#via-a').click() + .elementByCss('p').text() + + expect(counter).toBe('COUNT: 0') + + await browser.close() + }) + }) + + describe('when hash get removed', () => { + it('should not run getInitialProps', async () => { + const browser = await webdriver(context.appPort, '/nav/hash-changes') + + const counter = await browser + .elementByCss('#via-a').click() + .elementByCss('#page-url').click() + .elementByCss('p').text() + + expect(counter).toBe('COUNT: 1') + + await browser.close() + }) + }) + + describe('when hash set to empty', () => { + it('should not run getInitialProps', async () => { + const browser = await webdriver(context.appPort, '/nav/hash-changes') + + const counter = await browser + .elementByCss('#via-a').click() + .elementByCss('#via-empty-hash').click() + .elementByCss('p').text() + + expect(counter).toBe('COUNT: 0') + + await browser.close() + }) + }) + + describe('when hash changed to a different hash', () => { + it('should not run getInitialProps', async () => { + const browser = await webdriver(context.appPort, '/nav/hash-changes') + + const counter = await browser + .elementByCss('#via-a').click() + .elementByCss('#via-link').click() + .elementByCss('p').text() + + expect(counter).toBe('COUNT: 0') + + await browser.close() + }) + }) + }) + + describe('with shallow routing', () => { + it('should update the url without running getInitialProps', async () => { + const browser = await webdriver(context.appPort, '/nav/shallow-routing') + const counter = await browser + .elementByCss('#increase').click() + .elementByCss('#increase').click() + .elementByCss('#counter').text() + expect(counter).toBe('Counter: 2') + + const getInitialPropsRunCount = await browser + .elementByCss('#get-initial-props-run-count').text() + expect(getInitialPropsRunCount).toBe('getInitialProps run count: 1') + + await browser.close() + }) + + it('should handle the back button and should not run getInitialProps', async () => { + const browser = await webdriver(context.appPort, '/nav/shallow-routing') + let counter = await browser + .elementByCss('#increase').click() + .elementByCss('#increase').click() + .elementByCss('#counter').text() + expect(counter).toBe('Counter: 2') + + counter = await browser + .back() + .elementByCss('#counter').text() + expect(counter).toBe('Counter: 1') + + const getInitialPropsRunCount = await browser + .elementByCss('#get-initial-props-run-count').text() + expect(getInitialPropsRunCount).toBe('getInitialProps run count: 1') + + await browser.close() + }) + + it('should run getInitialProps always when rending the page to the screen', async () => { + const browser = await webdriver(context.appPort, '/nav/shallow-routing') + + const counter = await browser + .elementByCss('#increase').click() + .elementByCss('#increase').click() + .elementByCss('#home-link').click() + .waitForElementByCss('.nav-home') + .back() + .waitForElementByCss('.shallow-routing') + .elementByCss('#counter').text() + expect(counter).toBe('Counter: 2') + + const getInitialPropsRunCount = await browser + .elementByCss('#get-initial-props-run-count').text() + expect(getInitialPropsRunCount).toBe('getInitialProps run count: 2') + + await browser.close() + }) + }) + + describe('with URL objects', () => { + it('should work with ', async () => { + const browser = await webdriver(context.appPort, '/nav') + const text = await browser + .elementByCss('#query-string-link').click() + .waitForElementByCss('.nav-querystring') + .elementByCss('p').text() + expect(text).toBe('10') + + expect(await browser.url()) + .toBe(`http://localhost:${context.appPort}/nav/querystring/10#10`) + await browser.close() + }) + + it('should work with "Router.push"', async () => { + const browser = await webdriver(context.appPort, '/nav') + const text = await browser + .elementByCss('#query-string-button').click() + .waitForElementByCss('.nav-querystring') + .elementByCss('p').text() + expect(text).toBe('10') + + expect(await browser.url()) + .toBe(`http://localhost:${context.appPort}/nav/querystring/10#10`) + await browser.close() + }) + + it('should work with the "replace" prop', async () => { + const browser = await webdriver(context.appPort, '/nav') + + let stackLength = await browser + .eval('window.history.length') + + expect(stackLength).toBe(2) + + // Navigation to /about using a replace link should maintain the url stack length + const text = await browser + .elementByCss('#about-replace-link').click() + .waitForElementByCss('.nav-about') + .elementByCss('p').text() + + expect(text).toBe('This is the about page.') + + stackLength = await browser + .eval('window.history.length') + + expect(stackLength).toBe(2) + + // Going back to the home with a regular link will augment the history count + await browser + .elementByCss('#home-link').click() + .waitForElementByCss('.nav-home') + + stackLength = await browser + .eval('window.history.length') + + expect(stackLength).toBe(3) + + await browser.close() + }) + }) + + describe('with getInitialProp redirect', () => { + it('should redirect the page via client side', async () => { + const browser = await webdriver(context.appPort, '/nav') + const text = await browser + .elementByCss('#redirect-link').click() + .waitForElementByCss('.nav-about') + .elementByCss('p').text() + + expect(text).toBe('This is the about page.') + await browser.close() + }) + + it('should redirect the page when loading', async () => { + const browser = await webdriver(context.appPort, '/nav/redirect') + const text = await browser + .waitForElementByCss('.nav-about') + .elementByCss('p').text() + + expect(text).toBe('This is the about page.') + await browser.close() + }) + }) + + describe('with different types of urls', () => { + it('should work with normal page', async () => { + const browser = await webdriver(context.appPort, '/with-cdm') + const text = await browser.elementByCss('p').text() + + expect(text).toBe('ComponentDidMount executed on client.') + await browser.close() + }) + + it('should work with dir/ page', async () => { + const browser = await webdriver(context.appPort, '/nested-cdm') + const text = await browser.elementByCss('p').text() + + expect(text).toBe('ComponentDidMount executed on client.') + await browser.close() + }) + + it('should work with /index page', async () => { + const browser = await webdriver(context.appPort, '/index') + const text = await browser.elementByCss('p').text() + + expect(text).toBe('ComponentDidMount executed on client.') + await browser.close() + }) + + it('should work with / page', async () => { + const browser = await webdriver(context.appPort, '/') + const text = await browser.elementByCss('p').text() + + expect(text).toBe('ComponentDidMount executed on client.') + await browser.close() + }) + }) + + describe('with the HOC based router', () => { + it('should navigate as expected', async () => { + const browser = await webdriver(context.appPort, '/nav/with-hoc') + + const pathname = await browser.elementByCss('#pathname').text() + expect(pathname).toBe('Current path: /nav/with-hoc') + + const asPath = await browser.elementByCss('#asPath').text() + expect(asPath).toBe('Current asPath: /nav/with-hoc') + + const text = await browser + .elementByCss('.nav-with-hoc a').click() + .waitForElementByCss('.nav-home') + .elementByCss('p').text() + + expect(text).toBe('This is the home.') + await browser.close() + }) + }) + + describe('with asPath', () => { + describe('inside getInitialProps', () => { + it('should show the correct asPath with a Link with as prop', async () => { + const browser = await webdriver(context.appPort, '/nav') + const asPath = await browser + .elementByCss('#as-path-link').click() + .waitForElementByCss('.as-path-content') + .elementByCss('.as-path-content').text() + + expect(asPath).toBe('/as/path') + await browser.close() + }) + + it('should show the correct asPath with a Link without the as prop', async () => { + const browser = await webdriver(context.appPort, '/nav') + const asPath = await browser + .elementByCss('#as-path-link-no-as').click() + .waitForElementByCss('.as-path-content') + .elementByCss('.as-path-content').text() + + expect(asPath).toBe('/nav/as-path') + await browser.close() + }) + }) + + describe('with next/router', () => { + it('should show the correct asPath', async () => { + const browser = await webdriver(context.appPort, '/nav') + const asPath = await browser + .elementByCss('#as-path-using-router-link').click() + .waitForElementByCss('.as-path-content') + .elementByCss('.as-path-content').text() + + expect(asPath).toBe('/nav/as-path-using-router') + await browser.close() + }) + }) + + describe('with next/link', () => { + it('should use pushState with same href and different asPath', async () => { + let browser + try { + browser = await webdriver(context.appPort, '/nav/as-path-pushstate') + await browser.elementByCss('#hello').click().waitForElementByCss('#something-hello') + const queryOne = JSON.parse(await browser.elementByCss('#router-query').text()) + expect(queryOne.something).toBe('hello') + await browser.elementByCss('#same-query').click().waitForElementByCss('#something-same-query') + const queryTwo = JSON.parse(await browser.elementByCss('#router-query').text()) + expect(queryTwo.something).toBe('hello') + await browser.back().waitForElementByCss('#something-hello') + const queryThree = JSON.parse(await browser.elementByCss('#router-query').text()) + expect(queryThree.something).toBe('hello') + await browser.elementByCss('#else').click().waitForElementByCss('#something-else') + await browser.elementByCss('#hello2').click().waitForElementByCss('#nav-as-path-pushstate') + await browser.back().waitForElementByCss('#something-else') + const queryFour = JSON.parse(await browser.elementByCss('#router-query').text()) + expect(queryFour.something).toBe(undefined) + } finally { + if (browser) { + await browser.close() + } + } + }) + + it('should detect asPath query changes correctly', async () => { + let browser + try { + browser = await webdriver(context.appPort, '/nav/as-path-query') + await browser.elementByCss('#hello').click().waitForElementByCss('#something-hello-something-hello') + const queryOne = JSON.parse(await browser.elementByCss('#router-query').text()) + expect(queryOne.something).toBe('hello') + await browser.elementByCss('#hello2').click().waitForElementByCss('#something-hello-something-else') + const queryTwo = JSON.parse(await browser.elementByCss('#router-query').text()) + expect(queryTwo.something).toBe('else') + } finally { + if (browser) { + await browser.close() + } + } + }) + }) + }) + + describe('runtime errors', () => { + it('should show react-error-overlay when a client side error is thrown inside a component', async () => { + let browser + try { + browser = await webdriver(context.appPort, '/error-inside-browser-page') + await waitFor(3000) + const text = await getReactErrorOverlayContent(browser) + expect(text).toMatch(/An Expected error occurred/) + expect(text).toMatch(/pages\/error-inside-browser-page\.js:5/) + } finally { + if (browser) { + await browser.close() + } + } + }) + + it('should show react-error-overlay when a client side error is thrown outside a component', async () => { + let browser + try { + browser = await webdriver(context.appPort, '/error-in-the-browser-global-scope') + await waitFor(3000) + const text = await getReactErrorOverlayContent(browser) + expect(text).toMatch(/An Expected error occurred/) + expect(text).toMatch(/error-in-the-browser-global-scope\.js:2/) + } finally { + if (browser) { + await browser.close() + } + } + }) + }) + + describe('with 404 pages', () => { + it('should 404 on not existent page', async () => { + const browser = await webdriver(context.appPort, '/non-existent') + expect(await browser.elementByCss('h1').text()).toBe('404') + expect(await browser.elementByCss('h2').text()).toBe('This page could not be found.') + await browser.close() + }) + + it('should 404 for /', async () => { + const browser = await webdriver(context.appPort, '/nav/about/') + expect(await browser.elementByCss('h1').text()).toBe('404') + expect(await browser.elementByCss('h2').text()).toBe('This page could not be found.') + await browser.close() + }) + + it('should should not contain a page script in a 404 page', async () => { + const browser = await webdriver(context.appPort, '/non-existent') + const scripts = await browser.elementsByCss('script[src]') + for (const script of scripts) { + const src = await script.getAttribute('src') + expect(src.includes('/non-existent')).toBeFalsy() + } + await browser.close() + }) + }) + + describe('updating head while client routing', () => { + it('should update head during client routing', async () => { + let browser + try { + browser = await webdriver(context.appPort, '/nav/head-1') + expect(await browser.elementByCss('meta[name="description"]').getAttribute('content')).toBe('Head One') + await browser.elementByCss('#to-head-2').click().waitForElementByCss('#head-2') + expect(await browser.elementByCss('meta[name="description"]').getAttribute('content')).toBe('Head Two') + await browser.elementByCss('#to-head-1').click().waitForElementByCss('#head-1') + expect(await browser.elementByCss('meta[name="description"]').getAttribute('content')).toBe('Head One') + } finally { + if (browser) { + await browser.close() + } + } + }) + }) + + it('should not error on module.exports + polyfills', async () => { + let browser + try { + browser = await webdriver(context.appPort, '/read-only-object-error') + expect(await browser.elementByCss('body').text()).toBe('this is just a placeholder component') + } finally { + if (browser) { + await browser.close() + } + } + }) + + it('should work on nested /index/index.js', async () => { + const browser = await webdriver(context.appPort, '/nested-index/index') + expect(await browser.elementByCss('p').text()).toBe('This is an index.js nested in an index/ folder.') + await browser.close() + }) + + renderingSuite((p, q) => renderViaHTTP(context.appPort, p, q), (p, q) => fetchViaHTTP(context.appPort, p, q)) +}) diff --git a/test/integration/basic/test/rendering.js b/test/integration/client-navigation/test/rendering.js similarity index 99% rename from test/integration/basic/test/rendering.js rename to test/integration/client-navigation/test/rendering.js index 65f9a9130b..0d2874f1fc 100644 --- a/test/integration/basic/test/rendering.js +++ b/test/integration/client-navigation/test/rendering.js @@ -4,13 +4,13 @@ import cheerio from 'cheerio' import { BUILD_MANIFEST, REACT_LOADABLE_MANIFEST } from 'next-server/constants' import { join } from 'path' -export default function ({ app }, suiteName, render, fetch) { +export default function (render, fetch) { async function get$ (path, query) { const html = await render(path, query) return cheerio.load(html) } - describe(suiteName, () => { + describe('Rendering via HTTP', () => { test('renders a stateless component', async () => { const html = await render('/stateless') expect(html.includes('')).toBeTruthy() diff --git a/yarn.lock b/yarn.lock index d2bca03378..a73eabbb2e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -777,6 +777,14 @@ lodash "^4.17.11" to-fast-properties "^2.0.0" +"@jest/types@^24.5.0": + version "24.5.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.5.0.tgz#feee214a4d0167b0ca447284e95a57aa10b3ee95" + integrity sha512-kN7RFzNMf2R8UDadPOl6ReyI+MT8xfqRuAnuVL+i4gwjv/zubdDK+EDeLHYwq1j0CSSR2W/MmgaRlMZJzXdmVA== + dependencies: + "@types/istanbul-lib-coverage" "^1.1.0" + "@types/yargs" "^12.0.9" + "@lerna/add@3.13.0": version "3.13.0" resolved "https://registry.yarnpkg.com/@lerna/add/-/add-3.13.0.tgz#e971a17c1f85cba40f22c816a2bb9d855b62d07d" @@ -1584,6 +1592,11 @@ resolved "https://registry.yarnpkg.com/@types/fresh/-/fresh-0.5.0.tgz#4d09231027d69c4369cfb01a9af5ef083d0d285f" integrity sha512-eGPzuyc6wZM3sSHJdF7NM2jW6B/xsB014Rqg/iDa6xY02mlfy1w/TE2sYhR8vbHxkzJOXiGo6NuIk3xk35vsgQ== +"@types/istanbul-lib-coverage@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.0.tgz#2cc2ca41051498382b43157c8227fea60363f94a" + integrity sha512-ohkhb9LehJy+PA40rDtGAji61NCgdtKLAlFoYp4cnuuQEswwdK3vz9SOIkkyc3wrk8dzjphQApNs56yyXLStaQ== + "@types/loader-utils@1.1.3": version "1.1.3" resolved "https://registry.yarnpkg.com/@types/loader-utils/-/loader-utils-1.1.3.tgz#82b9163f2ead596c68a8c03e450fbd6e089df401" @@ -1739,6 +1752,11 @@ "@types/uglify-js" "*" source-map "^0.6.0" +"@types/yargs@^12.0.9": + version "12.0.10" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-12.0.10.tgz#17a8ec65cd8e88f51b418ceb271af18d3137df67" + integrity sha512-WsVzTPshvCSbHThUduGGxbmnwcpkgSctHGHTqzWyFg4lYAuV5qXlyFPOsP3OWqCINfmg/8VXP+zJaa4OxEsBQQ== + "@webassemblyjs/ast@1.7.11": version "1.7.11" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.7.11.tgz#b988582cafbb2b095e8b556526f30c90d057cace" @@ -7129,6 +7147,11 @@ jest-get-type@^22.1.0: resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-22.4.3.tgz#e3a8504d8479342dd4420236b322869f18900ce4" integrity sha512-/jsz0Y+V29w1chdXVygEKSz2nBoHoYqNShPe+QgxSNjAuP1i8+k4LbQNrfoliKej0P45sivkSCh7yiD6ubHS3w== +jest-get-type@^24.3.0: + version "24.3.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.3.0.tgz#582cfd1a4f91b5cdad1d43d2932f816d543c65da" + integrity sha512-HYF6pry72YUlVcvUx3sEpMRwXEWGEPlJ0bSPVnB3b3n++j4phUEoSPcS6GC0pPJ9rpyPSe4cb5muFo6D39cXow== + jest-haste-map@^23.6.0: version "23.6.0" resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-23.6.0.tgz#2e3eb997814ca696d62afdb3f2529f5bbc935e16" @@ -7161,13 +7184,12 @@ jest-jasmine2@^23.6.0: jest-util "^23.4.0" pretty-format "^23.6.0" -jest-junit@^5.0.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/jest-junit/-/jest-junit-5.2.0.tgz#980401db7aa69999cf117c6d740a8135c22ae379" - integrity sha512-Mdg0Qpdh1Xm/FA1B/mcLlmEmlr3XzH5pZg7MvcAwZhjHijPRd1z/UwYwkwNHmCV7o4ZOWCf77nLu7ZkhHHrtJg== +jest-junit@6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/jest-junit/-/jest-junit-6.3.0.tgz#99e64ebc54eddcb21238f0cc49f5820c89a8c785" + integrity sha512-3PH9UkpaomX6CUzqjlnk0m4yBCW/eroxV6v61OM6LkCQFO848P3YUhfIzu8ypZSBKB3vvCbB4WaLTKT0BrIf8A== dependencies: - jest-config "^23.6.0" - jest-validate "^23.0.1" + jest-validate "^24.0.0" mkdirp "^0.5.1" strip-ansi "^4.0.0" xml "^1.0.1" @@ -7317,7 +7339,7 @@ jest-validate@^21.1.0: leven "^2.1.0" pretty-format "^21.2.1" -jest-validate@^23.0.1, jest-validate@^23.6.0: +jest-validate@^23.6.0: version "23.6.0" resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-23.6.0.tgz#36761f99d1ed33fcd425b4e4c5595d62b6597474" integrity sha512-OFKapYxe72yz7agrDAWi8v2WL8GIfVqcbKRCLbRG9PAxtzF9b1SEDdTpytNDN12z2fJynoBwpMpvj2R39plI2A== @@ -7327,6 +7349,18 @@ jest-validate@^23.0.1, jest-validate@^23.6.0: leven "^2.1.0" pretty-format "^23.6.0" +jest-validate@^24.0.0: + version "24.5.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-24.5.0.tgz#62fd93d81214c070bb2d7a55f329a79d8057c7de" + integrity sha512-gg0dYszxjgK2o11unSIJhkOFZqNRQbWOAB2/LOUdsd2LfD9oXiMeuee8XsT0iRy5EvSccBgB4h/9HRbIo3MHgQ== + dependencies: + "@jest/types" "^24.5.0" + camelcase "^5.0.0" + chalk "^2.0.1" + jest-get-type "^24.3.0" + leven "^2.1.0" + pretty-format "^24.5.0" + jest-watcher@^23.4.0: version "23.4.0" resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-23.4.0.tgz#d2e28ce74f8dad6c6afc922b92cabef6ed05c91c" @@ -9909,6 +9943,16 @@ pretty-format@^23.6.0: ansi-regex "^3.0.0" ansi-styles "^3.2.0" +pretty-format@^24.5.0: + version "24.5.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.5.0.tgz#cc69a0281a62cd7242633fc135d6930cd889822d" + integrity sha512-/3RuSghukCf8Riu5Ncve0iI+BzVkbRU5EeUoArKARZobREycuH5O4waxvaNIloEXdb0qwgmEAed5vTpX1HNROQ== + dependencies: + "@jest/types" "^24.5.0" + ansi-regex "^4.0.0" + ansi-styles "^3.2.0" + react-is "^16.8.4" + private@^0.1.6, private@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" @@ -10218,6 +10262,11 @@ react-is@^16.3.2, react-is@^16.8.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.3.tgz#4ad8b029c2a718fc0cfc746c8d4e1b7221e5387d" integrity sha512-Y4rC1ZJmsxxkkPuMLwvKvlL1Zfpbcu+Bf4ZigkHup3v9EfdYhAlWAaVyA19olXq2o2mGn0w+dFKvk3pVVlYcIA== +react-is@^16.8.4: + version "16.8.4" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.4.tgz#90f336a68c3a29a096a3d648ab80e87ec61482a2" + integrity sha512-PVadd+WaUDOAciICm/J1waJaSvgq+4rHE/K70j0PFqKhkTBsPv/82UGQJNXAngz1fOQLLxI6z1sEDmJDQhCTAA== + react@16.8.0: version "16.8.0" resolved "https://registry.yarnpkg.com/react/-/react-16.8.0.tgz#8533f0e4af818f448a276eae71681d09e8dd970a" -- GitLab