test(ivy): ngcc - check private dependency in integration test (#29643)

The test now attempts to compile an entry-point (@angular/common/http/testing)
that has a transient "private" dependency. A private dependency is one that is
only visible by looking at the compiled JS code, rather than the generated TS
typings files.

This proves that we can't rely on typings files alone for computing the
dependencies between entry-points.

PR Close #29643
This commit is contained in:
Pete Bacon Darwin 2019-04-28 20:47:56 +01:00 committed by Andrew Kushnir
parent 4c03208537
commit c2cf500da9
1 changed files with 22 additions and 66 deletions

View File

@ -10,7 +10,6 @@ import {AbsoluteFsPath} from '@angular/compiler-cli/src/ngtsc/path';
import {existsSync, readFileSync, readdirSync, statSync, writeFileSync} from 'fs'; import {existsSync, readFileSync, readdirSync, statSync, writeFileSync} from 'fs';
import * as mockFs from 'mock-fs'; import * as mockFs from 'mock-fs';
import {join} from 'path'; import {join} from 'path';
const Module = require('module');
import {getAngularPackagesFromRunfiles, resolveNpmTreeArtifact} from '../../../test/runfile_helpers'; import {getAngularPackagesFromRunfiles, resolveNpmTreeArtifact} from '../../../test/runfile_helpers';
import {mainNgcc} from '../../src/main'; import {mainNgcc} from '../../src/main';
@ -40,39 +39,27 @@ describe('ngcc main()', () => {
describe('with targetEntryPointPath', () => { describe('with targetEntryPointPath', () => {
it('should only compile the given package entry-point (and its dependencies).', () => { it('should only compile the given package entry-point (and its dependencies).', () => {
mainNgcc({basePath: '/node_modules', targetEntryPointPath: '@angular/common/http'}); const STANDARD_MARKERS = {
module: '0.0.0-PLACEHOLDER',
es2015: '0.0.0-PLACEHOLDER',
esm5: '0.0.0-PLACEHOLDER',
esm2015: '0.0.0-PLACEHOLDER',
fesm5: '0.0.0-PLACEHOLDER',
fesm2015: '0.0.0-PLACEHOLDER',
typings: '0.0.0-PLACEHOLDER',
};
expect(loadPackage('@angular/common/http').__processed_by_ivy_ngcc__).toEqual({ mainNgcc({basePath: '/node_modules', targetEntryPointPath: '@angular/common/http/testing'});
module: '0.0.0-PLACEHOLDER', expect(loadPackage('@angular/common/http/testing').__processed_by_ivy_ngcc__)
es2015: '0.0.0-PLACEHOLDER', .toEqual(STANDARD_MARKERS);
esm5: '0.0.0-PLACEHOLDER', // * `common/http` is a dependency of `common/http/testing`, so is compiled.
esm2015: '0.0.0-PLACEHOLDER', expect(loadPackage('@angular/common/http').__processed_by_ivy_ngcc__)
fesm5: '0.0.0-PLACEHOLDER', .toEqual(STANDARD_MARKERS);
fesm2015: '0.0.0-PLACEHOLDER', // * `core` is a dependency of `common/http`, so is compiled.
typings: '0.0.0-PLACEHOLDER', expect(loadPackage('@angular/core').__processed_by_ivy_ngcc__).toEqual(STANDARD_MARKERS);
}); // * `common` is a private (only in .js not .d.ts) dependency so is compiled.
// * `common` is a dependency of `common/http`, so is compiled. expect(loadPackage('@angular/common').__processed_by_ivy_ngcc__).toEqual(STANDARD_MARKERS);
expect(loadPackage('@angular/common').__processed_by_ivy_ngcc__).toEqual({ // * `common/testing` is not a dependency so is not compiled.
module: '0.0.0-PLACEHOLDER',
es2015: '0.0.0-PLACEHOLDER',
esm5: '0.0.0-PLACEHOLDER',
esm2015: '0.0.0-PLACEHOLDER',
fesm5: '0.0.0-PLACEHOLDER',
fesm2015: '0.0.0-PLACEHOLDER',
typings: '0.0.0-PLACEHOLDER',
});
// * `core` is a dependency of `common`, so is compiled.
expect(loadPackage('@angular/core').__processed_by_ivy_ngcc__).toEqual({
module: '0.0.0-PLACEHOLDER',
es2015: '0.0.0-PLACEHOLDER',
esm5: '0.0.0-PLACEHOLDER',
esm2015: '0.0.0-PLACEHOLDER',
fesm5: '0.0.0-PLACEHOLDER',
fesm2015: '0.0.0-PLACEHOLDER',
typings: '0.0.0-PLACEHOLDER',
});
// * `common/testing` is not a dependency of `common/http` so is not compiled.
expect(loadPackage('@angular/common/testing').__processed_by_ivy_ngcc__).toBeUndefined(); expect(loadPackage('@angular/common/testing').__processed_by_ivy_ngcc__).toBeUndefined();
}); });
@ -332,13 +319,13 @@ function createMockFileSystem() {
'/node_modules/tslib': loadDirectory(resolveNpmTreeArtifact('tslib', 'tslib.js')), '/node_modules/tslib': loadDirectory(resolveNpmTreeArtifact('tslib', 'tslib.js')),
'/node_modules/test-package': { '/node_modules/test-package': {
'package.json': '{"name": "test-package", "es2015": "./index.js", "typings": "./index.d.ts"}', 'package.json': '{"name": "test-package", "es2015": "./index.js", "typings": "./index.d.ts"}',
// no metadata.json file so not compiled by Angular.
'index.js': 'index.js':
'import {AppModule} from "@angular/common"; export class MyApp extends AppModule;', 'import {AppModule} from "@angular/common"; export class MyApp extends AppModule;',
'index.d.s': 'index.d.ts':
'import {AppModule} from "@angular/common"; export declare class MyApp extends AppModule;', 'import {AppModule} from "@angular/common"; export declare class MyApp extends AppModule;',
} }
}); });
spyOn(Module, '_resolveFilename').and.callFake(mockResolve);
} }
function restoreRealFileSystem() { function restoreRealFileSystem() {
@ -380,37 +367,6 @@ interface Directory {
[pathSegment: string]: string|Directory; [pathSegment: string]: string|Directory;
} }
/**
* A mock implementation of the node.js Module._resolveFilename function,
* which we are spying on to support mocking out the file-system in these tests.
*
* @param request the path to a module that needs resolving.
*/
function mockResolve(request: string): string|null {
if (existsSync(request)) {
const stat = statSync(request);
if (stat.isFile()) {
return request;
} else if (stat.isDirectory()) {
const pIndex = mockResolve(request + '/index');
if (pIndex && existsSync(pIndex)) {
return pIndex;
}
}
}
for (const ext of ['.js', '.d.ts']) {
if (existsSync(request + ext)) {
return request + ext;
}
}
if (request.indexOf('/node_modules') === 0) {
// We already tried adding node_modules so give up.
return null;
} else {
return mockResolve(join('/node_modules', request));
}
}
function loadPackage(packageName: string): EntryPointPackageJson { function loadPackage(packageName: string): EntryPointPackageJson {
return JSON.parse(readFileSync(`/node_modules/${packageName}/package.json`, 'utf8')); return JSON.parse(readFileSync(`/node_modules/${packageName}/package.json`, 'utf8'));
} }