[next] Update tests to run against latest canary (#4682)

In the latest canary of Next.js pages are no longer nested under the `BUILD_ID` folder and instead are nested under a hash for the page bundle content. To prevent these tests from breaking too often from changes in canary this updates to locate the page bundle using the `buildManifest`. This also updates our latest SSG fixture to test against the latest canary to help ensure the feature doesn't break with a new canary release
This commit is contained in:
JJ Kasper
2020-06-22 16:31:37 -05:00
committed by GitHub
parent bb705cd091
commit b454021234
21 changed files with 102 additions and 47 deletions

View File

@@ -596,7 +596,7 @@ export const build = async ({
src: path.join(
'/',
entryDirectory,
'_next/static/(?:[^/]+/pages|chunks|runtime|css|media)/.+'
'_next/static/(?:[^/]+/pages|pages|chunks|runtime|css|media)/.+'
),
status: 404,
check: true,
@@ -616,7 +616,7 @@ export const build = async ({
src: path.join(
'/',
entryDirectory,
'_next/static/(?:[^/]+/pages|chunks|runtime|css|media)/.+'
'_next/static/(?:[^/]+/pages|pages|chunks|runtime|css|media)/.+'
),
// Next.js assets contain a hash or entropy in their filenames, so they
// are guaranteed to be unique and cacheable indefinitely.
@@ -1616,7 +1616,7 @@ export const build = async ({
src: path.join(
'/',
entryDirectory,
'_next/static/(?:[^/]+/pages|chunks|runtime|css|media)/.+'
'_next/static/(?:[^/]+/pages|pages|chunks|runtime|css|media)/.+'
),
status: 404,
check: true,
@@ -1646,7 +1646,7 @@ export const build = async ({
src: path.join(
'/',
entryDirectory,
'_next/static/(?:[^/]+/pages|chunks|runtime|css|media)/.+'
'_next/static/(?:[^/]+/pages|pages|chunks|runtime|css|media)/.+'
),
// Next.js assets contain a hash or entropy in their filenames, so they
// are guaranteed to be unique and cacheable indefinitely.

View File

@@ -1,6 +1,6 @@
{
"dependencies": {
"next": "9.2.1-canary.8",
"next": "canary",
"react": "^16.8.6",
"react-dom": "^16.8.6"
}

View File

@@ -1,15 +1,15 @@
module.exports = {
generateBuildId() {
return 'build-id'
return 'testing-build-id';
},
experimental: {
async rewrites() {
return [
{
source: '/:path*',
destination: '/params'
}
]
}
}
}
destination: '/params',
},
];
},
},
};

View File

@@ -3,7 +3,7 @@
"builds": [{ "src": "package.json", "use": "@vercel/next" }],
"probes": [
{
"path": "/_next/static/build-id/pages/hello.js",
"path": "/_next/__NEXT_SCRIPT__(/hello)",
"mustContain": "hello world"
},
{

View File

@@ -1,6 +1,6 @@
{
"dependencies": {
"next": "9.2.1-canary.8",
"next": "canary",
"react": "^16.8.6",
"react-dom": "^16.8.6"
}

View File

@@ -3,7 +3,7 @@
"builds": [{ "src": "package.json", "use": "@vercel/next" }],
"probes": [
{
"path": "/_next/static/9dc4d2c93491d81eead3/pages/index.js",
"path": "/_next/__NEXT_SCRIPT__(/)",
"responseHeaders": {
"cache-control": "public,max-age=31536000,immutable"
}

View File

@@ -2,7 +2,5 @@ module.exports = {
generateBuildId() {
return 'testing-build-id';
},
experimental: {
basePath: '/docs',
},
basePath: '/docs',
};

View File

@@ -3,7 +3,7 @@
"builds": [{ "src": "package.json", "use": "@vercel/next" }],
"probes": [
{
"path": "/docs/_next/static/a7184ed7301386fd6825/pages/index.js",
"path": "/docs/_next/__NEXT_SCRIPT__(/,/docs)",
"responseHeaders": {
"cache-control": "public,max-age=31536000,immutable"
}
@@ -29,11 +29,11 @@
"mustNotContain": "hello from another"
},
{
"path": "/_next/static/testing-build-id/pages/index.js",
"path": "/_next/__NEXT_SCRIPT__(/)",
"mustNotContain": "hello from index"
},
{
"path": "/_next/static/testing-build-id/pages/another.js",
"path": "/_next/__NEXT_SCRIPT__(/another)",
"mustNotContain": "hello from another"
}
]

View File

@@ -1,6 +1,6 @@
{
"dependencies": {
"next": "9.3.1",
"next": "canary",
"react": "^16.8.6",
"react-dom": "^16.8.6"
}

View File

@@ -1,6 +1,6 @@
{
"dependencies": {
"next": "9.2.3-canary.14",
"next": "canary",
"react": "^16.8.6",
"react-dom": "^16.8.6"
}

View File

@@ -1,13 +1,13 @@
import React from 'react';
// eslint-disable-next-line camelcase
export async function unstable_getStaticProps() {
export async function getStaticProps() {
return {
props: {
world: 'world',
time: new Date().getTime(),
},
revalidate: 5,
unstable_revalidate: 5,
};
}

View File

@@ -1,13 +1,13 @@
import React from 'react';
// eslint-disable-next-line camelcase
export async function unstable_getStaticProps() {
export async function getStaticProps() {
return {
props: {
world: 'world',
time: new Date().getTime(),
},
revalidate: 5,
unstable_revalidate: 5,
};
}

View File

@@ -1,7 +1,7 @@
import React from 'react';
// eslint-disable-next-line camelcase
export async function unstable_getStaticPaths() {
export async function getStaticPaths() {
return {
paths: [
'/blog/post-1/comment-1',
@@ -13,14 +13,14 @@ export async function unstable_getStaticPaths() {
}
// eslint-disable-next-line camelcase
export async function unstable_getStaticProps({ params }) {
export async function getStaticProps({ params }) {
return {
props: {
post: params.post,
comment: params.comment,
time: new Date().getTime(),
},
revalidate: 2,
unstable_revalidate: 2,
};
}

View File

@@ -1,7 +1,7 @@
import React from 'react';
// eslint-disable-next-line camelcase
export async function unstable_getStaticPaths() {
export async function getStaticPaths() {
return {
paths: ['/blog/post-1', { params: { post: 'post-2' } }],
fallback: true,
@@ -9,7 +9,7 @@ export async function unstable_getStaticPaths() {
}
// eslint-disable-next-line camelcase
export async function unstable_getStaticProps({ params }) {
export async function getStaticProps({ params }) {
if (params.post === 'post-10') {
await new Promise(resolve => {
setTimeout(() => resolve(), 1000);
@@ -21,7 +21,7 @@ export async function unstable_getStaticProps({ params }) {
post: params.post,
time: (await import('perf_hooks')).performance.now(),
},
revalidate: 10,
unstable_revalidate: 10,
};
}

View File

@@ -1,13 +1,13 @@
import React from 'react';
// eslint-disable-next-line camelcase
export async function unstable_getStaticProps() {
export async function getStaticProps() {
return {
props: {
world: 'world',
time: new Date().getTime(),
},
revalidate: false,
unstable_revalidate: false,
};
}

View File

@@ -1,7 +1,7 @@
import React from 'react';
// eslint-disable-next-line camelcase
export async function unstable_getStaticPaths() {
export async function getStaticPaths() {
return {
paths: ['/nofallback/one', { params: { slug: 'two' } }],
fallback: false,
@@ -9,13 +9,13 @@ export async function unstable_getStaticPaths() {
}
// eslint-disable-next-line camelcase
export async function unstable_getStaticProps({ params }) {
export async function getStaticProps({ params }) {
return {
props: {
slug: params.slug,
time: (await import('perf_hooks')).performance.now(),
},
revalidate: 10,
unstable_revalidate: 10,
};
}

View File

@@ -85,6 +85,10 @@ module.exports = {
source: '/:path/post-321',
destination: '/with-params',
},
{
source: '/a/catch-all/:path*',
destination: '/a/catch-all',
},
];
},
async redirects() {

View File

@@ -182,7 +182,7 @@
// should match /_next file after rewrite
{
"path": "/hidden/_next/static/b09092d6eebe375caba5/pages/hello.js",
"path": "/hidden/_next/__NEXT_SCRIPT__(/hello)",
"mustContain": "createElement"
},
@@ -252,6 +252,13 @@
"path": "/catchall-dash/hello/world",
"status": 200,
"mustContain": "hello/world"
},
// should rewrite and normalize catch-all rewrite param
{
"path": "/a/catch-all/hello/world",
"status": 200,
"mustContain": "hello/world"
}
]
}

View File

@@ -0,0 +1,9 @@
import { useRouter } from 'next/router';
export default () => <p>{useRouter().query.path?.join('/')}</p>;
export const getServerSideProps = () => {
return {
props: {},
};
};

View File

@@ -22,10 +22,10 @@ it(
filePath.match(/_error/)
);
const hasUnderScoreAppStaticFile = filePaths.some(filePath =>
filePath.match(/static.*\/pages\/_app\.js$/)
filePath.match(/static.*\/pages\/_app-.*\.js$/)
);
const hasUnderScoreErrorStaticFile = filePaths.some(filePath =>
filePath.match(/static.*\/pages\/_error\.js$/)
filePath.match(/static.*\/pages\/_error-.*\.js$/)
);
expect(hasUnderScoreAppStaticFile).toBeTruthy();
expect(hasUnderScoreErrorStaticFile).toBeTruthy();
@@ -310,10 +310,10 @@ it(
filePath.match(/_error/)
);
const hasUnderScoreAppStaticFile = filePaths.some(filePath =>
filePath.match(/static.*\/pages\/_app\.js$/)
filePath.match(/static.*\/pages\/_app-.*\.js$/)
);
const hasUnderScoreErrorStaticFile = filePaths.some(filePath =>
filePath.match(/static.*\/pages\/_error\.js$/)
filePath.match(/static.*\/pages\/_error-.*\.js$/)
);
expect(hasUnderScoreAppStaticFile).toBeTruthy();
expect(hasUnderScoreErrorStaticFile).toBeTruthy();
@@ -345,10 +345,10 @@ it(
filePath.match(/_error/)
);
const hasUnderScoreAppStaticFile = filePaths.some(filePath =>
filePath.match(/static.*\/pages\/_app\.js$/)
filePath.match(/static.*\/pages\/_app-.*\.js$/)
);
const hasUnderScoreErrorStaticFile = filePaths.some(filePath =>
filePath.match(/static.*\/pages\/_error\.js$/)
filePath.match(/static.*\/pages\/_error-.*\.js$/)
);
expect(hasUnderScoreAppStaticFile).toBeTruthy();
expect(hasUnderScoreErrorStaticFile).toBeTruthy();
@@ -380,10 +380,10 @@ it(
filePath.match(/_error/)
);
const hasUnderScoreAppStaticFile = filePaths.some(filePath =>
filePath.match(/static.*\/pages\/_app\.js$/)
filePath.match(/static.*\/pages\/_app-.*\.js$/)
);
const hasUnderScoreErrorStaticFile = filePaths.some(filePath =>
filePath.match(/static.*\/pages\/_error\.js$/)
filePath.match(/static.*\/pages\/_error-.*\.js$/)
);
const hasBuildFile = await fs.pathExists(
path.join(__dirname, 'serverless-no-config-build'),

View File

@@ -95,6 +95,7 @@ async function testDeployment(
bodies[configName] = Buffer.from(JSON.stringify(nowJson));
delete bodies['probe.js'];
const { deploymentId, deploymentUrl } = await nowDeploy(bodies, randomness);
let nextBuildManifest;
for (const probe of nowJson.probes || []) {
console.log('testing', JSON.stringify(probe));
@@ -102,6 +103,42 @@ async function testDeployment(
await new Promise(resolve => setTimeout(resolve, probe.delay));
continue;
}
const nextScriptIndex = probe.path.indexOf('__NEXT_SCRIPT__(');
if (nextScriptIndex > -1) {
const scriptNameEnd = probe.path.lastIndexOf(')');
let scriptName = probe.path.substring(
nextScriptIndex + '__NEXT_SCRIPT__('.length,
scriptNameEnd
);
const scriptArgs = scriptName.split(',');
scriptName = scriptArgs.shift();
const manifestPrefix = scriptArgs.shift() || '';
if (!nextBuildManifest) {
const manifestUrl = `https://${deploymentUrl}${manifestPrefix}/_next/static/testing-build-id/_buildManifest.js`;
console.log('fetching buildManifest at', manifestUrl);
const { text: manifestContent } = await fetchDeploymentUrl(manifestUrl);
// we must eval it since we use devalue to stringify it
global.__BUILD_MANIFEST_CB = null;
nextBuildManifest = eval(
manifestContent
.replace('self.__BUILD_MANIFEST', 'manifest')
.replace(/self.__BUILD_MANIFEST_CB.*/, '')
);
}
const scriptRelativePath = nextBuildManifest[scriptName];
probe.path =
probe.path.substring(0, nextScriptIndex) +
scriptRelativePath +
probe.path.substr(scriptNameEnd + 1);
}
const probeUrl = `https://${deploymentUrl}${probe.path}`;
const fetchOpts = {
...probe.fetchOptions,