[next] Add public dir check and update tests (#5526)

* Add public dir check and update tests

* De-dupe test checks a bit
This commit is contained in:
JJ Kasper
2020-12-08 09:25:55 -06:00
committed by GitHub
parent dd10e8cc77
commit c02dc9ac49
12 changed files with 282 additions and 68 deletions

View File

@@ -1933,7 +1933,25 @@ export async function build({
path.join(entryPath, outputDirectory, 'static') path.join(entryPath, outputDirectory, 'static')
); );
const staticFolderFiles = await glob('**', path.join(entryPath, 'static')); const staticFolderFiles = await glob('**', path.join(entryPath, 'static'));
const publicFolderFiles = await glob('**', path.join(entryPath, 'public'));
let publicFolderFiles: Files = {};
let publicFolderPath: string | undefined;
if (await pathExists(path.join(entryPath, 'public'))) {
publicFolderPath = path.join(entryPath, 'public');
} else if (
// check at the same level as the output directory also
await pathExists(path.join(entryPath, outputDirectory, '../public'))
) {
publicFolderPath = path.join(entryPath, outputDirectory, '../public');
}
if (publicFolderPath) {
debug(`Using public folder at ${publicFolderPath}`);
publicFolderFiles = await glob('**/*', publicFolderPath);
} else {
debug('No public folder found');
}
const staticFiles = Object.keys(nextStaticFiles).reduce( const staticFiles = Object.keys(nextStaticFiles).reduce(
(mappedFiles, file) => ({ (mappedFiles, file) => ({
@@ -1954,10 +1972,7 @@ export async function build({
const publicDirectoryFiles = Object.keys(publicFolderFiles).reduce( const publicDirectoryFiles = Object.keys(publicFolderFiles).reduce(
(mappedFiles, file) => ({ (mappedFiles, file) => ({
...mappedFiles, ...mappedFiles,
[path.join( [path.join(entryDirectory, file)]: publicFolderFiles[file],
entryDirectory,
file.replace(/^public[/\\]+/, '')
)]: publicFolderFiles[file],
}), }),
{} {}
); );

View File

@@ -1,6 +1,29 @@
/* eslint-env jest */ /* eslint-env jest */
const fetch = require('node-fetch'); const fetch = require('node-fetch');
const cheerio = require('cheerio'); const cheerio = require('cheerio');
const { check, waitFor } = require('../../utils');
async function checkForChange(url, initialValue, hardError) {
return check(
async () => {
const res = await fetch(url);
if (res.status !== 200) {
throw new Error(`Invalid status code ${res.status}`);
}
const $ = cheerio.load(await res.text());
const props = JSON.parse($('#props').text());
if (isNaN(props.random)) {
throw new Error(`Invalid random value ${props.random}`);
}
const newValue = props.random;
return initialValue !== newValue ? 'success' : 'fail';
},
'success',
hardError
);
}
module.exports = function (ctx) { module.exports = function (ctx) {
it('should revalidate content properly from /', async () => { it('should revalidate content properly from /', async () => {
@@ -13,15 +36,15 @@ module.exports = function (ctx) {
expect($('#router-locale').text()).toBe('en-US'); expect($('#router-locale').text()).toBe('en-US');
// wait for revalidation to occur // wait for revalidation to occur
await new Promise(resolve => setTimeout(resolve, 4000)); await waitFor(2000);
const res2 = await fetch(`${ctx.deploymentUrl}/`); const res2 = await fetch(`${ctx.deploymentUrl}/`);
expect(res2.status).toBe(200); expect(res2.status).toBe(200);
$ = cheerio.load(await res2.text()); $ = cheerio.load(await res2.text());
const props2 = JSON.parse($('#props').text());
expect(initialRandom).not.toBe(props2.random);
expect($('#router-locale').text()).toBe('en-US'); expect($('#router-locale').text()).toBe('en-US');
await checkForChange(`${ctx.deploymentUrl}/`, initialRandom);
}); });
it('should revalidate content properly from /fr', async () => { it('should revalidate content properly from /fr', async () => {
@@ -34,15 +57,15 @@ module.exports = function (ctx) {
expect($('#router-locale').text()).toBe('fr'); expect($('#router-locale').text()).toBe('fr');
// wait for revalidation to occur // wait for revalidation to occur
await new Promise(resolve => setTimeout(resolve, 4000)); await waitFor(2000);
const res2 = await fetch(`${ctx.deploymentUrl}/fr`); const res2 = await fetch(`${ctx.deploymentUrl}/fr`);
expect(res2.status).toBe(200); expect(res2.status).toBe(200);
$ = cheerio.load(await res2.text()); $ = cheerio.load(await res2.text());
const props2 = JSON.parse($('#props').text());
expect(initialRandom).not.toBe(props2.random);
expect($('#router-locale').text()).toBe('fr'); expect($('#router-locale').text()).toBe('fr');
await checkForChange(`${ctx.deploymentUrl}/fr`, initialRandom);
}); });
it('should revalidate content properly from /nl-NL', async () => { it('should revalidate content properly from /nl-NL', async () => {
@@ -55,15 +78,15 @@ module.exports = function (ctx) {
expect($('#router-locale').text()).toBe('nl-NL'); expect($('#router-locale').text()).toBe('nl-NL');
// wait for revalidation to occur // wait for revalidation to occur
await new Promise(resolve => setTimeout(resolve, 4000)); await waitFor(2000);
const res2 = await fetch(`${ctx.deploymentUrl}/nl-NL`); const res2 = await fetch(`${ctx.deploymentUrl}/nl-NL`);
expect(res2.status).toBe(200); expect(res2.status).toBe(200);
$ = cheerio.load(await res2.text()); $ = cheerio.load(await res2.text());
const props2 = JSON.parse($('#props').text());
expect(initialRandom).not.toBe(props2.random);
expect($('#router-locale').text()).toBe('nl-NL'); expect($('#router-locale').text()).toBe('nl-NL');
await checkForChange(`${ctx.deploymentUrl}/nl-NL`, initialRandom);
}); });
it('should revalidate content properly from /second', async () => { it('should revalidate content properly from /second', async () => {
@@ -77,15 +100,15 @@ module.exports = function (ctx) {
expect($('#router-locale').text()).toBe('en-US'); expect($('#router-locale').text()).toBe('en-US');
// wait for revalidation to occur // wait for revalidation to occur
await new Promise(resolve => setTimeout(resolve, 4000)); await waitFor(2000);
const res2 = await fetch(`${ctx.deploymentUrl}/second`); const res2 = await fetch(`${ctx.deploymentUrl}/second`);
expect(res2.status).toBe(200); expect(res2.status).toBe(200);
$ = cheerio.load(await res2.text()); $ = cheerio.load(await res2.text());
const props2 = JSON.parse($('#props').text());
expect(initialRandom).not.toBe(props2.random);
expect($('#router-locale').text()).toBe('en-US'); expect($('#router-locale').text()).toBe('en-US');
await checkForChange(`${ctx.deploymentUrl}/second`, initialRandom);
}); });
it('should revalidate content properly from /fr/second', async () => { it('should revalidate content properly from /fr/second', async () => {
@@ -99,15 +122,15 @@ module.exports = function (ctx) {
expect($('#router-locale').text()).toBe('fr'); expect($('#router-locale').text()).toBe('fr');
// wait for revalidation to occur // wait for revalidation to occur
await new Promise(resolve => setTimeout(resolve, 4000)); await waitFor(2000);
const res2 = await fetch(`${ctx.deploymentUrl}/fr/second`); const res2 = await fetch(`${ctx.deploymentUrl}/fr/second`);
expect(res2.status).toBe(200); expect(res2.status).toBe(200);
$ = cheerio.load(await res2.text()); $ = cheerio.load(await res2.text());
const props2 = JSON.parse($('#props').text());
expect(initialRandom).not.toBe(props2.random);
expect($('#router-locale').text()).toBe('fr'); expect($('#router-locale').text()).toBe('fr');
await checkForChange(`${ctx.deploymentUrl}/fr/second`, initialRandom);
}); });
it('should revalidate content properly from /nl-NL/second', async () => { it('should revalidate content properly from /nl-NL/second', async () => {
@@ -121,14 +144,14 @@ module.exports = function (ctx) {
expect($('#router-locale').text()).toBe('nl-NL'); expect($('#router-locale').text()).toBe('nl-NL');
// wait for revalidation to occur // wait for revalidation to occur
await new Promise(resolve => setTimeout(resolve, 4000)); await waitFor(2000);
const res2 = await fetch(`${ctx.deploymentUrl}/nl-NL/second`); const res2 = await fetch(`${ctx.deploymentUrl}/nl-NL/second`);
expect(res2.status).toBe(200); expect(res2.status).toBe(200);
$ = cheerio.load(await res2.text()); $ = cheerio.load(await res2.text());
const props2 = JSON.parse($('#props').text());
expect(initialRandom).not.toBe(props2.random);
expect($('#router-locale').text()).toBe('nl-NL'); expect($('#router-locale').text()).toBe('nl-NL');
await checkForChange(`${ctx.deploymentUrl}/nl-NL/second`, initialRandom);
}); });
}; };

View File

@@ -1,6 +1,29 @@
/* eslint-env jest */ /* eslint-env jest */
const fetch = require('node-fetch'); const fetch = require('node-fetch');
const cheerio = require('cheerio'); const cheerio = require('cheerio');
const { check, waitFor } = require('../../utils');
async function checkForChange(url, initialValue, hardError) {
return check(
async () => {
const res = await fetch(url);
if (res.status !== 200) {
throw new Error(`Invalid status code ${res.status}`);
}
const $ = cheerio.load(await res.text());
const props = JSON.parse($('#props').text());
if (isNaN(props.random)) {
throw new Error(`Invalid random value ${props.random}`);
}
const newValue = props.random;
return initialValue !== newValue ? 'success' : 'fail';
},
'success',
hardError
);
}
module.exports = function (ctx) { module.exports = function (ctx) {
it('should revalidate content properly from /', async () => { it('should revalidate content properly from /', async () => {
@@ -10,7 +33,7 @@ module.exports = function (ctx) {
expect(dataRes.status).toBe(200); expect(dataRes.status).toBe(200);
await dataRes.json(); await dataRes.json();
await new Promise(resolve => setTimeout(resolve, 4000)); await waitFor(2000);
const res = await fetch(`${ctx.deploymentUrl}/`); const res = await fetch(`${ctx.deploymentUrl}/`);
expect(res.status).toBe(200); expect(res.status).toBe(200);
@@ -22,16 +45,17 @@ module.exports = function (ctx) {
expect(JSON.parse($('#router-query').text())).toEqual({}); expect(JSON.parse($('#router-query').text())).toEqual({});
// wait for revalidation to occur // wait for revalidation to occur
await new Promise(resolve => setTimeout(resolve, 4000)); await waitFor(2000);
const res2 = await fetch(`${ctx.deploymentUrl}/`); const res2 = await fetch(`${ctx.deploymentUrl}/`);
expect(res2.status).toBe(200); expect(res2.status).toBe(200);
$ = cheerio.load(await res2.text()); $ = cheerio.load(await res2.text());
const props2 = JSON.parse($('#props').text());
expect(initialRandom).not.toBe(props2.random);
expect($('#router-locale').text()).toBe('en-US'); expect($('#router-locale').text()).toBe('en-US');
expect(JSON.parse($('#router-query').text())).toEqual({}); expect(JSON.parse($('#router-query').text())).toEqual({});
await checkForChange(`${ctx.deploymentUrl}/`, initialRandom);
}); });
it('should revalidate content properly from /fr', async () => { it('should revalidate content properly from /fr', async () => {
@@ -41,7 +65,7 @@ module.exports = function (ctx) {
expect(dataRes.status).toBe(200); expect(dataRes.status).toBe(200);
await dataRes.json(); await dataRes.json();
await new Promise(resolve => setTimeout(resolve, 4000)); await waitFor(2000);
const res = await fetch(`${ctx.deploymentUrl}/fr`); const res = await fetch(`${ctx.deploymentUrl}/fr`);
expect(res.status).toBe(200); expect(res.status).toBe(200);
@@ -53,16 +77,16 @@ module.exports = function (ctx) {
expect(JSON.parse($('#router-query').text())).toEqual({}); expect(JSON.parse($('#router-query').text())).toEqual({});
// wait for revalidation to occur // wait for revalidation to occur
await new Promise(resolve => setTimeout(resolve, 4000)); await waitFor(2000);
const res2 = await fetch(`${ctx.deploymentUrl}/fr`); const res2 = await fetch(`${ctx.deploymentUrl}/fr`);
expect(res2.status).toBe(200); expect(res2.status).toBe(200);
$ = cheerio.load(await res2.text()); $ = cheerio.load(await res2.text());
const props2 = JSON.parse($('#props').text());
expect(initialRandom).not.toBe(props2.random);
expect($('#router-locale').text()).toBe('fr'); expect($('#router-locale').text()).toBe('fr');
expect(JSON.parse($('#router-query').text())).toEqual({}); expect(JSON.parse($('#router-query').text())).toEqual({});
await checkForChange(`${ctx.deploymentUrl}/fr`, initialRandom);
}); });
it('should revalidate content properly from /nl-NL', async () => { it('should revalidate content properly from /nl-NL', async () => {
@@ -72,7 +96,7 @@ module.exports = function (ctx) {
expect(dataRes.status).toBe(200); expect(dataRes.status).toBe(200);
await dataRes.json(); await dataRes.json();
await new Promise(resolve => setTimeout(resolve, 4000)); await waitFor(2000);
const res = await fetch(`${ctx.deploymentUrl}/nl-NL`); const res = await fetch(`${ctx.deploymentUrl}/nl-NL`);
expect(res.status).toBe(200); expect(res.status).toBe(200);
@@ -84,16 +108,16 @@ module.exports = function (ctx) {
expect(JSON.parse($('#router-query').text())).toEqual({}); expect(JSON.parse($('#router-query').text())).toEqual({});
// wait for revalidation to occur // wait for revalidation to occur
await new Promise(resolve => setTimeout(resolve, 4000)); await waitFor(2000);
const res2 = await fetch(`${ctx.deploymentUrl}/nl-NL`); const res2 = await fetch(`${ctx.deploymentUrl}/nl-NL`);
expect(res2.status).toBe(200); expect(res2.status).toBe(200);
$ = cheerio.load(await res2.text()); $ = cheerio.load(await res2.text());
const props2 = JSON.parse($('#props').text());
expect(initialRandom).not.toBe(props2.random);
expect($('#router-locale').text()).toBe('nl-NL'); expect($('#router-locale').text()).toBe('nl-NL');
expect(JSON.parse($('#router-query').text())).toEqual({}); expect(JSON.parse($('#router-query').text())).toEqual({});
await checkForChange(`${ctx.deploymentUrl}/nl-NL`, initialRandom);
}); });
it('should revalidate content properly from /gsp/fallback/first', async () => { it('should revalidate content properly from /gsp/fallback/first', async () => {
@@ -104,7 +128,7 @@ module.exports = function (ctx) {
expect(dataRes.status).toBe(200); expect(dataRes.status).toBe(200);
await dataRes.json(); await dataRes.json();
await new Promise(resolve => setTimeout(resolve, 4000)); await waitFor(2000);
const res = await fetch(`${ctx.deploymentUrl}/gsp/fallback/first`); const res = await fetch(`${ctx.deploymentUrl}/gsp/fallback/first`);
expect(res.status).toBe(200); expect(res.status).toBe(200);
@@ -118,17 +142,21 @@ module.exports = function (ctx) {
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'first' }); expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'first' });
// wait for revalidation to occur // wait for revalidation to occur
await new Promise(resolve => setTimeout(resolve, 4000)); await waitFor(2000);
const res2 = await fetch(`${ctx.deploymentUrl}/gsp/fallback/first`); const res2 = await fetch(`${ctx.deploymentUrl}/gsp/fallback/first`);
expect(res2.status).toBe(200); expect(res2.status).toBe(200);
$ = cheerio.load(await res2.text()); $ = cheerio.load(await res2.text());
const props2 = JSON.parse($('#props').text()); const props2 = JSON.parse($('#props').text());
expect(initialRandom).not.toBe(props2.random);
expect($('#router-locale').text()).toBe('en-US'); expect($('#router-locale').text()).toBe('en-US');
expect(props2.params).toEqual({ slug: 'first' }); expect(props2.params).toEqual({ slug: 'first' });
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'first' }); expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'first' });
await checkForChange(
`${ctx.deploymentUrl}/gsp/fallback/first`,
initialRandom
);
}); });
it('should revalidate content properly from /fr/gsp/fallback/first', async () => { it('should revalidate content properly from /fr/gsp/fallback/first', async () => {
@@ -139,7 +167,7 @@ module.exports = function (ctx) {
expect(dataRes.status).toBe(200); expect(dataRes.status).toBe(200);
await dataRes.json(); await dataRes.json();
await new Promise(resolve => setTimeout(resolve, 4000)); await waitFor(2000);
const res = await fetch(`${ctx.deploymentUrl}/fr/gsp/fallback/first`); const res = await fetch(`${ctx.deploymentUrl}/fr/gsp/fallback/first`);
expect(res.status).toBe(200); expect(res.status).toBe(200);
@@ -153,17 +181,21 @@ module.exports = function (ctx) {
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'first' }); expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'first' });
// wait for revalidation to occur // wait for revalidation to occur
await new Promise(resolve => setTimeout(resolve, 4000)); await waitFor(2000);
const res2 = await fetch(`${ctx.deploymentUrl}/fr/gsp/fallback/first`); const res2 = await fetch(`${ctx.deploymentUrl}/fr/gsp/fallback/first`);
expect(res2.status).toBe(200); expect(res2.status).toBe(200);
$ = cheerio.load(await res2.text()); $ = cheerio.load(await res2.text());
const props2 = JSON.parse($('#props').text()); const props2 = JSON.parse($('#props').text());
expect(initialRandom).not.toBe(props2.random);
expect($('#router-locale').text()).toBe('fr'); expect($('#router-locale').text()).toBe('fr');
expect(props2.params).toEqual({ slug: 'first' }); expect(props2.params).toEqual({ slug: 'first' });
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'first' }); expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'first' });
await checkForChange(
`${ctx.deploymentUrl}/fr/gsp/fallback/first`,
initialRandom
);
}); });
it('should revalidate content properly from /nl-NL/gsp/fallback/first', async () => { it('should revalidate content properly from /nl-NL/gsp/fallback/first', async () => {
@@ -174,7 +206,7 @@ module.exports = function (ctx) {
expect(dataRes.status).toBe(200); expect(dataRes.status).toBe(200);
await dataRes.json(); await dataRes.json();
await new Promise(resolve => setTimeout(resolve, 4000)); await waitFor(2000);
const res = await fetch(`${ctx.deploymentUrl}/nl-NL/gsp/fallback/first`); const res = await fetch(`${ctx.deploymentUrl}/nl-NL/gsp/fallback/first`);
expect(res.status).toBe(200); expect(res.status).toBe(200);
@@ -188,17 +220,21 @@ module.exports = function (ctx) {
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'first' }); expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'first' });
// wait for revalidation to occur // wait for revalidation to occur
await new Promise(resolve => setTimeout(resolve, 4000)); await waitFor(2000);
const res2 = await fetch(`${ctx.deploymentUrl}/nl-NL/gsp/fallback/first`); const res2 = await fetch(`${ctx.deploymentUrl}/nl-NL/gsp/fallback/first`);
expect(res2.status).toBe(200); expect(res2.status).toBe(200);
$ = cheerio.load(await res2.text()); $ = cheerio.load(await res2.text());
const props2 = JSON.parse($('#props').text()); const props2 = JSON.parse($('#props').text());
expect(initialRandom).not.toBe(props2.random);
expect($('#router-locale').text()).toBe('nl-NL'); expect($('#router-locale').text()).toBe('nl-NL');
expect(props2.params).toEqual({ slug: 'first' }); expect(props2.params).toEqual({ slug: 'first' });
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'first' }); expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'first' });
await checkForChange(
`${ctx.deploymentUrl}/nl-NL/gsp/fallback/first`,
initialRandom
);
}); });
// //
@@ -212,7 +248,7 @@ module.exports = function (ctx) {
const initRes = await fetch(`${ctx.deploymentUrl}/gsp/fallback/new-page`); const initRes = await fetch(`${ctx.deploymentUrl}/gsp/fallback/new-page`);
expect(initRes.status).toBe(200); expect(initRes.status).toBe(200);
await new Promise(resolve => setTimeout(resolve, 4000)); await waitFor(2000);
const res = await fetch(`${ctx.deploymentUrl}/gsp/fallback/new-page`); const res = await fetch(`${ctx.deploymentUrl}/gsp/fallback/new-page`);
expect(res.status).toBe(200); expect(res.status).toBe(200);
@@ -226,17 +262,21 @@ module.exports = function (ctx) {
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'new-page' }); expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'new-page' });
// wait for revalidation to occur // wait for revalidation to occur
await new Promise(resolve => setTimeout(resolve, 4000)); await waitFor(2000);
const res2 = await fetch(`${ctx.deploymentUrl}/gsp/fallback/new-page`); const res2 = await fetch(`${ctx.deploymentUrl}/gsp/fallback/new-page`);
expect(res2.status).toBe(200); expect(res2.status).toBe(200);
$ = cheerio.load(await res2.text()); $ = cheerio.load(await res2.text());
const props2 = JSON.parse($('#props').text()); const props2 = JSON.parse($('#props').text());
expect(initialRandom).not.toBe(props2.random);
expect($('#router-locale').text()).toBe('en-US'); expect($('#router-locale').text()).toBe('en-US');
expect(props2.params).toEqual({ slug: 'new-page' }); expect(props2.params).toEqual({ slug: 'new-page' });
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'new-page' }); expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'new-page' });
await checkForChange(
`${ctx.deploymentUrl}/gsp/fallback/new-page`,
initialRandom
);
}); });
it('should revalidate content properly from /fr/gsp/fallback/new-page', async () => { it('should revalidate content properly from /fr/gsp/fallback/new-page', async () => {
@@ -246,7 +286,7 @@ module.exports = function (ctx) {
); );
expect(dataRes.status).toBe(200); expect(dataRes.status).toBe(200);
await new Promise(resolve => setTimeout(resolve, 4000)); await waitFor(2000);
const res = await fetch(`${ctx.deploymentUrl}/fr/gsp/fallback/new-page`); const res = await fetch(`${ctx.deploymentUrl}/fr/gsp/fallback/new-page`);
expect(res.status).toBe(200); expect(res.status).toBe(200);
@@ -260,15 +300,18 @@ module.exports = function (ctx) {
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'new-page' }); expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'new-page' });
// wait for revalidation to occur // wait for revalidation to occur
await new Promise(resolve => setTimeout(resolve, 4000)); await waitFor(2000);
const res2 = await fetch(`${ctx.deploymentUrl}/fr/gsp/fallback/new-page`); const res2 = await fetch(`${ctx.deploymentUrl}/fr/gsp/fallback/new-page`);
expect(res2.status).toBe(200); expect(res2.status).toBe(200);
$ = cheerio.load(await res2.text()); $ = cheerio.load(await res2.text());
const props2 = JSON.parse($('#props').text());
expect(initialRandom).not.toBe(props2.random);
expect($('#router-locale').text()).toBe('fr'); expect($('#router-locale').text()).toBe('fr');
await checkForChange(
`${ctx.deploymentUrl}/fr/gsp/fallback/new-page`,
initialRandom
);
}); });
it('should revalidate content properly from /nl-NL/gsp/fallback/new-page', async () => { it('should revalidate content properly from /nl-NL/gsp/fallback/new-page', async () => {
@@ -278,7 +321,7 @@ module.exports = function (ctx) {
); );
expect(dataRes.status).toBe(200); expect(dataRes.status).toBe(200);
await new Promise(resolve => setTimeout(resolve, 4000)); await waitFor(2000);
const res = await fetch(`${ctx.deploymentUrl}/nl-NL/gsp/fallback/new-page`); const res = await fetch(`${ctx.deploymentUrl}/nl-NL/gsp/fallback/new-page`);
expect(res.status).toBe(200); expect(res.status).toBe(200);
@@ -292,7 +335,7 @@ module.exports = function (ctx) {
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'new-page' }); expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'new-page' });
// wait for revalidation to occur // wait for revalidation to occur
await new Promise(resolve => setTimeout(resolve, 4000)); await waitFor(2000);
const res2 = await fetch( const res2 = await fetch(
`${ctx.deploymentUrl}/nl-NL/gsp/fallback/new-page` `${ctx.deploymentUrl}/nl-NL/gsp/fallback/new-page`
@@ -301,10 +344,14 @@ module.exports = function (ctx) {
$ = cheerio.load(await res2.text()); $ = cheerio.load(await res2.text());
const props2 = JSON.parse($('#props').text()); const props2 = JSON.parse($('#props').text());
expect(initialRandom).not.toBe(props2.random);
expect($('#router-locale').text()).toBe('nl-NL'); expect($('#router-locale').text()).toBe('nl-NL');
expect(props2.params).toEqual({ slug: 'new-page' }); expect(props2.params).toEqual({ slug: 'new-page' });
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'new-page' }); expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'new-page' });
await checkForChange(
`${ctx.deploymentUrl}/nl-NL/gsp/fallback/new-page`,
initialRandom
);
}); });
it('should revalidate content properly from /gsp/no-fallback/first', async () => { it('should revalidate content properly from /gsp/no-fallback/first', async () => {
@@ -314,7 +361,7 @@ module.exports = function (ctx) {
expect(dataRes.status).toBe(200); expect(dataRes.status).toBe(200);
await dataRes.json(); await dataRes.json();
await new Promise(resolve => setTimeout(resolve, 4000)); await waitFor(2000);
const res = await fetch(`${ctx.deploymentUrl}/gsp/no-fallback/first`); const res = await fetch(`${ctx.deploymentUrl}/gsp/no-fallback/first`);
expect(res.status).toBe(200); expect(res.status).toBe(200);
@@ -327,17 +374,21 @@ module.exports = function (ctx) {
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'first' }); expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'first' });
// wait for revalidation to occur // wait for revalidation to occur
await new Promise(resolve => setTimeout(resolve, 4000)); await waitFor(2000);
const res2 = await fetch(`${ctx.deploymentUrl}/gsp/no-fallback/first`); const res2 = await fetch(`${ctx.deploymentUrl}/gsp/no-fallback/first`);
expect(res2.status).toBe(200); expect(res2.status).toBe(200);
$ = cheerio.load(await res2.text()); $ = cheerio.load(await res2.text());
const props2 = JSON.parse($('#props').text()); const props2 = JSON.parse($('#props').text());
expect(initialRandom).not.toBe(props2.random);
expect($('#router-locale').text()).toBe('en-US'); expect($('#router-locale').text()).toBe('en-US');
expect(props2.params).toEqual({ slug: 'first' }); expect(props2.params).toEqual({ slug: 'first' });
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'first' }); expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'first' });
await checkForChange(
`${ctx.deploymentUrl}/gsp/no-fallback/first`,
initialRandom
);
}); });
it('should revalidate content properly from /fr/gsp/no-fallback/first', async () => { it('should revalidate content properly from /fr/gsp/no-fallback/first', async () => {
@@ -347,7 +398,7 @@ module.exports = function (ctx) {
expect(dataRes.status).toBe(200); expect(dataRes.status).toBe(200);
await dataRes.json(); await dataRes.json();
await new Promise(resolve => setTimeout(resolve, 4000)); await waitFor(2000);
const res = await fetch(`${ctx.deploymentUrl}/fr/gsp/no-fallback/first`); const res = await fetch(`${ctx.deploymentUrl}/fr/gsp/no-fallback/first`);
expect(res.status).toBe(200); expect(res.status).toBe(200);
@@ -360,17 +411,21 @@ module.exports = function (ctx) {
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'first' }); expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'first' });
// wait for revalidation to occur // wait for revalidation to occur
await new Promise(resolve => setTimeout(resolve, 4000)); await waitFor(2000);
const res2 = await fetch(`${ctx.deploymentUrl}/fr/gsp/no-fallback/first`); const res2 = await fetch(`${ctx.deploymentUrl}/fr/gsp/no-fallback/first`);
expect(res2.status).toBe(200); expect(res2.status).toBe(200);
$ = cheerio.load(await res2.text()); $ = cheerio.load(await res2.text());
const props2 = JSON.parse($('#props').text()); const props2 = JSON.parse($('#props').text());
expect(initialRandom).not.toBe(props2.random);
expect($('#router-locale').text()).toBe('fr'); expect($('#router-locale').text()).toBe('fr');
expect(props2.params).toEqual({ slug: 'first' }); expect(props2.params).toEqual({ slug: 'first' });
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'first' }); expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'first' });
await checkForChange(
`${ctx.deploymentUrl}/fr/gsp/no-fallback/first`,
initialRandom
);
}); });
it('should revalidate content properly from /nl-NL/gsp/no-fallback/second', async () => { it('should revalidate content properly from /nl-NL/gsp/no-fallback/second', async () => {
@@ -380,7 +435,7 @@ module.exports = function (ctx) {
expect(dataRes.status).toBe(200); expect(dataRes.status).toBe(200);
await dataRes.json(); await dataRes.json();
await new Promise(resolve => setTimeout(resolve, 4000)); await waitFor(2000);
const res = await fetch( const res = await fetch(
`${ctx.deploymentUrl}/nl-NL/gsp/no-fallback/second` `${ctx.deploymentUrl}/nl-NL/gsp/no-fallback/second`
@@ -395,7 +450,7 @@ module.exports = function (ctx) {
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'second' }); expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'second' });
// wait for revalidation to occur // wait for revalidation to occur
await new Promise(resolve => setTimeout(resolve, 4000)); await waitFor(2000);
const res2 = await fetch( const res2 = await fetch(
`${ctx.deploymentUrl}/nl-NL/gsp/no-fallback/second` `${ctx.deploymentUrl}/nl-NL/gsp/no-fallback/second`
@@ -404,9 +459,13 @@ module.exports = function (ctx) {
$ = cheerio.load(await res2.text()); $ = cheerio.load(await res2.text());
const props2 = JSON.parse($('#props').text()); const props2 = JSON.parse($('#props').text());
expect(initialRandom).not.toBe(props2.random);
expect($('#router-locale').text()).toBe('nl-NL'); expect($('#router-locale').text()).toBe('nl-NL');
expect(props2.params).toEqual({ slug: 'second' }); expect(props2.params).toEqual({ slug: 'second' });
expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'second' }); expect(JSON.parse($('#router-query').text())).toEqual({ slug: 'second' });
await checkForChange(
`${ctx.deploymentUrl}/nl-NL/gsp/no-fallback/second`,
initialRandom
);
}); });
}; };

