Skip to content

Commit

Permalink
fix: the tsconfig spec generated for library contains several issues
Browse files Browse the repository at this point in the history
  • Loading branch information
cpaulve-1A committed Jan 21, 2025
1 parent 3ffc0ba commit 8d98aed
Show file tree
Hide file tree
Showing 21 changed files with 199 additions and 67 deletions.
13 changes: 12 additions & 1 deletion packages/@o3r/components/schematics/index.it.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/
const o3rEnvironment = globalThis.o3rEnvironment;

import fs from 'node:fs';
import * as path from 'node:path';
import {
getDefaultExecSyncOptions,
Expand Down Expand Up @@ -50,7 +51,17 @@ describe('ng add components', () => {
expect(diff.modified).toContain('package.json');
expect(diff.modified).toContain('angular.json');
expect(diff.modified).toContain('libs/test-lib/package.json');
expect(diff.modified.length).toBe(8);
const vscodeContent = fs.readFileSync(`${workspacePath}/.vscode/extensions.json`, 'utf8');
const angularJSON = JSON.parse(fs.readFileSync(`${workspacePath}/angular.json`, 'utf8'));
expect(vscodeContent).toContain('"Orta.vscode-jest"');
expect(angularJSON.schematics['@o3r/core:component']).toBeDefined();
expect(angularJSON.schematics['@o3r/core:component-container']).toBeDefined();
expect(angularJSON.schematics['@o3r/core:component-presenter']).toBeDefined();
expect(angularJSON.cli?.schematicCollections?.indexOf('@o3r/components') > -1).toBe(true);

const packageJson = JSON.parse(fs.readFileSync(`${workspacePath}/package.json`, 'utf8'));
expect(packageJson.dependencies['@o3r/components']).toBeDefined();

expect(diff.added).toContain('libs/test-lib/cms.json');
expect(diff.added).toContain('libs/test-lib/placeholders.metadata.json');
expect(diff.added).toContain('libs/test-lib/tsconfig.cms.json');
Expand Down
15 changes: 12 additions & 3 deletions packages/@o3r/configuration/schematics/index.it.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/
const o3rEnvironment = globalThis.o3rEnvironment;

import * as fs from 'node:fs';
import * as path from 'node:path';
import {
addImportToAppModule,
Expand Down Expand Up @@ -49,7 +50,7 @@ describe('new otter application with configuration', () => {
expect(() => packageManagerRunOnProject(appName, isInWorkspace, { script: 'build' }, execAppOptions)).not.toThrow();
});
test('should add configuration to a library', () => {
const { applicationPath, workspacePath, libName, libraryPath, isInWorkspace, untouchedProjectsPaths, o3rVersion } = o3rEnvironment.testEnvironment;
const { workspacePath, untouchedProjectsPaths, isInWorkspace, applicationPath, libName, libraryPath, o3rVersion } = o3rEnvironment.testEnvironment;
const execAppOptions = { ...getDefaultExecSyncOptions(), cwd: workspacePath };
const relativeLibraryPath = path.relative(workspacePath, libraryPath);
packageManagerExec({ script: 'ng', args: ['add', `@o3r/configuration@${o3rVersion}`, '--skip-confirmation', '--project-name', libName] }, execAppOptions);
Expand All @@ -66,8 +67,16 @@ describe('new otter application with configuration', () => {

const diff = getGitDiff(workspacePath);
expect(diff.added.length).toEqual(20);
expect(diff.modified.length).toEqual(7);
expect(diff.modified).toContain('package.json');
const vscodeContent = fs.readFileSync(`${workspacePath}/.vscode/extensions.json`, 'utf8');
const angularJSON = JSON.parse(fs.readFileSync(`${workspacePath}/angular.json`, 'utf8'));
expect(vscodeContent).toContain('"Orta.vscode-jest"');
expect(angularJSON.schematics['@o3r/core:component']).toBeDefined();
expect(angularJSON.schematics['@o3r/core:component-container']).toBeDefined();
expect(angularJSON.schematics['@o3r/core:component-presenter']).toBeDefined();
expect(angularJSON.cli?.schematicCollections?.indexOf('@o3r/configuration') > -1).toBe(true);

const packageJson = JSON.parse(fs.readFileSync(`${workspacePath}/package.json`, 'utf8'));
expect(packageJson.dependencies['@o3r/configuration']).toBeDefined();
expect(diff.added).toContain(path.posix.join(relativeLibraryPath, 'src/components/test-component/test-component.config.ts').replace(/[/\\]+/g, '/'));
expect(diff.added).toContain(path.posix.join(relativeLibraryPath, 'src/components/test-signal/test-signal.config.ts').replace(/[/\\]+/g, '/'));

Expand Down
3 changes: 3 additions & 0 deletions packages/@o3r/testing/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,9 @@
"typescript-eslint": "~8.19.0",
"zone.js": "~0.14.2"
},
"generatorDependencies": {
"@angular-builders/jest": "~18.0.0"
},
"schematics": "./collection.json",
"ng-update": {
"migrations": "./migration.json"
Expand Down
5 changes: 4 additions & 1 deletion packages/@o3r/testing/schematics/ng-add/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ const devDependenciesToInstall = [
'jest-environment-jsdom',
'jest-preset-angular',
'ts-jest',
'@angular-builders/jest',
'@angular-devkit/build-angular',
'@types/jest'
];

Expand Down Expand Up @@ -162,7 +164,8 @@ function ngAddFn(options: NgAddSchematicsSchema): Rule {

const jestConfigFilesForWorkspace = () => mergeWith(apply(url('./templates/workspace'), [
template({
...options
...options,
tsconfigPath: `./${['tsconfig.base.json', 'tsconfig.json'].find((tsconfigBase) => tree.exists(`./${tsconfigBase}`))}`
}),
move(tree.root.path),
renameTemplateFiles()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"extends": "<%= tsconfigPath %>",
"compilerOptions": {
"strictPropertyInitialization": false,
"strictNullChecks": false,
"types": ["node", "jest"],
"composite": true,
"esModuleInterop": true
},
"include": []
}
1 change: 1 addition & 0 deletions packages/@o3r/workspace/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@
},
"generatorDependencies": {
"@angular/material": "~18.2.0",
"@angular-builders/jest": "~18.0.0",
"@ngrx/router-store": "~18.0.0",
"@ngrx/effects": "~18.0.0",
"@ngrx/store-devtools": "~18.0.0",
Expand Down
2 changes: 2 additions & 0 deletions packages/@o3r/workspace/schematics/index.it.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ describe('new otter workspace', () => {
expect(() => packageManagerExec({ script: 'ng', args: ['g', 'library', libName] }, execAppOptions)).not.toThrow();
expect(existsSync(path.join(workspacePath, 'project'))).toBe(false);
generatedLibFiles.forEach((file) => expect(existsSync(path.join(inLibraryPath, file))).toBe(true));
// TODO apps are generated without jest full configuration - needs to be fixed before removing this part
expect(() => packageManagerExec({ script: 'ng', args: ['test', libName] }, execAppOptions)).not.toThrow();
expect(() => packageManagerRunOnProject(libName, true, { script: 'build' }, execAppOptions)).not.toThrow();
});

Expand Down
53 changes: 48 additions & 5 deletions packages/@o3r/workspace/schematics/library/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ jest.mock('@angular-devkit/schematics', () => {
});

const collectionPath = path.join(__dirname, '..', '..', 'collection.json');
const angularJsonFile = `{
"version": 1,
"projects": {
"my-new-module": {
"projectType": "library",
"root": "packages-test/my-new-module"
}
}
}`;

describe('New module generator', () => {
let initialTree: Tree;
Expand All @@ -36,7 +45,7 @@ describe('New module generator', () => {
});

it('should generate the minimum mandatory files', async () => {
initialTree.create('angular.json', '{"version": 1, "projects": {} }');
initialTree.create('angular.json', angularJsonFile);
initialTree.create('package.json', '{ "version": "0.0.0-test" }');
initialTree.create('/packages-test/my-new-module/package.json', '{ "version": "0.0.0-test" }');
initialTree.create('/packages-test/my-new-module/ng-package.json', '{ }');
Expand All @@ -58,11 +67,43 @@ describe('New module generator', () => {
expect(tree.exists('/packages-test/my-new-module/project.json')).toBe(false);
expect(JSON.parse(tree.readContent('/tsconfig.base.json')).compilerOptions.paths['@my/new-module']).toContain('packages-test/my-new-module/src/public-api');
expect(JSON.parse(tree.readContent('/tsconfig.build.json')).compilerOptions.paths['@my/new-module'][0]).toBe('packages-test/my-new-module/dist');
expect(tree.exists('/packages-test/my-new-module/testing/setup-jest.ts')).toBe(false);
expect(JSON.parse(tree.readContent('/packages-test/my-new-module/package.json')).scripts.test).toContain('ng test my-new-module');
expect(tree.exists('/packages-test/my-new-module/jest.config.js')).toBe(false);
expect(tree.files.length).toBeGreaterThanOrEqual(9);
});

// eslint-disable-next-line jest/no-disabled-tests -- TODO: Should be re-enable when the following issue #2066 is fixed
describe.skip('in NX monorepo', () => {
it('should generate an project with jest files', async () => {
initialTree.create('angular.json', angularJsonFile);
initialTree.create('package.json', '{ "version": "0.0.0-test" }');
initialTree.create('/packages-test/my-new-module/package.json', '{ "version": "0.0.0-test" }');
initialTree.create('/packages-test/my-new-module/ng-package.json', '{ }');
const runner = new SchematicTestRunner('schematics', collectionPath);
const angularPackageJson = require.resolve('@schematics/angular/package.json');
const o3rCorePackageJson = require.resolve('@o3r/core/package.json');
runner.registerCollection('@o3r/core', path.resolve(path.dirname(o3rCorePackageJson), require(o3rCorePackageJson).schematics));
runner.registerCollection('@schematics/angular', path.resolve(path.dirname(angularPackageJson), require(angularPackageJson).schematics));
jest.spyOn(require('@angular-devkit/schematics'), 'externalSchematic');
const tree = await runner.runSchematic('library', {
path: 'packages-test',
name: '@my/new-module',
skipLinter: true,
skipInstall: true,
testingFramework: 'jest'
}, initialTree);
expect(tree.exists('/packages-test/my-new-module/testing/setup-jest.ts')).toBe(true);
expect(tree.exists('/packages-test/my-new-module/jest.config.js')).toBe(true);
const packageJsonContent = tree.readJson('/packages-test/my-new-module/package.json') as any;
expect(packageJsonContent.scripts.test).toBe('ng test my-new-module');
expect(packageJsonContent.devDependencies['@angular-builders/jest']).toBeDefined();
(tree.readJson('/packages-test/my-new-module/tsconfig.spec.json') as { references: { path: string }[] })
.references
.forEach((ref) => {
expect(tree.exists(path.join('/packages-test/my-new-module', ref.path))).toBe(true);
});
});

describe('in NX monorepo', () => {
it('should generate Nx project.json with given name', async () => {
initialTree.create('nx.json', '{"workspaceLayout": { "libsDir": "packages-test" } }');
initialTree.create('angular.json', '{"version": 1, "projects": {} }');
Expand All @@ -77,14 +118,16 @@ describe('New module generator', () => {
runner.registerCollection('@schematics/angular', path.resolve(path.dirname(angularPackageJson), require(angularPackageJson).schematics));
runner.registerCollection('@nx/workspace', path.resolve(path.dirname(nxWorkspacePackageJson), require(nxWorkspacePackageJson).generators));
const tree = await runner.runExternalSchematic('schematics', 'library', {
path: 'packages-test',
name: '@my/new-module',
projectName: 'test-module-name',
skipLinter: true
}, initialTree);

expect(tree.exists('/packages-test/my-new-module/project.json')).toBe(true);
expect(tree.readContent('/packages-test/my-new-module/project.json')).toContain('"name": "test-module-name"');
const projectJson: any = tree.readJson('/packages-test/my-new-module/project.json');
expect(projectJson.name).toBe('test-module-name');
expect(tree.exists(projectJson.targets.test.options.jestConfig)).toBe(true);
expect(projectJson.targets.test.executor).toBe('@nrwl/jest:jest');
});
});
});
78 changes: 73 additions & 5 deletions packages/@o3r/workspace/schematics/library/rules/rules.ng.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ import {
template,
url,
} from '@angular-devkit/schematics';
import type {
Tree,
} from '@angular-devkit/schematics';
import {
findConfigFileRelativePath,
} from '@o3r/schematics';
Expand All @@ -32,6 +35,44 @@ import {
updatePackageDependenciesFactory,
} from './shared';

/**
* Set jest files and script in the generated library.
* @param options
*/
function setUpAngularTestPackageJson(options: NgGenerateModuleSchema & { targetPath: string }): Rule {
return (tree: Tree) => {
const packageJsonPath = path.join(options.targetPath, 'package.json');
const packageJsonContent = tree.readJson(packageJsonPath) as PackageJson;
packageJsonContent.scripts ||= {};
packageJsonContent.scripts.test ||= `ng test ${options.name}`;
tree.overwrite(packageJsonPath, JSON.stringify(packageJsonContent, null, 2));
return tree;
};
}

/**
* Set jest files and script in the generated library.
* @param options
*/
function setUpJestForAngularJson(options: NgGenerateModuleSchema & { targetPath: string }) {
return (tree: Tree) => {
const angularFile = tree.readJson('/angular.json') as { projects: any };
const project: any = angularFile.projects[options.name];
project.architect ||= {};
project.architect.test = {
builder: '@angular-builders/jest:run',
options: {
tsConfig: `tsconfig.spec.json`,
configPath: `jest.config.js`,
setupFilesAfterEnv: './testing/setup-jest.ts'
}
};

tree.overwrite('/angular.json', JSON.stringify(angularFile, null, 2));
return tree;
};
}

/**
* generate the rules to adapt the library generated by ng cli
* @param options Schematic options
Expand All @@ -50,21 +91,48 @@ export function ngGenerateModule(options: NgGenerateModuleSchema & { targetPath:
const o3rCorePackageJson: PackageJson & { generatorDependencies?: Record<string, string> } = JSON.parse(readFileSync(o3rCorePackageJsonPath).toString());
const otterVersion = o3rCorePackageJson.dependencies!['@o3r/schematics'];

const templateNg = apply(url('./templates/ng'), [
const templateNg = apply(url('./templates/ng/common'), [
template({
...options,
tsconfigSpecPath: findConfigFileRelativePath(tree,
['tsconfig.test.json', 'tsconfig.spec.json', 'tsconfig.jest.json', 'tsconfig.jasmine.json', 'tsconfig.base.json', 'tsconfig.json'], options.targetPath),
tsconfigBasePath: findConfigFileRelativePath(tree, ['tsconfig.base.json', 'tsconfig.json'], options.targetPath),
tsconfigBuildPath: findConfigFileRelativePath(tree, ['tsconfig.build.json', 'tsconfig.base.json', 'tsconfig.json'], options.targetPath)
}),
renameTemplateFiles(),
move(options.targetPath)
]);

const templateCommonJest = apply(url('./templates/jest'), [
template({
...options,
tsconfigBasePath: findConfigFileRelativePath(tree, ['tsconfig.base.json', 'tsconfig.json'], options.targetPath)
}),
renameTemplateFiles(),
move(options.targetPath)
]);
const templateNgJest = apply(url('./templates/ng/jest'), [
template({
...options,
tsconfigSpecPath: findConfigFileRelativePath(tree,
['tsconfig.test.json', 'tsconfig.spec.json', 'tsconfig.jest.json', 'tsconfig.jasmine.json', 'tsconfig.base.json', 'tsconfig.json'], options.targetPath),
tsconfigBasePath: findConfigFileRelativePath(tree, ['tsconfig.base.json', 'tsconfig.json'], options.targetPath)
}),
renameTemplateFiles(),
move(options.targetPath)
]);
const packageJsonContent = tree.readText('/package.json');
const hasJestInstalled = options.testingFramework === 'jest' || packageJsonContent.match('"jest"');
return chain([
mergeWith(templateNg, MergeStrategy.Overwrite),
updatePackageDependenciesFactory(options.targetPath, otterVersion!, o3rCorePackageJson, options),
...hasJestInstalled
? [
mergeWith(templateCommonJest, MergeStrategy.Overwrite),
mergeWith(templateNgJest, MergeStrategy.Overwrite),
setUpJestForAngularJson(options),
setUpAngularTestPackageJson({ ...options })
]
: [
setUpAngularTestPackageJson(options)
],
updatePackageDependenciesFactory(options.targetPath, otterVersion!, o3rCorePackageJson, { ...options, useJest: !!hasJestInstalled }),
updateNgPackagrFactory(options.targetPath),
(t) => {
const genPackageJsonPath = path.posix.join(options.targetPath, 'package.json');
Expand Down
14 changes: 11 additions & 3 deletions packages/@o3r/workspace/schematics/library/rules/rules.nx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,25 +105,33 @@ export function nxGenerateModule(options: NgGenerateModuleSchema & { packageJson
const o3rCorePackageJsonPath = path.resolve(__dirname, '..', '..', '..', 'package.json');
const o3rCorePackageJson: PackageJson & { generatorDependencies?: Record<string, string> } = JSON.parse(readFileSync(o3rCorePackageJsonPath).toString());
const otterVersion = o3rCorePackageJson.dependencies!['@o3r/schematics'];

const templateNx = apply(url('./templates/nx'), [
template({
...options,
path: targetPath,
projectRoot: path.posix.resolve(targetPath, options.name),
projectRoot: targetPath,
otterVersion,
tsconfigBasePath: findConfigFileRelativePath(tree, ['tsconfig.base.json', 'tsconfig.json'], targetPath),
runner: getPackageManagerRunner(getWorkspaceConfig(tree))
}),
renameTemplateFiles(),
move(targetPath)
]);
const templateJest = apply(url('./templates/jest'), [
template({
...options,
tsconfigBasePath: findConfigFileRelativePath(tree, ['tsconfig.base.json', 'tsconfig.json'], targetPath)
}),
renameTemplateFiles(),
move(targetPath)
]);
rules.push(mergeWith(templateNx, MergeStrategy.Overwrite));

return chain([
...rules,
updatePackageDependenciesFactory(targetPath, otterVersion!, o3rCorePackageJson, options),
updatePackageDependenciesFactory(targetPath, otterVersion!, o3rCorePackageJson, { ...options, useJest: true }),
updateNgPackagrFactory(targetPath),
mergeWith(templateJest, MergeStrategy.Overwrite),
(t) => {
const packageJson = t.readJson(path.posix.join(targetPath, 'package.json')) as PackageJson;
packageJson.name = options.packageJsonName;
Expand Down
Loading

0 comments on commit 8d98aed

Please sign in to comment.