Pete Bacon Darwin 6de5a12a9d refactor(ngcc): move logging code into ngtsc (#37114)
The `Logger` interface and its related classes are general purpose
and could be used by other tooling. Moving it into ngtsc is a more
suitable place from which to share it - similar to the FileSystem stuff.

PR Close #37114
2020-06-22 13:38:47 -07:00

787 lines
34 KiB
TypeScript

/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {absoluteFrom, AbsoluteFsPath, FileSystem, getFileSystem, join, relative} from '../../../src/ngtsc/file_system';
import {runInEachFileSystem} from '../../../src/ngtsc/file_system/testing';
import {MockLogger} from '../../../src/ngtsc/logging/testing';
import {loadTestFiles} from '../../../test/helpers';
import {NgccConfiguration, ProcessedNgccPackageConfig} from '../../src/packages/configuration';
import {EntryPoint, EntryPointJsonProperty, getEntryPointFormat, getEntryPointInfo, IGNORED_ENTRY_POINT, INCOMPATIBLE_ENTRY_POINT, isEntryPoint, NO_ENTRY_POINT, SUPPORTED_FORMAT_PROPERTIES} from '../../src/packages/entry_point';
runInEachFileSystem(() => {
describe('getEntryPointInfo()', () => {
let SOME_PACKAGE: AbsoluteFsPath;
let _: typeof absoluteFrom;
let fs: FileSystem;
beforeEach(() => {
_ = absoluteFrom;
SOME_PACKAGE = _('/project/node_modules/some_package');
fs = getFileSystem();
});
it('should return an object containing absolute paths to the formats of the specified entry-point',
() => {
loadTestFiles([
{
name: _('/project/node_modules/some_package/valid_entry_point/package.json'),
contents: createPackageJson('valid_entry_point')
},
{
name: _(
'/project/node_modules/some_package/valid_entry_point/valid_entry_point.metadata.json'),
contents: 'some meta data'
},
]);
const config = new NgccConfiguration(fs, _('/project'));
const entryPoint = getEntryPointInfo(
fs, config, new MockLogger(), SOME_PACKAGE,
_('/project/node_modules/some_package/valid_entry_point'));
expect(entryPoint).toEqual({
name: 'some_package/valid_entry_point',
path: _('/project/node_modules/some_package/valid_entry_point'),
packageName: 'some_package',
packagePath: SOME_PACKAGE,
packageJson: loadPackageJson(fs, '/project/node_modules/some_package/valid_entry_point'),
typings:
_(`/project/node_modules/some_package/valid_entry_point/valid_entry_point.d.ts`),
compiledByAngular: true,
ignoreMissingDependencies: false,
generateDeepReexports: false,
});
});
it('should return `IGNORED_ENTRY_POINT` if configured to ignore the specified entry-point', () => {
loadTestFiles([
{
name: _('/project/node_modules/some_package/valid_entry_point/package.json'),
contents: createPackageJson('valid_entry_point'),
},
{
name: _(
'/project/node_modules/some_package/valid_entry_point/valid_entry_point.metadata.json'),
contents: 'some meta data',
},
]);
const config = new NgccConfiguration(fs, _('/project'));
spyOn(config, 'getPackageConfig')
.and.returnValue(new ProcessedNgccPackageConfig(
_('/project/node_modules/some_package'),
{entryPoints: {'./valid_entry_point': {ignore: true}}}));
const entryPoint = getEntryPointInfo(
fs, config, new MockLogger(), SOME_PACKAGE,
_('/project/node_modules/some_package/valid_entry_point'));
expect(entryPoint).toBe(IGNORED_ENTRY_POINT);
});
it('should retrieve the entry-point\'s version from the package\'s `package.json`', () => {
const entryPointPath = join(SOME_PACKAGE, 'valid_entry_point');
loadTestFiles([
{
name: _('/project/ngcc.config.js'),
contents: `
module.exports = {
packages: {
'some_package@3': {
entryPoints: {valid_entry_point: {override: {packageVersion: '3'}}},
},
'some_package@2': {
entryPoints: {valid_entry_point: {override: {packageVersion: '2'}}},
},
'some_package@1': {
entryPoints: {valid_entry_point: {override: {packageVersion: '1'}}},
},
},
};
`,
},
{
name: join(SOME_PACKAGE, 'package.json'),
contents: createPackageJson('', {version: '1.0.0'}),
},
{
name: join(entryPointPath, 'package.json'),
contents: createPackageJson('valid_entry_point', {version: '2.0.0'}),
},
{
name: join(entryPointPath, 'valid_entry_point.metadata.json'),
contents: 'some meta data',
},
]);
const config = new NgccConfiguration(fs, _('/project'));
const info: EntryPoint =
getEntryPointInfo(fs, config, new MockLogger(), SOME_PACKAGE, entryPointPath) as any;
expect(info.packageJson).toEqual(jasmine.objectContaining({packageVersion: '1'}));
});
it('should use `null` for version if it cannot be retrieved from a `package.json`', () => {
const entryPointPath = join(SOME_PACKAGE, 'valid_entry_point');
loadTestFiles([
{
name: _('/project/ngcc.config.js'),
contents: `
module.exports = {
packages: {
'some_package@3': {
entryPoints: {valid_entry_point: {override: {packageVersion: '3'}}},
},
'some_package@2': {
entryPoints: {valid_entry_point: {override: {packageVersion: '2'}}},
},
'some_package@1': {
entryPoints: {valid_entry_point: {override: {packageVersion: '1'}}},
},
},
};
`,
},
{
name: join(SOME_PACKAGE, 'package.json'),
contents: createPackageJson(''),
},
{
name: join(entryPointPath, 'package.json'),
contents: createPackageJson('valid_entry_point'),
},
{
name: join(entryPointPath, 'valid_entry_point.metadata.json'),
contents: 'some meta data',
},
]);
const config = new NgccConfiguration(fs, _('/project'));
const info: EntryPoint =
getEntryPointInfo(fs, config, new MockLogger(), SOME_PACKAGE, entryPointPath) as any;
expect(info.packageJson).toEqual(jasmine.objectContaining({packageVersion: '3'}));
});
it('should override the properties on package.json if the entry-point is configured', () => {
loadTestFiles([
{
name: _('/project/node_modules/some_package/valid_entry_point/package.json'),
contents: createPackageJson('valid_entry_point'),
},
{
name: _(
'/project/node_modules/some_package/valid_entry_point/valid_entry_point.metadata.json'),
contents: 'some meta data',
},
]);
const config = new NgccConfiguration(fs, _('/project'));
const override = {
typings: './some_other.d.ts',
esm2015: './some_other.js',
};
spyOn(config, 'getPackageConfig')
.and.returnValue(new ProcessedNgccPackageConfig(
_('/project/node_modules/some_package'),
{entryPoints: {'./valid_entry_point': {override}}}));
const entryPoint = getEntryPointInfo(
fs, config, new MockLogger(), SOME_PACKAGE,
_('/project/node_modules/some_package/valid_entry_point'));
const overriddenPackageJson = {
...loadPackageJson(fs, '/project/node_modules/some_package/valid_entry_point'),
...override
};
expect(entryPoint).toEqual({
name: 'some_package/valid_entry_point',
path: _('/project/node_modules/some_package/valid_entry_point'),
packageName: 'some_package',
packagePath: SOME_PACKAGE,
packageJson: overriddenPackageJson,
typings: _('/project/node_modules/some_package/valid_entry_point/some_other.d.ts'),
compiledByAngular: true,
ignoreMissingDependencies: false,
generateDeepReexports: false,
});
});
it('should return `NO_ENTRY_POINT` if there is no package.json at the entry-point path', () => {
loadTestFiles([
{
name: _(
'/project/node_modules/some_package/missing_package_json/missing_package_json.metadata.json'),
contents: 'some meta data'
},
]);
const config = new NgccConfiguration(fs, _('/project'));
const entryPoint = getEntryPointInfo(
fs, config, new MockLogger(), SOME_PACKAGE,
_('/project/node_modules/some_package/missing_package_json'));
expect(entryPoint).toBe(NO_ENTRY_POINT);
});
it('should return a configured entry-point if there is no package.json at the entry-point path',
() => {
loadTestFiles([
// no package.json!
{
name: _(
'/project/node_modules/some_package/missing_package_json/missing_package_json.metadata.json'),
contents: 'some meta data',
},
]);
const config = new NgccConfiguration(fs, _('/project'));
const override =
JSON.parse(createPackageJson('missing_package_json', {excludes: ['name']}));
spyOn(config, 'getPackageConfig')
.and.returnValue(new ProcessedNgccPackageConfig(
_('/project/node_modules/some_package/'),
{entryPoints: {'./missing_package_json': {override}}}));
const entryPoint = getEntryPointInfo(
fs, config, new MockLogger(), SOME_PACKAGE,
_('/project/node_modules/some_package/missing_package_json'));
expect(entryPoint).toEqual({
name: 'some_package/missing_package_json',
path: _('/project/node_modules/some_package/missing_package_json'),
packageName: 'some_package',
packagePath: SOME_PACKAGE,
packageJson: {name: 'some_package/missing_package_json', ...override},
typings: _(
'/project/node_modules/some_package/missing_package_json/missing_package_json.d.ts'),
compiledByAngular: true,
ignoreMissingDependencies: false,
generateDeepReexports: false,
});
});
[false, true].forEach(isScoped => {
const nameWithScope = (baseName: string) => `${isScoped ? '@some-scope/' : ''}${baseName}`;
const getPackageName = (packagePath: AbsoluteFsPath, entryPointPath: AbsoluteFsPath) => {
const config = new NgccConfiguration(fs, _('/project'));
const logger = new MockLogger();
const entryPoint = getEntryPointInfo(fs, config, logger, packagePath, entryPointPath);
if (!isEntryPoint(entryPoint)) {
return fail(`Expected an entry point but got ${entryPoint}`);
}
return entryPoint.packageName;
};
const setUpPackageWithEntryPointPackageJson =
(entryPointName: string, entryPointPath: AbsoluteFsPath) => {
// Ensure a `package.json` exists for the entry-point (containing `entryPointName`).
loadTestFiles([
{
name: join(entryPointPath, 'package.json'),
contents: JSON.stringify({name: entryPointName, typings: './index.d.ts'}),
},
]);
};
const setUpPackageWithoutEntryPointPackageJson =
(packagePath: AbsoluteFsPath, entryPointPath: AbsoluteFsPath) => {
// Ensure there is an ngcc config for the entry-point providing a `typings` field to
// avoid returning `INCOMPATIBLE_ENTRY_POINT` (since there is no `package.json`).
loadTestFiles([
{
name: join(packagePath, 'ngcc.config.js'),
contents: `
module.exports = {
entryPoints: {
'${relative(packagePath, entryPointPath)}': {
override: {typings: './index.d.ts'},
},
},
};
`,
},
]);
};
describe(`should compute the containing ${isScoped ? 'scoped ' : ''}package's name`, () => {
it('for a primary entry-point with a `package.json`', () => {
const packagePath = _(`/project/node_modules/${nameWithScope('on-disk-package-name')}`);
const entryPointPath = packagePath;
const expectedPackageName = nameWithScope('package-json-package-name');
setUpPackageWithEntryPointPackageJson(expectedPackageName, entryPointPath);
expect(getPackageName(packagePath, entryPointPath)).toBe(expectedPackageName);
});
it('for a primary entry-point without a `package.json`', () => {
const packagePath = _(`/project/node_modules/${nameWithScope('on-disk-package-name')}`);
const entryPointPath = packagePath;
const expectedPackageName = nameWithScope('on-disk-package-name');
setUpPackageWithoutEntryPointPackageJson(packagePath, entryPointPath);
expect(getPackageName(packagePath, entryPointPath)).toBe(expectedPackageName);
});
it('for a secondary entry-point with a `package.json`', () => {
const packagePath = _(`/project/node_modules/${nameWithScope('on-disk-package-name')}`);
const entryPointPath = join(packagePath, 'some-entry-point');
const expectedPackageName = nameWithScope('package-json-package-name');
setUpPackageWithEntryPointPackageJson(
`${expectedPackageName}/some-entry-point`, entryPointPath);
expect(getPackageName(packagePath, entryPointPath)).toBe(expectedPackageName);
});
it('for a secondary entry-point without a `package.json`', () => {
const packagePath = _(`/project/node_modules/${nameWithScope('on-disk-package-name')}`);
const entryPointPath = join(packagePath, 'some-entry-point');
const expectedPackageName = nameWithScope('on-disk-package-name');
setUpPackageWithoutEntryPointPackageJson(packagePath, entryPointPath);
expect(getPackageName(packagePath, entryPointPath)).toBe(expectedPackageName);
});
it('for a primary entry-point without a `package.json` in nested `node_modules/`', () => {
const packagePath = _(`/project/node_modules/other-package/node_modules/${
nameWithScope('on-disk-package-name')}`);
const entryPointPath = packagePath;
const expectedPackageName = nameWithScope('on-disk-package-name');
setUpPackageWithoutEntryPointPackageJson(packagePath, entryPointPath);
expect(getPackageName(packagePath, entryPointPath)).toBe(expectedPackageName);
});
it('for a secondary entry-point without a `package.json` in nested `node_modules/`', () => {
const packagePath = _(`/project/node_modules/other-package/node_modules/${
nameWithScope('on-disk-package-name')}`);
const entryPointPath = join(packagePath, 'some-entry-point');
const expectedPackageName = nameWithScope('on-disk-package-name');
setUpPackageWithoutEntryPointPackageJson(packagePath, entryPointPath);
expect(getPackageName(packagePath, entryPointPath)).toBe(expectedPackageName);
});
it('for a primary entry-point with a `package.json` outside `node_modules/`', () => {
const packagePath = _(`/project/libs/${nameWithScope('on-disk-package-name')}`);
const entryPointPath = packagePath;
const expectedPackageName = nameWithScope('package-json-package-name');
setUpPackageWithEntryPointPackageJson(expectedPackageName, entryPointPath);
expect(getPackageName(packagePath, entryPointPath)).toBe(expectedPackageName);
});
it('for a primary entry-point without a `package.json` outside `node_modules/`', () => {
const packagePath = _(`/project/libs/${nameWithScope('on-disk-package-name')}`);
const entryPointPath = packagePath;
const expectedPackageName = nameWithScope('on-disk-package-name');
setUpPackageWithoutEntryPointPackageJson(packagePath, entryPointPath);
expect(getPackageName(packagePath, entryPointPath)).toBe(expectedPackageName);
});
it('for a secondary entry-point with a `package.json` outside `node_modules/`', () => {
const packagePath = _(`/project/libs/${nameWithScope('on-disk-package-name')}`);
const entryPointPath = join(packagePath, 'some-entry-point');
const expectedPackageName = nameWithScope('package-json-package-name');
setUpPackageWithEntryPointPackageJson(expectedPackageName, entryPointPath);
expect(getPackageName(packagePath, entryPointPath)).toBe(expectedPackageName);
});
it('for a secondary entry-point without a `package.json` outside `node_modules/`', () => {
const packagePath = _(`/project/libs/${nameWithScope('on-disk-package-name')}`);
const entryPointPath = join(packagePath, 'some-entry-point');
const expectedPackageName = nameWithScope('on-disk-package-name');
setUpPackageWithoutEntryPointPackageJson(packagePath, entryPointPath);
expect(getPackageName(packagePath, entryPointPath)).toBe(expectedPackageName);
});
});
});
it('should return `INCOMPATIBLE_ENTRY_POINT` if there is no typings or types field in the package.json',
() => {
loadTestFiles([
{
name: _('/project/node_modules/some_package/missing_typings/package.json'),
contents: createPackageJson('missing_typings', {excludes: ['typings']})
},
{
name: _(
'/project/node_modules/some_package/missing_typings/missing_typings.metadata.json'),
contents: 'some meta data'
},
]);
const config = new NgccConfiguration(fs, _('/project'));
const entryPoint = getEntryPointInfo(
fs, config, new MockLogger(), SOME_PACKAGE,
_('/project/node_modules/some_package/missing_typings'));
expect(entryPoint).toBe(INCOMPATIBLE_ENTRY_POINT);
});
it('should return `INCOMPATIBLE_ENTRY_POINT` if the typings or types field is not a string in the package.json',
() => {
loadTestFiles([
{
name: _('/project/node_modules/some_package/typings_array/package.json'),
contents: createPackageJson('typings_array', {typingsIsArray: true})
},
{
name: _(
'/project/node_modules/some_package/typings_array/missing_typings.metadata.json'),
contents: 'some meta data'
},
]);
const config = new NgccConfiguration(fs, _('/project'));
const entryPoint = getEntryPointInfo(
fs, config, new MockLogger(), SOME_PACKAGE,
_('/project/node_modules/some_package/typings_array'));
expect(entryPoint).toBe(INCOMPATIBLE_ENTRY_POINT);
});
for (let prop of SUPPORTED_FORMAT_PROPERTIES) {
// Ignore the UMD format
if (prop === 'main' || prop === 'browser') continue;
// Let's give 'module' a specific path, otherwise compute it based on the property.
const typingsPath = prop === 'module' ? 'index' : `${prop}/missing_typings`;
it(`should return an object if it can guess the typings path from the "${prop}" field`,
() => {
loadTestFiles([
{
name: _('/project/node_modules/some_package/missing_typings/package.json'),
contents: createPackageJson('missing_typings', {excludes: ['typings']}),
},
{
name: _(`/project/node_modules/some_package/missing_typings/${
typingsPath}.metadata.json`),
contents: 'some meta data',
},
{
name: _(`/project/node_modules/some_package/missing_typings/${typingsPath}.d.ts`),
contents: '// some typings file',
},
]);
const config = new NgccConfiguration(fs, _('/project'));
const entryPoint = getEntryPointInfo(
fs, config, new MockLogger(), SOME_PACKAGE,
_('/project/node_modules/some_package/missing_typings'));
expect(entryPoint).toEqual({
name: 'some_package/missing_typings',
path: _('/project/node_modules/some_package/missing_typings'),
packageName: 'some_package',
packagePath: SOME_PACKAGE,
packageJson: loadPackageJson(fs, '/project/node_modules/some_package/missing_typings'),
typings: _(`/project/node_modules/some_package/missing_typings/${typingsPath}.d.ts`),
compiledByAngular: true,
ignoreMissingDependencies: false,
generateDeepReexports: false,
});
});
}
it('should return an object with `compiledByAngular` set to false if there is no metadata.json file next to the typing file',
() => {
loadTestFiles([
{
name: _('/project/node_modules/some_package/missing_metadata/package.json'),
contents: createPackageJson('missing_metadata')
},
]);
const config = new NgccConfiguration(fs, _('/project'));
const entryPoint = getEntryPointInfo(
fs, config, new MockLogger(), SOME_PACKAGE,
_('/project/node_modules/some_package/missing_metadata'));
expect(entryPoint).toEqual({
name: 'some_package/missing_metadata',
path: _('/project/node_modules/some_package/missing_metadata'),
packageName: 'some_package',
packagePath: SOME_PACKAGE,
packageJson: loadPackageJson(fs, '/project/node_modules/some_package/missing_metadata'),
typings: _(`/project/node_modules/some_package/missing_metadata/missing_metadata.d.ts`),
compiledByAngular: false,
ignoreMissingDependencies: false,
generateDeepReexports: false,
});
});
it('should return an object with `compiledByAngular` set to true if there is no metadata.json file but the entry-point has a configuration',
() => {
loadTestFiles([
{
name: _('/project/node_modules/some_package/missing_metadata/package.json'),
contents: createPackageJson('missing_metadata'),
},
// no metadata.json!
]);
const config = new NgccConfiguration(fs, _('/project'));
spyOn(config, 'getPackageConfig')
.and.returnValue(new ProcessedNgccPackageConfig(
_('/project/node_modules/some_package'),
{entryPoints: {'./missing_metadata': {}}}));
const entryPoint = getEntryPointInfo(
fs, config, new MockLogger(), SOME_PACKAGE,
_('/project/node_modules/some_package/missing_metadata'));
expect(entryPoint).toEqual({
name: 'some_package/missing_metadata',
path: _('/project/node_modules/some_package/missing_metadata'),
packageName: 'some_package',
packagePath: SOME_PACKAGE,
packageJson: loadPackageJson(fs, '/project/node_modules/some_package/missing_metadata'),
typings: _('/project/node_modules/some_package/missing_metadata/missing_metadata.d.ts'),
compiledByAngular: true,
ignoreMissingDependencies: false,
generateDeepReexports: false,
});
});
it('should work if the typings field is named `types', () => {
loadTestFiles([
{
name: _('/project/node_modules/some_package/types_rather_than_typings/package.json'),
contents: createPackageJson('types_rather_than_typings', {typingsProp: 'types'})
},
{
name: _(
'/project/node_modules/some_package/types_rather_than_typings/types_rather_than_typings.metadata.json'),
contents: 'some meta data'
},
]);
const config = new NgccConfiguration(fs, _('/project'));
const entryPoint = getEntryPointInfo(
fs, config, new MockLogger(), SOME_PACKAGE,
_('/project/node_modules/some_package/types_rather_than_typings'));
expect(entryPoint).toEqual({
name: 'some_package/types_rather_than_typings',
path: _('/project/node_modules/some_package/types_rather_than_typings'),
packageName: 'some_package',
packagePath: SOME_PACKAGE,
packageJson:
loadPackageJson(fs, '/project/node_modules/some_package/types_rather_than_typings'),
typings: _(
`/project/node_modules/some_package/types_rather_than_typings/types_rather_than_typings.d.ts`),
compiledByAngular: true,
ignoreMissingDependencies: false,
generateDeepReexports: false,
});
});
it('should work with Angular Material style package.json', () => {
loadTestFiles([
{
name: _('/project/node_modules/some_package/material_style/package.json'),
contents: `{
"name": "some_package/material_style",
"typings": "./material_style.d.ts",
"main": "./bundles/material_style.umd.js",
"module": "./esm5/material_style.es5.js",
"es2015": "./esm2015/material_style.js"
}`
},
{
name: _('/project/node_modules/some_package/material_style/material_style.metadata.json'),
contents: 'some meta data'
},
]);
const config = new NgccConfiguration(fs, _('/project'));
const entryPoint = getEntryPointInfo(
fs, config, new MockLogger(), SOME_PACKAGE,
_('/project/node_modules/some_package/material_style'));
expect(entryPoint).toEqual({
name: 'some_package/material_style',
path: _('/project/node_modules/some_package/material_style'),
packageName: 'some_package',
packagePath: SOME_PACKAGE,
packageJson: loadPackageJson(fs, '/project/node_modules/some_package/material_style'),
typings: _(`/project/node_modules/some_package/material_style/material_style.d.ts`),
compiledByAngular: true,
ignoreMissingDependencies: false,
generateDeepReexports: false,
});
});
it('should return `INCOMPATIBLE_ENTRY_POINT` if the package.json is not valid JSON', () => {
loadTestFiles([
// package.json might not be a valid JSON
// for example, @schematics/angular contains a package.json blueprint
// with unexpected symbols
{
name: _('/project/node_modules/some_package/unexpected_symbols/package.json'),
contents: '{"devDependencies": {<% if (!minimal) { %>"@types/jasmine": "~2.8.8" <% } %>}}'
},
]);
const config = new NgccConfiguration(fs, _('/project'));
const entryPoint = getEntryPointInfo(
fs, config, new MockLogger(), SOME_PACKAGE,
_('/project/node_modules/some_package/unexpected_symbols'));
expect(entryPoint).toBe(INCOMPATIBLE_ENTRY_POINT);
});
});
describe('getEntryPointFormat()', () => {
let SOME_PACKAGE: AbsoluteFsPath;
let _: typeof absoluteFrom;
let fs: FileSystem;
let entryPoint: EntryPoint;
beforeEach(() => {
_ = absoluteFrom;
SOME_PACKAGE = _('/project/node_modules/some_package');
fs = getFileSystem();
loadTestFiles([{
name: _('/project/node_modules/some_package/valid_entry_point/package.json'),
contents: createPackageJson('valid_entry_point')
}]);
const config = new NgccConfiguration(fs, _('/project'));
const result = getEntryPointInfo(
fs, config, new MockLogger(), SOME_PACKAGE,
_('/project/node_modules/some_package/valid_entry_point'));
if (!isEntryPoint(result)) {
return fail(`Expected an entry point but got ${result}`);
}
entryPoint = result;
});
it('should return `esm2015` format for `fesm2015` property', () => {
expect(getEntryPointFormat(fs, entryPoint, 'fesm2015')).toBe('esm2015');
});
it('should return `esm5` format for `fesm5` property', () => {
expect(getEntryPointFormat(fs, entryPoint, 'fesm5')).toBe('esm5');
});
it('should return `esm2015` format for `es2015` property', () => {
expect(getEntryPointFormat(fs, entryPoint, 'es2015')).toBe('esm2015');
});
it('should return `esm2015` format for `esm2015` property', () => {
expect(getEntryPointFormat(fs, entryPoint, 'esm2015')).toBe('esm2015');
});
it('should return `esm5` format for `esm5` property', () => {
expect(getEntryPointFormat(fs, entryPoint, 'esm5')).toBe('esm5');
});
it('should return `esm5` format for `module` property', () => {
expect(getEntryPointFormat(fs, entryPoint, 'module')).toBe('esm5');
});
it('should return `esm2015` format for `module` property if it points to esm2015 output',
() => {
entryPoint.packageJson['module'] = '../fesm2015/valid-entry-point.js';
expect(getEntryPointFormat(fs, entryPoint, 'module')).toBe('esm2015');
});
(['browser', 'main'] as EntryPointJsonProperty[]).forEach(browserOrMain => {
it('should return `esm5` for `' + browserOrMain +
'` if the file contains import or export statements',
() => {
const name = _(
'/project/node_modules/some_package/valid_entry_point/bundles/valid_entry_point/index.js');
loadTestFiles([{name, contents: `import * as core from '@angular/core;`}]);
expect(getEntryPointFormat(fs, entryPoint, browserOrMain)).toBe('esm5');
loadTestFiles([{name, contents: `import {Component} from '@angular/core;`}]);
expect(getEntryPointFormat(fs, entryPoint, browserOrMain)).toBe('esm5');
loadTestFiles([{name, contents: `export function foo() {}`}]);
expect(getEntryPointFormat(fs, entryPoint, browserOrMain)).toBe('esm5');
loadTestFiles([{name, contents: `export * from 'abc';`}]);
expect(getEntryPointFormat(fs, entryPoint, browserOrMain)).toBe('esm5');
});
it('should return `umd` for `' + browserOrMain +
'` if the file contains a UMD wrapper function',
() => {
loadTestFiles([{
name: _(
'/project/node_modules/some_package/valid_entry_point/bundles/valid_entry_point/index.js'),
contents: `
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core')) :
typeof define === 'function' && define.amd ? define('@angular/common', ['exports', '@angular/core'], factory) :
(global = global || self, factory((global.ng = global.ng || {}, global.ng.common = {}), global.ng.core));
}(this, function (exports, core) { 'use strict'; }));
`
}]);
expect(getEntryPointFormat(fs, entryPoint, browserOrMain)).toBe('umd');
});
it('should return `commonjs` for `' + browserOrMain +
'` if the file does not contain a UMD wrapper function',
() => {
loadTestFiles([{
name: _(
'/project/node_modules/some_package/valid_entry_point/bundles/valid_entry_point/index.js'),
contents: `
const core = require('@angular/core);
module.exports = {};
`
}]);
expect(getEntryPointFormat(fs, entryPoint, browserOrMain)).toBe('commonjs');
});
it('should resolve the format path with suitable postfixes', () => {
loadTestFiles([{
name: _(
'/project/node_modules/some_package/valid_entry_point/bundles/valid_entry_point/index.js'),
contents: `
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core')) :
typeof define === 'function' && define.amd ? define('@angular/common', ['exports', '@angular/core'], factory) :
(global = global || self, factory((global.ng = global.ng || {}, global.ng.common = {}), global.ng.core));
}(this, function (exports, core) { 'use strict'; }));
`
}]);
entryPoint.packageJson.main = './bundles/valid_entry_point/index';
expect(getEntryPointFormat(fs, entryPoint, browserOrMain)).toBe('umd');
entryPoint.packageJson.main = './bundles/valid_entry_point';
expect(getEntryPointFormat(fs, entryPoint, browserOrMain)).toBe('umd');
});
});
it('should return `undefined` if the `browser` property is not a string', () => {
entryPoint.packageJson.browser = {} as any;
expect(getEntryPointFormat(fs, entryPoint, 'browser')).toBeUndefined();
});
});
});
export function createPackageJson(
entryPointName: string, {excludes, typingsProp = 'typings', typingsIsArray, version}: {
excludes?: string[],
typingsProp?: string,
typingsIsArray?: boolean,
version?: string
} = {}): string {
const packageJson: any = {
name: (entryPointName === '') ? 'some_package' : `some_package/${entryPointName}`,
version,
[typingsProp]: typingsIsArray ? [`./${entryPointName}.d.ts`] : `./${entryPointName}.d.ts`,
fesm2015: `./fesm2015/${entryPointName}.js`,
esm2015: `./esm2015/${entryPointName}.js`,
es2015: `./es2015/${entryPointName}.js`,
fesm5: `./fesm5/${entryPointName}.js`,
esm5: `./esm5/${entryPointName}.js`,
main: `./bundles/${entryPointName}/index.js`,
browser: `./bundles/${entryPointName}/index.js`,
module: './index.js',
};
if (excludes) {
excludes.forEach(exclude => delete packageJson[exclude]);
}
return JSON.stringify(packageJson);
}
export function loadPackageJson(fs: FileSystem, packagePath: string) {
return JSON.parse(fs.readFile(fs.resolve(packagePath + '/package.json')));
}