View File

@@ -0,0 +1,39 @@
{
"version": 2,
"builds": [
{
"src": "package.json",
"use": "@vercel/next",
"config": {
"outputDirectory": "web/.next"
}
}
],
"probes": [
{
"path": "/",
"status": 200,
"mustContain": "Index page"
},
{
"path": "/dynamic/first",
"status": 200,
"mustContain": "Dynamic Page"
},
{
"path": "/dynamic-ssr/second",
"status": 200,
"mustContain": "Dynamic SSR Page"
},
{
"path": "/hello.txt",
"status": 200,
"mustContain": "hello world!"
},
{
"path": "/public/data.txt",
"status": 200,
"mustContain": "data!!"
}
]
}

View File

@@ -0,0 +1,10 @@
{
"scripts": {
"build": "next build web"
},
"dependencies": {
"next": "canary",
"react": "^16.8.6",
"react-dom": "^16.8.6"
}
}

View File

@@ -0,0 +1,12 @@
export function getServerSideProps() {
return {
props: {
hello: 'world',
random: Math.random(),
},
};
}
export default function Dynamic() {
return <p>Dynamic SSR Page</p>;
}

View File

@@ -0,0 +1,3 @@
export default function Dynamic() {
return <p>Dynamic Page</p>;
}

View File

