Add more tests
This commit is contained in:
parent
d84a0296b2
commit
681fc99a68
|
@ -0,0 +1,34 @@
|
||||||
|
import request from 'supertest';
|
||||||
|
|
||||||
|
import createServer from '../createServer.js';
|
||||||
|
|
||||||
|
describe('A request that targets a directory with a trailing slash', () => {
|
||||||
|
let server;
|
||||||
|
beforeEach(() => {
|
||||||
|
server = createServer();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when the directory exists', () => {
|
||||||
|
it('returns an HTML page', done => {
|
||||||
|
request(server)
|
||||||
|
.get('/react@16.8.0/umd/')
|
||||||
|
.end((err, res) => {
|
||||||
|
expect(res.statusCode).toBe(200);
|
||||||
|
expect(res.headers['content-type']).toMatch(/\btext\/html\b/);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when the directory does not exist', () => {
|
||||||
|
it('returns a 404 text error', done => {
|
||||||
|
request(server)
|
||||||
|
.get('/react@16.8.0/not-here/')
|
||||||
|
.end((err, res) => {
|
||||||
|
expect(res.statusCode).toBe(404);
|
||||||
|
expect(res.headers['content-type']).toMatch(/\btext\/plain\b/);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,40 @@
|
||||||
|
import request from 'supertest';
|
||||||
|
|
||||||
|
import createServer from '../createServer.js';
|
||||||
|
|
||||||
|
describe('A request for a directory', () => {
|
||||||
|
let server;
|
||||||
|
beforeEach(() => {
|
||||||
|
server = createServer();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when a .js file exists with the same name', () => {
|
||||||
|
it('is redirected to the .js file', done => {
|
||||||
|
request(server)
|
||||||
|
.get('/preact@8.4.2/devtools')
|
||||||
|
.end((err, res) => {
|
||||||
|
expect(res.statusCode).toBe(302);
|
||||||
|
expect(res.headers.location).toEqual('/preact@8.4.2/devtools.js');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when a .json file exists with the same name', () => {
|
||||||
|
it('is redirected to the .json file');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when it contains an index.js file', () => {
|
||||||
|
it('is redirected to the index.js file', done => {
|
||||||
|
request(server)
|
||||||
|
.get('/preact@8.4.2/src/dom')
|
||||||
|
.end((err, res) => {
|
||||||
|
expect(res.statusCode).toBe(302);
|
||||||
|
expect(res.headers.location).toEqual(
|
||||||
|
'/preact@8.4.2/src/dom/index.js'
|
||||||
|
);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,20 @@
|
||||||
|
import request from 'supertest';
|
||||||
|
|
||||||
|
import createServer from '../createServer.js';
|
||||||
|
|
||||||
|
describe('A request for a non-existent file', () => {
|
||||||
|
let server;
|
||||||
|
beforeEach(() => {
|
||||||
|
server = createServer();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns a 404 text error', done => {
|
||||||
|
request(server)
|
||||||
|
.get('/preact@8.4.2/not-here.js')
|
||||||
|
.end((err, res) => {
|
||||||
|
expect(res.statusCode).toBe(404);
|
||||||
|
expect(res.headers['content-type']).toMatch(/\btext\/plain\b/);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -4,13 +4,8 @@ import semver from 'semver';
|
||||||
import AutoIndexApp from '../client/autoIndex/App.js';
|
import AutoIndexApp from '../client/autoIndex/App.js';
|
||||||
|
|
||||||
import MainTemplate from './utils/MainTemplate.js';
|
import MainTemplate from './utils/MainTemplate.js';
|
||||||
import getEntryPoint from './utils/getEntryPoint.js';
|
import getScripts from './utils/getScripts.js';
|
||||||
import getGlobalScripts from './utils/getGlobalScripts.js';
|
import { createElement, createHTML } from './utils/markupHelpers.js';
|
||||||
import {
|
|
||||||
createElement,
|
|
||||||
createHTML,
|
|
||||||
createScript
|
|
||||||
} from './utils/markupHelpers.js';
|
|
||||||
|
|
||||||
const doctype = '<!DOCTYPE html>';
|
const doctype = '<!DOCTYPE html>';
|
||||||
const globalURLs =
|
const globalURLs =
|
||||||
|
@ -40,10 +35,7 @@ export default function serveAutoIndexPage(req, res) {
|
||||||
entries: req.entries
|
entries: req.entries
|
||||||
};
|
};
|
||||||
const content = createHTML(renderToString(createElement(AutoIndexApp, data)));
|
const content = createHTML(renderToString(createElement(AutoIndexApp, data)));
|
||||||
const entryPoint = getEntryPoint('autoIndex', 'iife');
|
const elements = getScripts('autoIndex', 'iife', globalURLs);
|
||||||
const elements = getGlobalScripts(entryPoint, globalURLs).concat(
|
|
||||||
createScript(entryPoint.code)
|
|
||||||
);
|
|
||||||
|
|
||||||
const html =
|
const html =
|
||||||
doctype +
|
doctype +
|
||||||
|
|
|
@ -3,13 +3,8 @@ import { renderToString, renderToStaticMarkup } from 'react-dom/server';
|
||||||
import MainApp from '../client/main/App.js';
|
import MainApp from '../client/main/App.js';
|
||||||
|
|
||||||
import MainTemplate from './utils/MainTemplate.js';
|
import MainTemplate from './utils/MainTemplate.js';
|
||||||
import getEntryPoint from './utils/getEntryPoint.js';
|
import getScripts from './utils/getScripts.js';
|
||||||
import getGlobalScripts from './utils/getGlobalScripts.js';
|
import { createElement, createHTML } from './utils/markupHelpers.js';
|
||||||
import {
|
|
||||||
createElement,
|
|
||||||
createHTML,
|
|
||||||
createScript
|
|
||||||
} from './utils/markupHelpers.js';
|
|
||||||
|
|
||||||
const doctype = '<!DOCTYPE html>';
|
const doctype = '<!DOCTYPE html>';
|
||||||
const globalURLs =
|
const globalURLs =
|
||||||
|
@ -27,10 +22,7 @@ const globalURLs =
|
||||||
|
|
||||||
export default function serveMainPage(req, res) {
|
export default function serveMainPage(req, res) {
|
||||||
const content = createHTML(renderToString(createElement(MainApp)));
|
const content = createHTML(renderToString(createElement(MainApp)));
|
||||||
const entryPoint = getEntryPoint('main', 'iife');
|
const elements = getScripts('main', 'iife', globalURLs);
|
||||||
const elements = getGlobalScripts(entryPoint, globalURLs).concat(
|
|
||||||
createScript(entryPoint.code)
|
|
||||||
);
|
|
||||||
|
|
||||||
const html =
|
const html =
|
||||||
doctype +
|
doctype +
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
// Virtual module id; see rollup.config.js
|
|
||||||
// eslint-disable-next-line import/no-unresolved
|
|
||||||
import entryManifest from 'entry-manifest';
|
|
||||||
|
|
||||||
export default function getEntryPoint(name, format) {
|
|
||||||
let entryPoints;
|
|
||||||
entryManifest.forEach(manifest => {
|
|
||||||
if (name in manifest) {
|
|
||||||
entryPoints = manifest[name];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (entryPoints) {
|
|
||||||
return entryPoints.find(e => e.format === format);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
import { createElement } from './markupHelpers.js';
|
|
||||||
|
|
||||||
export default function getGlobalScripts(entryPoint, globalURLs) {
|
|
||||||
return entryPoint.globalImports.map(id => {
|
|
||||||
if (process.env.NODE_ENV !== 'production') {
|
|
||||||
if (!globalURLs[id]) {
|
|
||||||
throw new Error('Missing global URL for id "%s"', id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return createElement('script', { src: globalURLs[id] });
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
// Virtual module id; see rollup.config.js
|
||||||
|
// eslint-disable-next-line import/no-unresolved
|
||||||
|
import entryManifest from 'entry-manifest';
|
||||||
|
|
||||||
|
import { createElement, createScript } from './markupHelpers.js';
|
||||||
|
|
||||||
|
function getEntryPoint(name, format) {
|
||||||
|
let entryPoints;
|
||||||
|
entryManifest.forEach(manifest => {
|
||||||
|
if (name in manifest) {
|
||||||
|
entryPoints = manifest[name];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (entryPoints) {
|
||||||
|
return entryPoints.find(e => e.format === format);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getGlobalScripts(entryPoint, globalURLs) {
|
||||||
|
return entryPoint.globalImports.map(id => {
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
if (!globalURLs[id]) {
|
||||||
|
throw new Error('Missing global URL for id "%s"', id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return createElement('script', { src: globalURLs[id] });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function getScripts(entryName, format, globalURLs) {
|
||||||
|
const entryPoint = getEntryPoint(entryName, format);
|
||||||
|
|
||||||
|
if (!entryPoint) return [];
|
||||||
|
|
||||||
|
return getGlobalScripts(entryPoint, globalURLs).concat(
|
||||||
|
createScript(entryPoint.code)
|
||||||
|
);
|
||||||
|
}
|
|
@ -7,6 +7,25 @@ import { fetchPackage as fetchNpmPackage } from '../utils/npm.js';
|
||||||
import getIntegrity from '../utils/getIntegrity.js';
|
import getIntegrity from '../utils/getIntegrity.js';
|
||||||
import getContentType from '../utils/getContentType.js';
|
import getContentType from '../utils/getContentType.js';
|
||||||
|
|
||||||
|
function fileRedirect(req, res, entry) {
|
||||||
|
// Redirect to the file with the extension so it's more
|
||||||
|
// clear which file is being served.
|
||||||
|
res
|
||||||
|
.set({
|
||||||
|
'Cache-Control': 'public, max-age=31536000', // 1 year
|
||||||
|
'Cache-Tag': 'redirect, file-redirect'
|
||||||
|
})
|
||||||
|
.redirect(
|
||||||
|
302,
|
||||||
|
createPackageURL(
|
||||||
|
req.packageName,
|
||||||
|
req.packageVersion,
|
||||||
|
addLeadingSlash(entry.name),
|
||||||
|
createSearch(req.query)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function indexRedirect(req, res, entry) {
|
function indexRedirect(req, res, entry) {
|
||||||
// Redirect to the index file so relative imports
|
// Redirect to the index file so relative imports
|
||||||
// resolve correctly.
|
// resolve correctly.
|
||||||
|
@ -104,7 +123,9 @@ function searchEntries(tarballStream, entryName, wantsIndex) {
|
||||||
const chunks = [];
|
const chunks = [];
|
||||||
|
|
||||||
stream
|
stream
|
||||||
.on('data', chunk => chunks.push(chunk))
|
.on('data', chunk => {
|
||||||
|
chunks.push(chunk);
|
||||||
|
})
|
||||||
.on('end', () => {
|
.on('end', () => {
|
||||||
const content = Buffer.concat(chunks);
|
const content = Buffer.concat(chunks);
|
||||||
|
|
||||||
|
@ -170,6 +191,10 @@ export default async function findFile(req, res, next) {
|
||||||
.send(`Cannot find "${req.filename}" in ${req.packageSpec}`);
|
.send(`Cannot find "${req.filename}" in ${req.packageSpec}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (foundEntry.type === 'file' && foundEntry.name !== entryName) {
|
||||||
|
return fileRedirect(req, res, foundEntry);
|
||||||
|
}
|
||||||
|
|
||||||
// If the foundEntry is a directory and there is no trailing slash
|
// If the foundEntry is a directory and there is no trailing slash
|
||||||
// on the request path, we need to redirect to some "index" file
|
// on the request path, we need to redirect to some "index" file
|
||||||
// inside that directory. This is so our URLs work in a similar way
|
// inside that directory. This is so our URLs work in a similar way
|
||||||
|
@ -177,8 +202,7 @@ export default async function findFile(req, res, next) {
|
||||||
// and `lib/index.json` when `lib` is a directory.
|
// and `lib/index.json` when `lib` is a directory.
|
||||||
if (foundEntry.type === 'directory' && !wantsIndex) {
|
if (foundEntry.type === 'directory' && !wantsIndex) {
|
||||||
const indexEntry =
|
const indexEntry =
|
||||||
entries[path.join(entryName, 'index.js')] ||
|
entries[`${entryName}/index.js`] || entries[`${entryName}/index.json`];
|
||||||
entries[path.join(entryName, 'index.json')];
|
|
||||||
|
|
||||||
if (indexEntry && indexEntry.type === 'file') {
|
if (indexEntry && indexEntry.type === 'file') {
|
||||||
return indexRedirect(req, res, indexEntry);
|
return indexRedirect(req, res, indexEntry);
|
||||||
|
|
Loading…
Reference in New Issue