Nx doesn't find generated files in tree using a plugin generator while testing

40 Views Asked by At

I'm working in a Nx workspace, trying to create some generators. It works fine until I try to test them. The test update the tree and create all the files but fails trying to find tsconfig.json which has actually generated. It occurs when calling the generator after creating the file on the tree but in the next step (which is modifying the file, the updateJson function for tsconfig.json) fails.

This is the generator.spec.ts

import { Tree, readJsonFile, readProjectConfiguration } from '@nx/devkit';
import { ApplicationGeneratorSchema } from './schema';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
import appicationGenerator from './generator';

describe('application generator', () => {
  let tree: Tree;
  const options: ApplicationGeneratorSchema = { projectName: 'test' };

  beforeEach(() => {
    tree = createTreeWithEmptyWorkspace();
    // runNxCommand(`g @devon4ts_node/schematics:application --projectName ${options.projectName}`, {});
  });

  it('should run successfully', async () => {
    await appicationGenerator(tree, options);
    const config = readProjectConfiguration(tree, options.projectName);
    expect(config).toBeDefined();
  });

  it('should generate main.ts and other application specific files', async () => {
    expect(tree.exists(`./apps/${options.projectName}/src/main.ts`)).toBeTruthy();
    expect(tree.exists(`./apps/${options.projectName}/src/app/app.module.ts`)).toBeTruthy();
    expect(tree.exists(`./apps/${options.projectName}/src/app/app.controller.ts`)).toBeTruthy();
    expect(tree.exists(`./apps/${options.projectName}/src/app/app.service.ts`)).toBeTruthy();
    expect(tree.exists(`./apps/${options.projectName}/src/app/app.controller.spec.ts`)).toBeTruthy();
    expect(tree.exists(`./apps/${options.projectName}/src/app/app.service.spec.ts`)).toBeTruthy();
  });

  it('should add dependencies to package.json', async () => {
    const fileContent = tree.read('package.json')?.toString('utf-8');
    expect(fileContent).toMatch(/"devDependencies": {(.|\n)*"husky":/g);
    expect(fileContent).toMatch(/"dependencies": {(.|\n)*"winston":/g);
  });

  it('should delete .eslintrc.json and create .eslintrc.js', async () => {
    expect(tree.exists(`./apps/${options.projectName}/.eslintrc.json`)).toBeFalsy();
    expect(tree.exists(`./apps/${options.projectName}/.eslintrc.js`)).toBeTruthy();
  });

  it('should update tsconfig.json', async () => {
    expect(tree.exists(`./apps/${options.projectName}/tsconfig.json`)).toBeTruthy();
    const fileContent = readJsonFile('package.json');
    expect(fileContent.compilerOptions).toEqual({
      strictNullChecks: true,
      noImplicitAny: true,
      strictBindCallApply: true,
      forceConsistentCasingInFileNames: true,
      noFallthroughCasesInSwitch: true,
      strict: true,
      skipDefaultLibCheck: true,
      noUnusedLocals: true,
      noUnusedParameters: true,
      skipLibCheck: true,
      allowSyntheticDefaultImports: true,
    });
  });

});

And this is the generator.ts

import {
  addDependenciesToPackageJson,
  addProjectConfiguration,
  formatFiles,
  generateFiles,
  installPackagesTask,
  Tree,
  updateJson,
} from '@nx/devkit';
import * as path from 'path';
import { ApplicationGeneratorSchema } from './schema';
import { execSync } from 'child_process';
import { stdout } from 'process';
import { packagesVersion } from '../packagesVersion';

export async function applicationGenerator(tree: Tree, options: ApplicationGeneratorSchema): Promise<() => void> {
  const projectRoot = `apps/${options.projectName}`;
  if (tree.exists(projectRoot)) {
    throw new Error(`Application with name "${options.projectName}" already exists`);
  }
  addProjectConfiguration(tree, options.projectName, {
    root: projectRoot,
    projectType: 'application',
    sourceRoot: `${projectRoot}/src`,
    targets: {},
  });
  execSync(
    `nx generate @nx/nest:application ${options.projectName} --strict --directory="apps"`,
    { stdio: 'inherit' }, // Print output directly to console
  );
  if (tree.exists(path.join(projectRoot, '.eslintrc.json'))) {
    tree.delete(path.join(projectRoot, '.eslintrc.json'));
  }
  addDependenciesToPackageJson(
    tree,
    {
      [packagesVersion['express'].name]: packagesVersion['express'].version,
      [packagesVersion['typeFest'].name]: packagesVersion['typeFest'].version,
      [packagesVersion['winston'].name]: packagesVersion['winston'].version,
      [packagesVersion['classTransformer'].name]: packagesVersion['classTransformer'].version,
      [packagesVersion['classValidator'].name]: packagesVersion['classValidator'].version,
    },
    {
      [packagesVersion['husky'].name]: packagesVersion['husky'].version,
      [packagesVersion['prettyQuick'].name]: packagesVersion['prettyQuick'].version,
      [packagesVersion['typesExpress'].name]: packagesVersion['typesExpress'].version,
      [packagesVersion['eslintPluginPrettier'].name]: packagesVersion['eslintPluginPrettier'].version,
    },
  );
  // Update scripts from package.json at root directory
  updateJson(tree, 'package.json', pkgJson => {
    // if scripts is undefined, set it to an empty object
    pkgJson.scripts = pkgJson.scripts ?? {};
    pkgJson.scripts.lint = 'eslint {apps,packages}/{src,apps,libs,test}/**/*.ts --fix';
    pkgJson.scripts.prepare = 'husky';
    // if jest is undefined, set it to an empty object
    pkgJson.jest = pkgJson.jest ?? {};
    pkgJson.jest.coverageDirectory = `./apps/${options.projectName}/coverage`;
    // return modified JSON object
    return pkgJson;
  });
  // Update compilerOptions from tsconfig.json at application directory
  updateJson(tree, `${projectRoot}/tsconfig.json`, tsconfigJson => {
    // if compilerOptions is undefined, set it to an empty object
    tsconfigJson.compilerOptions = {
      strictNullChecks: true,
      noImplicitAny: true,
      strictBindCallApply: true,
      forceConsistentCasingInFileNames: true,
      noFallthroughCasesInSwitch: true,
      strict: true,
      skipDefaultLibCheck: true,
      noUnusedLocals: true,
      noUnusedParameters: true,
      skipLibCheck: true,
      allowSyntheticDefaultImports: true,
    };
    return tsconfigJson;
  });
  generateFiles(tree, path.join(__dirname, 'files'), projectRoot, options);
  await formatFiles(tree);
  return () => {
    installPackagesTask(tree, false, '', 'pnpm');
    stdout.write(`NestJS app generated successfully!`);
  };
}

export default applicationGenerator;

0

There are 0 best solutions below