@@ -0,0 +1,3 @@
export default function Index() {
return <p>Index page</p>;
}

View File

@@ -0,0 +1 @@
hello world!

View File

@@ -0,0 +1 @@
data!!

39
packages/now-next/test/utils.js vendored Normal file
View File

@@ -0,0 +1,39 @@
async function waitFor(milliseconds) {
return new Promise(resolve => {
setTimeout(resolve, milliseconds);
});
}
async function check(contentFn, regex, hardError = true) {
let content;
let lastErr;
for (let tries = 0; tries < 30; tries++) {
try {
content = await contentFn();
if (typeof regex === 'string') {
if (regex === content) {
return true;
}
} else if (regex.test(content)) {
// found the content
return true;
}
await waitFor(1000);
} catch (err) {
await waitFor(1000);
lastErr = err;
}
}
console.error('TIMED OUT CHECK: ', { regex, content, lastErr });
if (hardError) {
throw new Error('TIMED OUT: ' + regex + '\n\n' + content);
}
return false;
}
module.exports = {
check,
waitFor,
};

View File

@@ -1,3 +1,4 @@
const fs = require('fs-extra');
const { glob, getWriteableDirectory } = require('@vercel/build-utils'); const { glob, getWriteableDirectory } = require('@vercel/build-utils');
function runAnalyze(wrapper, context) { function runAnalyze(wrapper, context) {
@@ -11,13 +12,21 @@ function runAnalyze(wrapper, context) {
async function runBuildLambda(inputPath) { async function runBuildLambda(inputPath) {
const inputFiles = await glob('**', inputPath); const inputFiles = await glob('**', inputPath);
const nowJsonRef = inputFiles['vercel.json'] || inputFiles['now.json']; const nowJsonRef = inputFiles['vercel.json'] || inputFiles['now.json'];
expect(nowJsonRef).toBeDefined();
if (typeof expect !== 'undefined') {
expect(nowJsonRef).toBeDefined();
}
const nowJson = require(nowJsonRef.fsPath); const nowJson = require(nowJsonRef.fsPath);
expect(nowJson.builds.length).toBe(1);
const build = nowJson.builds[0]; const build = nowJson.builds[0];
expect(build.src.includes('*')).toBeFalsy();
if (typeof expect !== 'undefined') {
expect(build.src.includes('*')).toBeFalsy();
}
const entrypoint = build.src.replace(/^\//, ''); // strip leftmost slash const entrypoint = build.src.replace(/^\//, ''); // strip leftmost slash
expect(inputFiles[entrypoint]).toBeDefined();
if (typeof expect !== 'undefined') {
expect(inputFiles[entrypoint]).toBeDefined();
}
inputFiles[entrypoint].digest = inputFiles[entrypoint].digest =
'this-is-a-fake-digest-for-non-default-analyze'; 'this-is-a-fake-digest-for-non-default-analyze';
const wrapper = require(build.use); const wrapper = require(build.use);
@@ -28,7 +37,7 @@ async function runBuildLambda(inputPath) {
config: build.config, config: build.config,
}); });
const workPath = await getWriteableDirectory(); const workPath = await fs.realpath(await getWriteableDirectory());
const buildResult = await wrapper.build({ const buildResult = await wrapper.build({
files: inputFiles, files: inputFiles,
entrypoint, entrypoint,