nx/packages/node/src/executors/package/package.impl.spec.ts
Craigory Coppola 79cf69b4e4
feat(core): consolidate nx.json and workspace.json (#6642)
* feat(core): consolidate settings between workspace.json + nx.json

workspace.json (and linked project.json files) now contain all project specific settings.
nx.json now contains all settings that affect the whole workspace.

* chore(core): fix angular unit tests w/ new config

* chore(core): fix failing tests

* chore(core): fix formatting

* chore(core): fix more tests

* chore(core): normalize-nx-json feedback

* chore(core): Fix more unit tests

* chore(core): fix remaining tests in workspace

* chore(linter): fix remaining linter tests

* chore(core): fix remaining spec + build issues

* chore(core): formatting fixes

* feat(core): migration script to move config options to new locations

* chore(core): fix e2e tests

* chore(core): run format

* chore(react-native): fix failing tests

Signed-off-by: AgentEnder <craigorycoppola@gmail.com>

* feat(core): move properties to new location during format step

Signed-off-by: AgentEnder <craigorycoppola@gmail.com>

* feat(core): initial pass on ngcli-adapter for property consolidation

Signed-off-by: AgentEnder <craigorycoppola@gmail.com>

* chore(misc): fix tests

Signed-off-by: AgentEnder <craigorycoppola@gmail.com>

* docs(core): update docs with changes

* chore(misc): fix tests

* chore(core): code review changes

updateWorkspaceJson -> updateWorkspace, no longer uses updater function

Signed-off-by: AgentEnder <craigorycoppola@gmail.com>

* chore(core): fix bug in ngcli impl

* fix(core): fix bug in ngcli-adapter

Signed-off-by: AgentEnder <craigorycoppola@gmail.com>

* fix(core): fix ngcli-adapter

Signed-off-by: AgentEnder <craigorycoppola@gmail.com>

* chore(core): fix workspace e2e

* chore(core): fix nx-plugin e2e

* fix(core): move defaultProject to nx.json

* chore(core): fix broken workspace test

* chore(core): formatting

* chore(core): fix workspace format

* chore(core): add nxJson to ExecutorContext

Signed-off-by: AgentEnder <craigorycoppola@gmail.com>

* chore(core): remove all references ot `NxProjectConfiguration` from our code

* chore(core): Review Changes

* fix(core): update new config locations v13 migration
2021-10-14 10:42:47 -04:00

335 lines
9.9 KiB
TypeScript

import { ExecutorContext } from '@nrwl/devkit';
import { join } from 'path';
import { mocked } from 'ts-jest/utils';
jest.mock('@nrwl/workspace/src/core/project-graph');
import * as projectGraph from '@nrwl/workspace/src/core/project-graph';
import {
ProjectGraph,
ProjectType,
} from '@nrwl/workspace/src/core/project-graph';
import { packageExecutor } from './package.impl';
import { NodePackageBuilderOptions } from './utils/models';
jest.mock('glob');
import * as glob from 'glob';
jest.mock('fs-extra');
import * as fs from 'fs-extra';
jest.mock('@nrwl/workspace/src/utilities/fileutils');
import * as fsUtility from '@nrwl/workspace/src/utilities/fileutils';
import * as tsUtils from '@nrwl/workspace/src/utilities/typescript';
import * as ts from 'typescript';
describe('NodePackageBuilder', () => {
let testOptions: NodePackageBuilderOptions;
let context: ExecutorContext;
beforeEach(async () => {
mocked(fsUtility.readJsonFile).mockImplementation((path: string) => {
if (path.endsWith('tsconfig.lib.json')) {
return {
extends: './tsconfig.json',
compilerOptions: {
outDir: '../../dist/out-tsc',
declaration: true,
rootDir: './src',
types: ['node'],
},
exclude: ['**/*.spec.ts'],
include: ['**/*.ts'],
};
} else {
return {
name: 'nodelib',
};
}
});
mocked(fsUtility.writeJsonFile).mockImplementation(
(_: string, _2: unknown) => {
//empty
return;
}
);
mocked(fs.existsSync).mockImplementation(
(path: string) => path === 'libs/nodelib/src/index.ts'
);
context = {
root: '/root',
cwd: '/root',
projectName: 'nodelib',
targetName: 'build',
workspace: {
version: 2,
projects: {
nodelib: {
root: 'libs/nodelib',
sourceRoot: 'libs/nodelib/src',
targets: {},
},
},
npmScope: 'test',
},
isVerbose: false,
};
testOptions = {
assets: [],
main: 'libs/nodelib/src/index.ts',
outputPath: 'dist/libs/nodelib',
packageJson: 'libs/nodelib/package.json',
tsConfig: 'libs/nodelib/tsconfig.lib.json',
watch: false,
sourceMap: false,
deleteOutputPath: true,
};
});
describe('Without library dependencies', () => {
beforeEach(() => {
jest
.spyOn(projectGraph, 'readCachedProjectGraph')
.mockImplementation(() => {
return {
nodes: {
nodelib: {
type: ProjectType.lib,
name: 'nodelib',
data: {
files: [],
root: 'libs/nodelib',
targets: { build: { executor: 'any builder' } },
},
},
'nodelib-child': {
type: ProjectType.lib,
name: 'nodelib-child',
data: {
files: [],
root: 'libs/nodelib-child',
prefix: 'proj',
targets: {
build: {
executor: 'any builder',
options: {
assets: [],
main: 'libs/nodelib-child/src/index.ts',
outputPath: 'dist/libs/nodelib-child',
packageJson: 'libs/nodelib-child/package.json',
tsConfig: 'libs/nodelib-child/tsconfig.lib.json',
},
},
},
},
},
},
dependencies: {
nodelib: [],
'nodelib-child': [],
},
} as ProjectGraph;
});
});
it('should update the package.json after compiling typescript', async () => {
await packageExecutor(testOptions, context);
expect(fsUtility.writeJsonFile).toHaveBeenCalledWith(
`${testOptions.outputPath}/package.json`,
{
name: 'nodelib',
main: './src/index.js',
typings: './src/index.d.ts',
}
);
});
it('should throw an error if `main` entry point does not exist', async () => {
await expect(
packageExecutor({ ...testOptions, main: 'does/not/exist.ts' }, context)
).rejects.toThrow(
`Please verify that the "main" option for project "nodelib" is valid.`
);
});
it('should have the output path in the BuilderOutput', async () => {
const result = await packageExecutor(testOptions, context);
expect(result.outputPath).toEqual(testOptions.outputPath);
});
describe('Asset copying', () => {
beforeEach(() => {
jest.clearAllMocks();
});
it('should be able to copy assets using the glob object', async () => {
mocked(glob.sync).mockReturnValue(['logo.png']);
await packageExecutor(
{
...testOptions,
assets: [
{
glob: '**.*',
input: 'lib/nodelib/src/assets',
output: './newfolder',
ignore: [],
},
],
},
context
);
expect(fs.copy).toHaveBeenCalledTimes(1);
expect(fs.copy).toHaveBeenCalledWith(
`${context.root}/lib/nodelib/src/assets/logo.png`,
`${context.root}/${testOptions.outputPath}/newfolder/logo.png`
);
});
it('should be able to copy assets with a regular string', async () => {
mocked(glob.sync).mockReturnValue(['lib/nodelib/src/LICENSE']);
await packageExecutor(
{
...testOptions,
assets: ['lib/nodelib/src/LICENSE'],
},
context
);
expect(fs.copy).toHaveBeenCalledTimes(1);
expect(fs.copy).toHaveBeenCalledWith(
`${context.root}/lib/nodelib/src/LICENSE`,
`${context.root}/${testOptions.outputPath}/LICENSE`
);
});
it('should be able to copy assets with a glob string', async () => {
mocked(glob.sync).mockReturnValue([
'lib/nodelib/src/README.md',
'lib/nodelib/src/CONTRIBUTING.md',
]);
await packageExecutor(
{
...testOptions,
assets: ['lib/nodelib/src/*.MD'],
},
context
);
expect(fs.copy).toHaveBeenCalledTimes(2);
expect(fs.copy).toHaveBeenCalledWith(
`${context.root}/lib/nodelib/src/README.md`,
`${context.root}/${testOptions.outputPath}/README.md`
);
expect(fs.copy).toHaveBeenCalledWith(
`${context.root}/lib/nodelib/src/CONTRIBUTING.md`,
`${context.root}/${testOptions.outputPath}/CONTRIBUTING.md`
);
});
});
describe('srcRootForCompilationRoot', () => {
let spy: jest.SpyInstance;
beforeEach(() => {
jest.clearAllMocks();
spy = jest.spyOn(ts, 'createCompilerHost');
});
it('should use srcRootForCompilationRoot when it is defined', async () => {
testOptions.srcRootForCompilationRoot = 'libs/nodelib/src';
await packageExecutor(testOptions, context);
expect(spy).toHaveBeenCalledWith(
expect.objectContaining({
rootDir: 'libs/nodelib/src',
})
);
});
it('should not use srcRootForCompilationRoot when it is not defined', async () => {
testOptions.srcRootForCompilationRoot = undefined;
await packageExecutor(testOptions, context);
expect(spy).toHaveBeenCalledWith(
expect.objectContaining({
rootDir: 'libs/nodelib',
})
);
});
});
});
describe('building with dependencies', () => {
beforeEach(() => {
// fake that dep project has been built
jest
.spyOn(projectGraph, 'readCachedProjectGraph')
.mockImplementation(() => {
return {
nodes: {
nodelib: {
type: ProjectType.lib,
name: 'nodelib',
data: {
files: [],
root: 'libs/nodelib',
targets: { build: { executor: 'any builder' } },
},
},
'nodelib-child': {
type: ProjectType.lib,
name: 'nodelib-child',
data: {
files: [],
root: 'libs/nodelib-child',
prefix: 'proj',
targets: {
build: {
executor: 'any builder',
options: {
assets: [],
main: 'libs/nodelib-child/src/index.ts',
outputPath: 'dist/libs/nodelib-child',
packageJson: 'libs/nodelib-child/package.json',
tsConfig: 'libs/nodelib-child/tsconfig.lib.json',
},
},
},
},
},
},
dependencies: {
nodelib: [
{
type: ProjectType.lib,
target: 'nodelib-child',
source: null,
},
],
'nodelib-child': [],
},
} as ProjectGraph;
});
// dist/libs/nodelib-child/package.json
mocked(fsUtility.directoryExists).mockImplementation((arg: string) => {
return arg.endsWith('dist/libs/nodelib-child');
});
});
it('should call the tsc compiler with the modified tsconfig.json', async () => {
const tmpTsConfigPath = join(
'/root',
'tmp',
'libs/nodelib',
'tsconfig.generated.json'
);
const tsConfigSpy = jest.spyOn(tsUtils, 'readTsConfig');
await packageExecutor(testOptions, context);
expect(tsConfigSpy).toHaveBeenCalledWith(tmpTsConfigPath);
});
});
});