738 lines
22 KiB
TypeScript
738 lines
22 KiB
TypeScript
import { stripIndents } from '@angular-devkit/core/src/utils/literals';
|
|
import { joinPathFragments } from '@nx/devkit';
|
|
import {
|
|
checkFilesDoNotExist,
|
|
checkFilesExist,
|
|
cleanupProject,
|
|
createFile,
|
|
detectPackageManager,
|
|
expectJestTestsToPass,
|
|
getPackageManagerCommand,
|
|
killPorts,
|
|
newProject,
|
|
packageInstall,
|
|
packageManagerLockFile,
|
|
promisifiedTreeKill,
|
|
readFile,
|
|
runCLI,
|
|
runCLIAsync,
|
|
runCommand,
|
|
runCommandUntil,
|
|
tmpProjPath,
|
|
uniq,
|
|
updateFile,
|
|
updateJson,
|
|
} from '@nx/e2e/utils';
|
|
import { exec, execSync } from 'child_process';
|
|
import * as http from 'http';
|
|
import { getLockFileName } from '@nx/js';
|
|
import { satisfies } from 'semver';
|
|
import { join } from 'path';
|
|
|
|
let originalEnvPort;
|
|
|
|
function getRandomPort() {
|
|
return Math.floor(1000 + Math.random() * 9000);
|
|
}
|
|
|
|
function getData(port, path = '/api'): Promise<any> {
|
|
return new Promise((resolve) => {
|
|
http.get(`http://localhost:${port}${path}`, (res) => {
|
|
expect(res.statusCode).toEqual(200);
|
|
let data = '';
|
|
res.on('data', (chunk) => {
|
|
data += chunk;
|
|
});
|
|
res.once('end', () => {
|
|
try {
|
|
resolve(JSON.parse(data));
|
|
} catch (e) {
|
|
resolve(data);
|
|
}
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
describe('Node Applications', () => {
|
|
beforeAll(() => {
|
|
originalEnvPort = process.env.PORT;
|
|
newProject({
|
|
packages: ['@nx/node', '@nx/express', '@nx/nest'],
|
|
});
|
|
});
|
|
|
|
afterAll(() => {
|
|
process.env.PORT = originalEnvPort;
|
|
cleanupProject();
|
|
});
|
|
|
|
it('should be able to generate an empty application', async () => {
|
|
const nodeapp = uniq('nodeapp');
|
|
const port = getRandomPort();
|
|
process.env.PORT = `${port}`;
|
|
runCLI(`generate @nx/node:app ${nodeapp} --port=${port} --linter=eslint`);
|
|
|
|
const lintResults = runCLI(`lint ${nodeapp}`);
|
|
expect(lintResults).toContain('Successfully ran target lint');
|
|
|
|
updateFile(`apps/${nodeapp}/src/main.ts`, `console.log('Hello World!');`);
|
|
await runCLIAsync(`build ${nodeapp}`);
|
|
|
|
checkFilesExist(`dist/apps/${nodeapp}/main.js`);
|
|
const result = execSync(`node dist/apps/${nodeapp}/main.js`, {
|
|
cwd: tmpProjPath(),
|
|
}).toString();
|
|
expect(result).toContain('Hello World!');
|
|
await killPorts(port);
|
|
}, 300000);
|
|
|
|
// TODO(crystal, @ndcunningham): This does not work because NxWebpackPlugin({}) outputFilename does not work.
|
|
xit('should be able to generate the correct outputFileName in options', async () => {
|
|
const nodeapp = uniq('nodeapp');
|
|
runCLI(`generate @nx/node:app ${nodeapp} --linter=eslint`);
|
|
|
|
updateJson(join('apps', nodeapp, 'project.json'), (config) => {
|
|
config.targets.build.options.outputFileName = 'index.js';
|
|
return config;
|
|
});
|
|
|
|
await runCLIAsync(`build ${nodeapp}`);
|
|
checkFilesExist(`dist/apps/${nodeapp}/index.js`);
|
|
}, 300000);
|
|
|
|
it('should be able to generate an empty application with additional entries', async () => {
|
|
const nodeapp = uniq('nodeapp');
|
|
const port = getRandomPort();
|
|
process.env.PORT = `${port}`;
|
|
runCLI(
|
|
`generate @nx/node:app ${nodeapp} --port=${port} --linter=eslint --bundler=webpack`
|
|
);
|
|
|
|
const lintResults = runCLI(`lint ${nodeapp}`);
|
|
expect(lintResults).toContain('Successfully ran target lint');
|
|
|
|
updateFile(
|
|
`apps/${nodeapp}/webpack.config.js`,
|
|
`
|
|
const { NxWebpackPlugin } = require('@nx/webpack');
|
|
const { join } = require('path');
|
|
|
|
module.exports = {
|
|
output: {
|
|
path: join(__dirname, '../../dist/apps/${nodeapp}'),
|
|
},
|
|
plugins: [
|
|
new NxWebpackPlugin({
|
|
target: 'node',
|
|
compiler: 'tsc',
|
|
main: './src/main.ts',
|
|
tsConfig: './tsconfig.app.json',
|
|
assets: ['./src/assets'],
|
|
additionalEntryPoints: [
|
|
{
|
|
entryPath: 'apps/${nodeapp}/src/additional-main.ts',
|
|
entryName: 'additional-main',
|
|
}
|
|
],
|
|
optimization: false,
|
|
outputHashing: 'none',
|
|
}),
|
|
],
|
|
};
|
|
`
|
|
);
|
|
|
|
updateFile(
|
|
`apps/${nodeapp}/src/additional-main.ts`,
|
|
`console.log('Hello Additional World!');`
|
|
);
|
|
updateFile(
|
|
`apps/${nodeapp}/src/main.ts`,
|
|
`console.log('Hello World!');
|
|
console.log('env: ' + process.env['NODE_ENV']);
|
|
`
|
|
);
|
|
|
|
await runCLIAsync(`build ${nodeapp}`);
|
|
|
|
checkFilesExist(
|
|
`dist/apps/${nodeapp}/main.js`,
|
|
`dist/apps/${nodeapp}/additional-main.js`
|
|
);
|
|
|
|
const result = execSync(
|
|
`NODE_ENV=development && node dist/apps/${nodeapp}/main.js`,
|
|
{
|
|
cwd: tmpProjPath(),
|
|
}
|
|
).toString();
|
|
expect(result).toContain('Hello World!');
|
|
expect(result).toContain('env: development');
|
|
|
|
const additionalResult = execSync(
|
|
`node dist/apps/${nodeapp}/additional-main.js`,
|
|
{
|
|
cwd: tmpProjPath(),
|
|
}
|
|
).toString();
|
|
expect(additionalResult).toContain('Hello Additional World!');
|
|
|
|
await killPorts(port);
|
|
}, 300_000);
|
|
|
|
it('should be able to generate an empty application with variable in .env file', async () => {
|
|
const originalEnvPort = process.env.PORT;
|
|
const port = 3457;
|
|
process.env.PORT = `${port}`;
|
|
const nodeapp = uniq('nodeapp');
|
|
|
|
runCLI(
|
|
`generate @nx/node:app ${nodeapp} --linter=eslint --bundler=webpack --framework=none`
|
|
);
|
|
|
|
updateFile('.env', `NX_FOOBAR="test foo bar"`);
|
|
|
|
updateFile(
|
|
`apps/${nodeapp}/src/main.ts`,
|
|
`console.log('foobar: ' + process.env['NX_FOOBAR']);`
|
|
);
|
|
|
|
await runCLIAsync(`build ${nodeapp}`);
|
|
checkFilesExist(`dist/apps/${nodeapp}/main.js`);
|
|
|
|
// check serving
|
|
const p = await runCommandUntil(
|
|
`serve ${nodeapp} --port=${port} --watch=false`,
|
|
(output) => {
|
|
process.stdout.write(output);
|
|
return output.includes(`foobar: test foo bar`);
|
|
}
|
|
);
|
|
try {
|
|
await promisifiedTreeKill(p.pid, 'SIGKILL');
|
|
await killPorts(port);
|
|
} finally {
|
|
process.env.port = originalEnvPort;
|
|
}
|
|
}, 60000);
|
|
|
|
it('should be able to generate an express application', async () => {
|
|
const nodeapp = uniq('nodeapp');
|
|
const originalEnvPort = process.env.PORT;
|
|
const port = 3499;
|
|
process.env.PORT = `${port}`;
|
|
|
|
runCLI(
|
|
`generate @nx/express:app ${nodeapp} --port=${port} --linter=eslint`
|
|
);
|
|
|
|
const lintResults = runCLI(`lint ${nodeapp}`);
|
|
expect(lintResults).toContain('Successfully ran target lint');
|
|
|
|
updateFile(
|
|
`apps/${nodeapp}/src/app/test.spec.ts`,
|
|
`
|
|
describe('test', () => {
|
|
it('should work', () => {
|
|
expect(true).toEqual(true);
|
|
})
|
|
})
|
|
`
|
|
);
|
|
|
|
const jestResult = runCLI(`test ${nodeapp}`);
|
|
expect(jestResult).toContain('Successfully ran target test');
|
|
|
|
// checking serve
|
|
updateFile(`apps/${nodeapp}/src/assets/file.txt`, `Test`);
|
|
const p = await runCommandUntil(`serve ${nodeapp}`, (output) =>
|
|
output.includes(`Listening at http://localhost:${port}`)
|
|
);
|
|
|
|
let result = await getData(port);
|
|
expect(result.message).toMatch(`Welcome to ${nodeapp}!`);
|
|
|
|
result = await getData(port, '/assets/file.txt');
|
|
expect(result).toMatch(`Test`);
|
|
|
|
try {
|
|
await promisifiedTreeKill(p.pid, 'SIGKILL');
|
|
expect(await killPorts(port)).toBeTruthy();
|
|
} catch (err) {
|
|
expect(err).toBeFalsy();
|
|
}
|
|
}, 120_000);
|
|
|
|
xit('should be able to generate a nest application', async () => {
|
|
const nestapp = uniq('nestapp');
|
|
const port = 3335;
|
|
runCLI(`generate @nx/nest:app ${nestapp} --linter=eslint`);
|
|
|
|
const lintResults = runCLI(`lint ${nestapp}`);
|
|
expect(lintResults).toContain('Successfully ran target lint');
|
|
|
|
updateFile(`apps/${nestapp}/src/assets/file.txt`, ``);
|
|
const jestResult = await runCLIAsync(`test ${nestapp}`);
|
|
expect(jestResult.combinedOutput).toContain(
|
|
'Test Suites: 2 passed, 2 total'
|
|
);
|
|
|
|
await runCLIAsync(`build ${nestapp}`);
|
|
|
|
checkFilesExist(
|
|
`dist/apps/${nestapp}/main.js`,
|
|
`dist/apps/${nestapp}/assets/file.txt`,
|
|
`dist/apps/${nestapp}/main.js.map`
|
|
);
|
|
|
|
const server = exec(`node ./dist/apps/${nestapp}/main.js`, {
|
|
cwd: tmpProjPath(),
|
|
});
|
|
expect(server).toBeTruthy();
|
|
|
|
// checking build
|
|
await new Promise((resolve) => {
|
|
server.stdout.on('data', async (data) => {
|
|
const message = data.toString();
|
|
if (message.includes(`Listening at http://localhost:${port}`)) {
|
|
const result = await getData(port);
|
|
|
|
expect(result.message).toEqual(`Welcome to ${nestapp}!`);
|
|
server.kill();
|
|
resolve(null);
|
|
}
|
|
});
|
|
});
|
|
|
|
// checking serve
|
|
const p = await runCommandUntil(
|
|
`serve ${nestapp} --port=${port}`,
|
|
(output) => {
|
|
process.stdout.write(output);
|
|
return output.includes(`Listening at http://localhost:${port}`);
|
|
}
|
|
);
|
|
const result = await getData(port);
|
|
expect(result.message).toEqual(`Welcome to ${nestapp}!`);
|
|
try {
|
|
await promisifiedTreeKill(p.pid, 'SIGKILL');
|
|
expect(await killPorts(port)).toBeTruthy();
|
|
} catch (err) {
|
|
expect(err).toBeFalsy();
|
|
}
|
|
}, 120000);
|
|
|
|
// TODO(crystal, @ndcunningham): how do we handle this now?
|
|
// Revisit when NxWebpackPlugin({}) outputFilename is working.
|
|
xit('should be able to run ESM applications', async () => {
|
|
const esmapp = uniq('esmapp');
|
|
|
|
runCLI(
|
|
`generate @nrwl/node:app ${esmapp} --linter=eslint --framework=none --bundler=webpack`
|
|
);
|
|
updateJson(`apps/${esmapp}/tsconfig.app.json`, (config) => {
|
|
config.module = 'esnext';
|
|
config.target = 'es2020';
|
|
return config;
|
|
});
|
|
updateJson(join('apps', esmapp, 'project.json'), (config) => {
|
|
config.targets.build.options.outputFileName = 'main.mjs';
|
|
config.targets.build.options.assets = [];
|
|
return config;
|
|
});
|
|
updateFile(
|
|
`apps/${esmapp}/webpack.config.js`,
|
|
`
|
|
const { composePlugins, withNx } = require('@nx/webpack');
|
|
module.exports = composePlugins(withNx(), (config) => {
|
|
config.experiments = {
|
|
...config.experiments,
|
|
outputModule: true,
|
|
topLevelAwait: true,
|
|
};
|
|
config.output = {
|
|
path: config.output.path,
|
|
chunkFormat: 'module',
|
|
library: { type: 'module' }
|
|
}
|
|
return config;
|
|
});
|
|
`
|
|
);
|
|
await runCLIAsync(`build ${esmapp}`);
|
|
const p = await runCommandUntil(`serve ${esmapp}`, (output) => {
|
|
return output.includes('Hello World');
|
|
});
|
|
p.kill();
|
|
}, 300000);
|
|
});
|
|
|
|
describe('Build Node apps', () => {
|
|
let scope: string;
|
|
beforeAll(() => {
|
|
originalEnvPort = process.env.PORT;
|
|
scope = newProject({
|
|
packages: ['@nx/node', '@nx/express', '@nx/nest'],
|
|
});
|
|
});
|
|
|
|
afterAll(() => {
|
|
process.env.PORT = originalEnvPort;
|
|
cleanupProject();
|
|
});
|
|
|
|
// TODO(crystal, @ndcunningham): What is the alternative here?
|
|
xit('should generate a package.json with the `--generatePackageJson` flag', async () => {
|
|
const packageManager = detectPackageManager(tmpProjPath());
|
|
const nestapp = uniq('nestapp');
|
|
runCLI(`generate @nx/nest:app ${nestapp} --linter=eslint`);
|
|
|
|
await runCLIAsync(`build ${nestapp} --generatePackageJson`);
|
|
|
|
checkFilesExist(`dist/apps/${nestapp}/package.json`);
|
|
checkFilesExist(
|
|
`dist/apps/${nestapp}/${getLockFileName(
|
|
detectPackageManager(tmpProjPath())
|
|
)}`
|
|
);
|
|
const rootPackageJson = JSON.parse(readFile(`package.json`));
|
|
const packageJson = JSON.parse(
|
|
readFile(`dist/apps/${nestapp}/package.json`)
|
|
);
|
|
expect(packageJson).toEqual(
|
|
expect.objectContaining({
|
|
main: 'main.js',
|
|
name: expect.any(String),
|
|
version: '0.0.1',
|
|
})
|
|
);
|
|
|
|
expect(
|
|
satisfies(
|
|
packageJson.dependencies['@nestjs/common'],
|
|
rootPackageJson.dependencies['@nestjs/common']
|
|
)
|
|
).toBeTruthy();
|
|
expect(
|
|
satisfies(
|
|
packageJson.dependencies['@nestjs/core'],
|
|
rootPackageJson.dependencies['@nestjs/core']
|
|
)
|
|
).toBeTruthy();
|
|
expect(
|
|
satisfies(
|
|
packageJson.dependencies['reflect-metadata'],
|
|
rootPackageJson.dependencies['reflect-metadata']
|
|
)
|
|
).toBeTruthy();
|
|
expect(
|
|
satisfies(
|
|
packageJson.dependencies['rxjs'],
|
|
rootPackageJson.dependencies['rxjs']
|
|
)
|
|
).toBeTruthy();
|
|
expect(
|
|
satisfies(
|
|
packageJson.dependencies['tslib'],
|
|
rootPackageJson.dependencies['tslib']
|
|
)
|
|
).toBeTruthy();
|
|
|
|
checkFilesExist(
|
|
`dist/apps/${nestapp}/${packageManagerLockFile[packageManager]}`
|
|
);
|
|
runCommand(`${getPackageManagerCommand().ciInstall}`, {
|
|
cwd: joinPathFragments(tmpProjPath(), 'dist/apps', nestapp),
|
|
});
|
|
|
|
const nodeapp = uniq('nodeapp');
|
|
runCLI(`generate @nx/node:app ${nodeapp} --bundler=webpack`);
|
|
|
|
const jslib = uniq('jslib');
|
|
runCLI(`generate @nx/js:lib ${jslib} --bundler=tsc`);
|
|
|
|
updateFile(
|
|
`apps/${nodeapp}/src/main.ts`,
|
|
`
|
|
import { ${jslib} } from '@${scope}/${jslib}';
|
|
console.log('Hello World!');
|
|
${jslib}();
|
|
`
|
|
);
|
|
|
|
const { combinedOutput: nodeCombinedOutput } = await runCLIAsync(
|
|
`build ${nodeapp} --generate-package-json`
|
|
);
|
|
expect(nodeCombinedOutput).not.toMatch(/Graph is not consistent/);
|
|
checkFilesExist(`dist/apps/${nodeapp}/package.json`);
|
|
checkFilesExist(
|
|
`dist/apps/${nodeapp}/${packageManagerLockFile[packageManager]}`
|
|
);
|
|
const nodeAppPackageJson = JSON.parse(
|
|
readFile(`dist/apps/${nodeapp}/package.json`)
|
|
);
|
|
|
|
expect(nodeAppPackageJson['dependencies']['tslib']).toBeTruthy();
|
|
|
|
runCommand(`${getPackageManagerCommand().ciInstall}`, {
|
|
cwd: joinPathFragments(tmpProjPath(), 'dist/apps', nestapp),
|
|
});
|
|
|
|
runCommand(`${getPackageManagerCommand().ciInstall}`, {
|
|
cwd: joinPathFragments(tmpProjPath(), 'dist/apps', nodeapp),
|
|
});
|
|
}, 1_000_000);
|
|
|
|
it('should remove previous output before building with the --deleteOutputPath option set', async () => {
|
|
const appName = uniq('app');
|
|
|
|
const port = getRandomPort();
|
|
process.env.PORT = `${port}`;
|
|
|
|
runCLI(`generate @nx/node:app ${appName} --port=${port} --no-interactive`);
|
|
|
|
// deleteOutputPath should default to true
|
|
createFile(`dist/apps/${appName}/_should_remove.txt`);
|
|
createFile(`dist/apps/_should_not_remove.txt`);
|
|
checkFilesExist(
|
|
`dist/apps/${appName}/_should_remove.txt`,
|
|
`dist/apps/_should_not_remove.txt`
|
|
);
|
|
runCLI(`build ${appName} --outputHashing none`); // no explicit deleteOutputPath option set
|
|
checkFilesDoNotExist(`dist/apps/${appName}/_should_remove.txt`);
|
|
checkFilesExist(`dist/apps/_should_not_remove.txt`);
|
|
|
|
// Explicitly set `deleteOutputPath` to true
|
|
createFile(`dist/apps/${appName}/_should_remove.txt`);
|
|
createFile(`dist/apps/_should_not_remove.txt`);
|
|
checkFilesExist(
|
|
`dist/apps/${appName}/_should_remove.txt`,
|
|
`dist/apps/_should_not_remove.txt`
|
|
);
|
|
runCLI(`build ${appName} --outputHashing none --deleteOutputPath`);
|
|
checkFilesDoNotExist(`dist/apps/${appName}/_should_remove.txt`);
|
|
checkFilesExist(`dist/apps/_should_not_remove.txt`);
|
|
|
|
// Explicitly set `deleteOutputPath` to false
|
|
createFile(`dist/apps/${appName}/_should_keep.txt`);
|
|
createFile(`dist/apps/_should_keep.txt`);
|
|
runCLI(`build ${appName} --deleteOutputPath=false --outputHashing none`);
|
|
checkFilesExist(`dist/apps/${appName}/_should_keep.txt`);
|
|
checkFilesExist(`dist/apps/_should_keep.txt`);
|
|
}, 120000);
|
|
|
|
it('should support generating projects with the new name and root format', () => {
|
|
const appName = uniq('app1');
|
|
const libName = uniq('@my-org/lib1');
|
|
|
|
const port = getRandomPort();
|
|
process.env.PORT = `${port}`;
|
|
|
|
runCLI(
|
|
`generate @nx/node:app ${appName} --project-name-and-root-format=as-provided --port=${port} --no-interactive`
|
|
);
|
|
|
|
// check files are generated without the layout directory ("apps/") and
|
|
// using the project name as the directory when no directory is provided
|
|
checkFilesExist(`${appName}/src/main.ts`);
|
|
// check build works
|
|
expect(runCLI(`build ${appName}`)).toContain(
|
|
`Successfully ran target build for project ${appName}`
|
|
);
|
|
// check tests pass
|
|
const appTestResult = runCLI(`test ${appName} --passWithNoTests`);
|
|
expect(appTestResult).toContain(
|
|
`Successfully ran target test for project ${appName}`
|
|
);
|
|
|
|
// assert scoped project names are not supported when --project-name-and-root-format=derived
|
|
expect(() =>
|
|
runCLI(
|
|
`generate @nx/node:lib ${libName} --buildable --project-name-and-root-format=derived --no-interactive`
|
|
)
|
|
).toThrow();
|
|
|
|
runCLI(
|
|
`generate @nx/node:lib ${libName} --buildable --project-name-and-root-format=as-provided --no-interactive`
|
|
);
|
|
|
|
// check files are generated without the layout directory ("libs/") and
|
|
// using the project name as the directory when no directory is provided
|
|
checkFilesExist(`${libName}/src/index.ts`);
|
|
// check build works
|
|
expect(runCLI(`build ${libName}`)).toContain(
|
|
`Successfully ran target build for project ${libName}`
|
|
);
|
|
// check tests pass
|
|
const libTestResult = runCLI(`test ${libName}`);
|
|
expect(libTestResult).toContain(
|
|
`Successfully ran target test for project ${libName}`
|
|
);
|
|
}, 500_000);
|
|
|
|
// TODO(crystal, @ndcunningnam): Investigate why these tests are failing
|
|
xdescribe('NestJS', () => {
|
|
// TODO(crystal, @ndcunningham): What is the alternative here?
|
|
xit('should have plugin output if specified in `tsPlugins`', async () => {
|
|
const nestapp = uniq('nestapp');
|
|
runCLI(`generate @nx/nest:app ${nestapp} --linter=eslint`);
|
|
|
|
packageInstall('@nestjs/swagger', undefined, '^7.0.0');
|
|
|
|
updateJson(join('apps', nestapp, 'project.json'), (config) => {
|
|
config.targets.build.options.tsPlugins = ['@nestjs/swagger/plugin'];
|
|
return config;
|
|
});
|
|
|
|
updateFile(
|
|
`apps/${nestapp}/src/app/foo.dto.ts`,
|
|
`
|
|
export class FooDto {
|
|
foo: string;
|
|
bar: number;
|
|
}`
|
|
);
|
|
updateFile(
|
|
`apps/${nestapp}/src/app/app.controller.ts`,
|
|
`
|
|
import { Controller, Get } from '@nestjs/common';
|
|
import { FooDto } from './foo.dto';
|
|
import { AppService } from './app.service';
|
|
|
|
@Controller()
|
|
export class AppController {
|
|
constructor(private readonly appService: AppService) {}
|
|
|
|
@Get()
|
|
getData() {
|
|
return this.appService.getData();
|
|
}
|
|
|
|
@Get('foo')
|
|
getFoo(): Promise<FooDto> {
|
|
return Promise.resolve({
|
|
foo: 'foo',
|
|
bar: 123
|
|
})
|
|
}
|
|
}`
|
|
);
|
|
|
|
await runCLIAsync(`build ${nestapp}`);
|
|
|
|
const mainJs = readFile(`dist/apps/${nestapp}/main.js`);
|
|
expect(mainJs).toContain('FooDto');
|
|
expect(mainJs).toContain('_OPENAPI_METADATA_FACTORY');
|
|
}, 300000);
|
|
});
|
|
|
|
describe('nest libraries', function () {
|
|
it('should be able to generate a nest library', async () => {
|
|
const nestlib = uniq('nestlib');
|
|
runCLI(`generate @nx/nest:lib ${nestlib}`);
|
|
|
|
const lintResults = runCLI(`lint ${nestlib}`);
|
|
expect(lintResults).toContain('Successfully ran target lint');
|
|
|
|
const testResults = runCLI(`test ${nestlib} --passWithNoTests`);
|
|
expect(testResults).toContain(
|
|
`Successfully ran target test for project ${nestlib}`
|
|
);
|
|
}, 60000);
|
|
|
|
it('should be able to generate a nest library w/ service', async () => {
|
|
const nestlib = uniq('nestlib');
|
|
|
|
runCLI(`generate @nx/nest:lib ${nestlib} --service`);
|
|
|
|
const lintResults = runCLI(`lint ${nestlib}`);
|
|
expect(lintResults).toContain('Successfully ran target lint');
|
|
|
|
const jestResult = await runCLIAsync(`test ${nestlib}`);
|
|
expect(jestResult.combinedOutput).toContain(
|
|
'Test Suites: 1 passed, 1 total'
|
|
);
|
|
}, 200000);
|
|
|
|
it('should be able to generate a nest library w/ controller', async () => {
|
|
const nestlib = uniq('nestlib');
|
|
|
|
runCLI(`generate @nx/nest:lib ${nestlib} --controller`);
|
|
|
|
const lintResults = runCLI(`lint ${nestlib}`);
|
|
expect(lintResults).toContain('Successfully ran target lint');
|
|
|
|
const jestResult = await runCLIAsync(`test ${nestlib}`);
|
|
expect(jestResult.combinedOutput).toContain(
|
|
'Test Suites: 1 passed, 1 total'
|
|
);
|
|
}, 200000);
|
|
|
|
it('should be able to generate a nest library w/ controller and service', async () => {
|
|
const nestlib = uniq('nestlib');
|
|
|
|
runCLI(`generate @nx/nest:lib ${nestlib} --controller --service`);
|
|
|
|
const lintResults = runCLI(`lint ${nestlib}`);
|
|
expect(lintResults).toContain('Successfully ran target lint');
|
|
|
|
const jestResult = await runCLIAsync(`test ${nestlib}`);
|
|
expect(jestResult.combinedOutput).toContain(
|
|
'Test Suites: 2 passed, 2 total'
|
|
);
|
|
}, 200000);
|
|
|
|
it('should have plugin output if specified in `transformers`', async () => {
|
|
const nestlib = uniq('nestlib');
|
|
runCLI(`generate @nx/nest:lib ${nestlib} --buildable`);
|
|
|
|
packageInstall('@nestjs/swagger', undefined, '^7.0.0');
|
|
|
|
updateJson(join('libs', nestlib, 'project.json'), (config) => {
|
|
config.targets.build.options.transformers = [
|
|
{
|
|
name: '@nestjs/swagger/plugin',
|
|
options: {
|
|
dtoFileNameSuffix: ['.model.ts'],
|
|
},
|
|
},
|
|
];
|
|
return config;
|
|
});
|
|
|
|
updateFile(
|
|
`libs/${nestlib}/src/lib/foo.model.ts`,
|
|
`
|
|
export class FooModel {
|
|
foo?: string;
|
|
bar?: number;
|
|
}`
|
|
);
|
|
|
|
await runCLIAsync(`build ${nestlib}`);
|
|
|
|
const fooModelJs = readFile(`dist/libs/${nestlib}/src/lib/foo.model.js`);
|
|
expect(stripIndents`${fooModelJs}`).toContain(
|
|
stripIndents`
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.FooModel = void 0;
|
|
const openapi = require("@nestjs/swagger");
|
|
class FooModel {
|
|
static _OPENAPI_METADATA_FACTORY() {
|
|
return { foo: { required: false, type: () => String }, bar: { required: false, type: () => Number } };
|
|
}
|
|
}
|
|
exports.FooModel = FooModel;
|
|
//# sourceMappingURL=foo.model.js.map
|
|
`
|
|
);
|
|
}, 300000);
|
|
|
|
it('should run default jest tests', async () => {
|
|
await expectJestTestsToPass('@nx/node:lib');
|
|
}, 100000);
|
|
});
|
|
});
|