Skip to content

Commit

Permalink
fix(core): test project generator should handle domain paths
Browse files Browse the repository at this point in the history
  • Loading branch information
AgentEnder committed May 17, 2024
1 parent c4c3d54 commit 7b2f502
Show file tree
Hide file tree
Showing 12 changed files with 365 additions and 300 deletions.
6 changes: 5 additions & 1 deletion docs/core/Generators/test.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Generate a .NET test project for an existing application or library

## Options

### <span className="required">name</span>
### <span className="required">targetProject</span>

- (string): The existing project to generate tests for

Expand All @@ -22,6 +22,10 @@ Generate a .NET test project for an existing application or library

- (string): What suffix should be used for the tests project name?

### testProjectName

- (string): What name should be used for the tests project?

### solutionFile

- (string): The name of the solution file to add the project to
Expand Down
1 change: 1 addition & 0 deletions jest.preset.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ const nxPreset = require('@nx/jest/preset').default;
module.exports = {
...nxPreset,
testEnvironment: 'node',
prettierPath: require.resolve('prettier-2'),
};
6 changes: 5 additions & 1 deletion nx.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@
"targetDefaults": {
"build": {
"dependsOn": ["^build", "prebuild", "^codegen", "codegen"],
"inputs": ["production", "^production"],
"inputs": [
"production",
"^production",
{ "env": "NX_DOTNET_NEXT_VERSION" }
],
"cache": true
},
"@nx-dotnet/core:build": {
Expand Down
7 changes: 4 additions & 3 deletions packages/core/src/generators/project-reference/generator.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import { Tree, readProjectConfiguration } from '@nx/devkit';
import { Tree } from '@nx/devkit';

import { DotNetClient, dotnetFactory } from '@nx-dotnet/dotnet';
import { getProjectFileForNxProject } from '@nx-dotnet/utils';

import { NxDotnetGeneratorSchema } from './schema';
import { readProjectConfiguration } from '../utils/project-configuration';

export default async function (
host: Tree,
options: NxDotnetGeneratorSchema,
client = new DotNetClient(dotnetFactory()),
) {
const hostProject = readProjectConfiguration(host, options.project);
const sourceProject = readProjectConfiguration(host, options.reference);
const hostProject = await readProjectConfiguration(host, options.project);
const sourceProject = await readProjectConfiguration(host, options.reference);
let [hostProjectFile, sourceProjectFile] = ['', ''];

try {
Expand Down
193 changes: 167 additions & 26 deletions packages/core/src/generators/test/generator.spec.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,189 @@
import { addProjectConfiguration, Tree } from '@nx/devkit';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';

import { DotNetClient, mockDotnetFactory } from '@nx-dotnet/dotnet';

import * as mockedProjectGenerator from '../utils/generate-test-project';
import generator from './generator';
import { NxDotnetGeneratorSchema } from './schema';
import generator, { calculateTestTargetNameAndRoot } from './generator';

jest.mock('../utils/generate-test-project');
import {
addProjectConfiguration,
readProjectConfiguration,
Tree,
writeJson,
} from '@nx/devkit';

describe('nx-dotnet test generator', () => {
import * as fs from 'fs';

import * as utils from '@nx-dotnet/utils';

import { initGenerator } from '../init/generator';
import { NxDotnetTestGeneratorSchema } from '../../models';

jest.mock('@nx-dotnet/utils', () => ({
// eslint-disable-next-line @typescript-eslint/no-explicit-any
...(jest.requireActual('@nx-dotnet/utils') as any),
glob: jest.fn(),
findProjectFileInPath: jest.fn(),
resolve: (m: string) => m,
}));

jest.mock('fs', () => ({
...jest.requireActual('fs'),
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
readFileSync: (p: fs.PathOrFileDescriptor, ...args) => {
// eslint-disable-next-line @typescript-eslint/no-var-requires
if (typeof p === 'string' && require('path').extname(p) === '.csproj')
return `<Project>
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
</Project>`;
return jest.requireActual('fs').readFileSync(p, ...args);
},
}));

describe('nx-dotnet test project generator', () => {
let tree: Tree;
let dotnetClient: DotNetClient;
let options: NxDotnetTestGeneratorSchema;
let testProjectName: string;

const options: NxDotnetGeneratorSchema = {
name: 'existing',
testTemplate: 'xunit',
language: 'C#',
pathScheme: 'nx',
};

beforeEach(() => {
beforeEach(async () => {
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
addProjectConfiguration(tree, 'existing', {
root: 'apps/existing',
targets: {},
tree.write('package.json', '{}');
await initGenerator(tree, null, new DotNetClient(mockDotnetFactory()));
addProjectConfiguration(tree, 'domain-existing-app', {
root: 'apps/domain/existing-app',
projectType: 'application',
targets: {},
});
addProjectConfiguration(tree, 'domain-existing-lib', {
root: 'libs/domain/existing-lib',
projectType: 'library',
targets: {},
});

fs.mkdirSync('apps/domain/existing-app', { recursive: true });
jest
.spyOn(utils, 'glob')
.mockResolvedValue([
'apps/domain/existing-app/Proj.Domain.ExistingApp.csproj',
]);
jest
.spyOn(utils, 'findProjectFileInPath')
.mockResolvedValue(
'apps/domain/existing-app/Proj.Domain.ExistingApp.csproj',
);

dotnetClient = new DotNetClient(mockDotnetFactory());

const packageJson = { scripts: {} };
writeJson(tree, 'package.json', packageJson);

options = {
targetProject: 'domain-existing-app',
testTemplate: 'xunit',
language: 'C#',
pathScheme: 'nx',
skipFormat: true,
};
testProjectName = options.targetProject + '-test';
});

it('should run successfully', async () => {
it('should include test target', async () => {
await generator(tree, options, dotnetClient);
const config = readProjectConfiguration(tree, testProjectName);
expect(config.targets?.test).toBeDefined();
});

it('should call project generator with application project type', async () => {
const projectGenerator = (
mockedProjectGenerator as jest.Mocked<typeof mockedProjectGenerator>
).GenerateTestProject;

it('should set outputs for build target', async () => {
await generator(tree, options, dotnetClient);
expect(projectGenerator).toHaveBeenCalled();
expect(projectGenerator.mock.calls[0][1].projectType).toEqual(
'application',
const config = readProjectConfiguration(tree, testProjectName);
const outputPath = config.targets?.build.outputs?.[0];
expect(outputPath).toEqual(
'{workspaceRoot}/dist/apps/domain/existing-app-test',
);
});

it('should include lint target', async () => {
await generator(tree, options, dotnetClient);
const config = readProjectConfiguration(tree, testProjectName);
expect(config.targets?.lint).toBeDefined();
});

it('should determine directory from existing project', async () => {
await generator(tree, options, dotnetClient);
const config = readProjectConfiguration(tree, testProjectName);
expect(config.root).toBe('apps/domain/existing-app-test');
});

it('should determine directory from existing project and suffix', async () => {
options.suffix = 'integration-tests';
testProjectName = options.targetProject + '-' + options.suffix;
await generator(tree, options, dotnetClient);
const config = readProjectConfiguration(tree, testProjectName);
expect(config.root).toBe('apps/domain/existing-app-integration-tests');
});

describe('calculateTestTargetNameAndRoot', () => {
it('should handle names that dont contain path segments', () => {
expect(
calculateTestTargetNameAndRoot(
'nx',
'existing-app',
'apps/domain/existing-app',
),
).toMatchInlineSnapshot(`
{
"name": "existing-app-test",
"root": "apps/domain/existing-app-test",
}
`);
});

it('should handle names that contain path segments', () => {
expect(
calculateTestTargetNameAndRoot(
'nx',
'domain-existing-app',
'apps/domain/existing-app',
),
).toMatchInlineSnapshot(`
{
"name": "domain-existing-app-test",
"root": "apps/domain/existing-app-test",
}
`);
});

it('should handle names with multiple path segments', () => {
expect(
calculateTestTargetNameAndRoot(
'nx',
'shared-domain-existing-app',
'apps/shared/domain/existing-app',
),
).toMatchInlineSnapshot(`
{
"name": "shared-domain-existing-app-test",
"root": "apps/shared/domain/existing-app-test",
}
`);
});

it('should handle roots that contain a portion of the project name', () => {
expect(
calculateTestTargetNameAndRoot(
'nx',
'shared-existing-app',
'apps/shared/domain/shared-existing-app',
),
).toMatchInlineSnapshot(`
{
"name": "shared-existing-app-test",
"root": "apps/shared/domain/shared-existing-app-test",
}
`);
});
});
});
Loading

0 comments on commit 7b2f502

Please sign in to comment.