Speed up test suite by using local npm.js stub
This commit is contained in:
parent
f362fa9717
commit
c3dc2dd014
|
@ -3,9 +3,9 @@ module.exports = {
|
|||
'\\.css$': '<rootDir>/modules/__mocks__/styleMock.js',
|
||||
'\\.png$': '<rootDir>/modules/__mocks__/imageMock.js',
|
||||
'entry-manifest': '<rootDir>/modules/__mocks__/entryManifest.js',
|
||||
'getStats\\.js': '<rootDir>/modules/__mocks__/getStatsMock.js'
|
||||
'getStats\\.js': '<rootDir>/modules/__mocks__/getStatsMock.js',
|
||||
'utils\\/npm\\.js': '<rootDir>/modules/__mocks__/npmMock.js'
|
||||
},
|
||||
testMatch: ['**/__tests__/*-test.js'],
|
||||
testURL: 'http://localhost/',
|
||||
setupTestFrameworkScriptFile: './jest.setup.js'
|
||||
testURL: 'http://localhost/'
|
||||
};
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
// TODO: Mock out the registry so tests don't actually hit
|
||||
// the real registry so they don't take so long. Then we can
|
||||
// remove this.
|
||||
jest.setTimeout(10000);
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,33 @@
|
|||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
function getPackageInfo(packageName) {
|
||||
const file = path.resolve(__dirname, `./metadata/${packageName}.json`);
|
||||
|
||||
try {
|
||||
return JSON.parse(fs.readFileSync(file, 'utf-8'));
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function getVersionsAndTags(packageName) {
|
||||
const info = getPackageInfo(packageName);
|
||||
return info
|
||||
? { versions: Object.keys(info.versions), tags: info['dist-tags'] }
|
||||
: [];
|
||||
}
|
||||
|
||||
export function getPackageConfig(packageName, version) {
|
||||
const info = getPackageInfo(packageName);
|
||||
return info ? info.versions[version] : null;
|
||||
}
|
||||
|
||||
export function getPackage(packageName, version) {
|
||||
const file = path.resolve(
|
||||
__dirname,
|
||||
`./packages/${packageName}-${version}.tgz`
|
||||
);
|
||||
|
||||
return fs.existsSync(file) ? fs.createReadStream(file) : null;
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -10,7 +10,7 @@ describe('A request for a JavaScript file', () => {
|
|||
|
||||
it('returns 200', done => {
|
||||
request(server)
|
||||
.get('/react@16.8.6/index.js')
|
||||
.get('/react@16.8.0/index.js')
|
||||
.end((err, res) => {
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(res.headers['content-type']).toMatch(
|
||||
|
|
|
@ -10,7 +10,7 @@ describe('A request for metadata', () => {
|
|||
|
||||
it('returns 200', done => {
|
||||
request(server)
|
||||
.get('/react@16.8.6/?meta')
|
||||
.get('/react@16.8.0/?meta')
|
||||
.end((err, res) => {
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(res.headers['content-type']).toMatch(/\bapplication\/json\b/);
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import { renderToString, renderToStaticMarkup } from 'react-dom/server';
|
||||
import semver from 'semver';
|
||||
|
||||
import BrowseApp from '../client/browse/App.js';
|
||||
import MainTemplate from '../templates/MainTemplate.js';
|
||||
import asyncHandler from '../utils/asyncHandler.js';
|
||||
import getScripts from '../utils/getScripts.js';
|
||||
import { createElement, createHTML } from '../utils/markup.js';
|
||||
import { getAvailableVersions } from '../utils/npm.js';
|
||||
import { getVersionsAndTags } from '../utils/npm.js';
|
||||
|
||||
const doctype = '<!DOCTYPE html>';
|
||||
const globalURLs =
|
||||
|
@ -21,6 +22,15 @@ const globalURLs =
|
|||
'react-dom': '/react-dom@16.8.6/umd/react-dom.development.js'
|
||||
};
|
||||
|
||||
function byVersion(a, b) {
|
||||
return semver.lt(a, b) ? -1 : semver.gt(a, b) ? 1 : 0;
|
||||
}
|
||||
|
||||
async function getAvailableVersions(packageName) {
|
||||
const versionsAndTags = await getVersionsAndTags(packageName);
|
||||
return versionsAndTags ? versionsAndTags.versions.sort(byVersion) : [];
|
||||
}
|
||||
|
||||
async function serveBrowsePage(req, res) {
|
||||
const availableVersions = await getAvailableVersions(req.packageName);
|
||||
const data = {
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import semver from 'semver';
|
||||
|
||||
import asyncHandler from '../utils/asyncHandler.js';
|
||||
import createPackageURL from '../utils/createPackageURL.js';
|
||||
import { getPackageConfig, resolveVersion } from '../utils/npm.js';
|
||||
import { getPackageConfig, getVersionsAndTags } from '../utils/npm.js';
|
||||
|
||||
function semverRedirect(req, res, newVersion) {
|
||||
res
|
||||
|
@ -15,6 +17,24 @@ function semverRedirect(req, res, newVersion) {
|
|||
);
|
||||
}
|
||||
|
||||
async function resolveVersion(packageName, range) {
|
||||
const versionsAndTags = await getVersionsAndTags(packageName);
|
||||
|
||||
if (versionsAndTags) {
|
||||
const { versions, tags } = versionsAndTags;
|
||||
|
||||
if (range in tags) {
|
||||
range = tags[range];
|
||||
}
|
||||
|
||||
return versions.includes(range)
|
||||
? range
|
||||
: semver.maxSatisfying(versions, range);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the package version/tag in the URL and make sure it's good. Also
|
||||
* fetch the package config and add it to req.packageConfig. Redirect to
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import url from 'url';
|
||||
import https from 'https';
|
||||
import LRUCache from 'lru-cache';
|
||||
import semver from 'semver';
|
||||
|
||||
import debug from './debug.js';
|
||||
import bufferStream from './bufferStream.js';
|
||||
|
@ -77,18 +76,16 @@ async function fetchPackageInfo(packageName) {
|
|||
|
||||
async function fetchVersionsAndTags(packageName) {
|
||||
const info = await fetchPackageInfo(packageName);
|
||||
|
||||
if (info && info.versions) {
|
||||
return {
|
||||
versions: Object.keys(info.versions),
|
||||
tags: info['dist-tags']
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
return info && info.versions
|
||||
? { versions: Object.keys(info.versions), tags: info['dist-tags'] }
|
||||
: null;
|
||||
}
|
||||
|
||||
async function getVersionsAndTags(packageName) {
|
||||
/**
|
||||
* Returns an object of available { versions, tags }.
|
||||
* Uses a cache to avoid over-fetching from the registry.
|
||||
*/
|
||||
export async function getVersionsAndTags(packageName) {
|
||||
const cacheKey = `versions-${packageName}`;
|
||||
const cacheValue = cache.get(cacheKey);
|
||||
|
||||
|
@ -107,45 +104,6 @@ async function getVersionsAndTags(packageName) {
|
|||
return value;
|
||||
}
|
||||
|
||||
function byVersion(a, b) {
|
||||
return semver.lt(a, b) ? -1 : semver.gt(a, b) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of available versions, sorted by semver.
|
||||
*/
|
||||
export async function getAvailableVersions(packageName) {
|
||||
const versionsAndTags = await getVersionsAndTags(packageName);
|
||||
|
||||
if (versionsAndTags) {
|
||||
return versionsAndTags.versions.sort(byVersion);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the semver range or tag to a valid version.
|
||||
* Output is cached to avoid over-fetching from the registry.
|
||||
*/
|
||||
export async function resolveVersion(packageName, range) {
|
||||
const versionsAndTags = await getVersionsAndTags(packageName);
|
||||
|
||||
if (versionsAndTags) {
|
||||
const { versions, tags } = versionsAndTags;
|
||||
|
||||
if (range in tags) {
|
||||
range = tags[range];
|
||||
}
|
||||
|
||||
return versions.includes(range)
|
||||
? range
|
||||
: semver.maxSatisfying(versions, range);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// All the keys that sometimes appear in package info
|
||||
// docs that we don't need. There are probably more.
|
||||
const packageConfigExcludeKeys = [
|
||||
|
@ -160,10 +118,10 @@ const packageConfigExcludeKeys = [
|
|||
'scripts'
|
||||
];
|
||||
|
||||
function cleanPackageConfig(doc) {
|
||||
return Object.keys(doc).reduce((memo, key) => {
|
||||
function cleanPackageConfig(config) {
|
||||
return Object.keys(config).reduce((memo, key) => {
|
||||
if (!key.startsWith('_') && !packageConfigExcludeKeys.includes(key)) {
|
||||
memo[key] = doc[key];
|
||||
memo[key] = config[key];
|
||||
}
|
||||
|
||||
return memo;
|
||||
|
@ -172,17 +130,14 @@ function cleanPackageConfig(doc) {
|
|||
|
||||
async function fetchPackageConfig(packageName, version) {
|
||||
const info = await fetchPackageInfo(packageName);
|
||||
|
||||
if (!info || !(version in info.versions)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return cleanPackageConfig(info.versions[version]);
|
||||
return info && info.versions && version in info.versions
|
||||
? cleanPackageConfig(info.versions[version])
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns metadata about a package, mostly the same as package.json.
|
||||
* Output is cached to avoid over-fetching from the registry.
|
||||
* Uses a cache to avoid over-fetching from the registry.
|
||||
*/
|
||||
export async function getPackageConfig(packageName, version) {
|
||||
const cacheKey = `config-${packageName}-${version}`;
|
||||
|
|
Loading…
Reference in New Issue