Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[draft] fix: the tsconfig spec generated for library contains several issues #2584

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@
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/component') > 0).toBe(true);

Check failure on line 60 in packages/@o3r/components/schematics/index.it.spec.ts

View workflow job for this annotation

GitHub Actions / it-tests / it-tests (ubuntu-latest, yarn, o3r-project-with-app)

ng add components › should add components to a library

expect(received).toBe(expected) // Object.is equality Expected: true Received: false at Object.<anonymous> (schematics/index.it.spec.ts:60:82)

Check failure on line 60 in packages/@o3r/components/schematics/index.it.spec.ts

View workflow job for this annotation

GitHub Actions / it-tests / it-tests (ubuntu-latest, npm, o3r-project-with-app)

ng add components › should add components to a library

expect(received).toBe(expected) // Object.is equality Expected: true Received: false at Object.<anonymous> (schematics/index.it.spec.ts:60:82)

const packageJson = JSON.parse(fs.readFileSync(`${workspacePath}/package.json`, 'utf8'));
expect(packageJson.dependencies['@o3r/component']).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
16 changes: 13 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 @@
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,17 @@

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/component') > 0).toBe(true);

Check failure on line 76 in packages/@o3r/configuration/schematics/index.it.spec.ts

View workflow job for this annotation

GitHub Actions / it-tests / it-tests (ubuntu-latest, yarn, o3r-project-with-app)

new otter application with configuration › should add configuration to a library

expect(received).toBe(expected) // Object.is equality Expected: true Received: false at Object.<anonymous> (schematics/index.it.spec.ts:76:82)

Check failure on line 76 in packages/@o3r/configuration/schematics/index.it.spec.ts

View workflow job for this annotation

GitHub Actions / it-tests / it-tests (ubuntu-latest, npm, o3r-project-with-app)

new otter application with configuration › should add configuration to a library

expect(received).toBe(expected) // Object.is equality Expected: true Received: false at Object.<anonymous> (schematics/index.it.spec.ts:76:82)

const packageJson = JSON.parse(fs.readFileSync(`${workspacePath}/package.json`, 'utf8'));
expect(packageJson.dependencies['@o3r/component']).toBeDefined();
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
2 changes: 2 additions & 0 deletions 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
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
5 changes: 4 additions & 1 deletion packages/@o3r/workspace/schematics/index.it.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
packageManagerRun,
packageManagerRunOnProject,
} from '@o3r/test-helpers';
import type {
import {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why did you remove the type import?

PackageJson,
} from 'type-fest';

Expand Down Expand Up @@ -114,6 +114,9 @@
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, 'c', 'lerna'] }, execAppOptions)).not.toThrow();

Check failure on line 118 in packages/@o3r/workspace/schematics/index.it.spec.ts

View workflow job for this annotation

GitHub Actions / it-tests / it-tests (ubuntu-latest, yarn, o3r-project-with-app)

new otter workspace › should add a library to an existing workspace

expect(received).not.toThrow() Error name: "Error" Error message: "Command failed: yarn ng test test-library c lerna STDERR: Error: Unknown arguments: c, lerna· OUTPUT: ,,Error: Unknown arguments: c, lerna " 115 | // Yarn doesn't log errors on stderr, so we need to get them from stdout to have them in the reports 116 | > 117 | throw new Error(`Command failed: ${args.join(' ')}\nSTDERR:\n${err.stderr?.toString() || ''}\nOUTPUT:\n${err.output?.toString() || ''}`); | ^ 118 | } 119 | } 120 | at execCmd (packages/@o3r/test-helpers/src/utilities/package-manager.ts:117:11) at packageManagerExec (packages/@o3r/test-helpers/src/utilities/package-manager.ts:178:10) at packages/@o3r/workspace/schematics/index.it.spec.ts:118:36 at Object.<anonymous> (.yarn/cache/expect-npm-29.7.0-62e9f7979e-63f97bc51f.zip/node_modules/expect/build/toThrowMatchers.js:74:11) at Object.throwingMatcher [as toThrow] (.yarn/cache/expect-npm-29.7.0-62e9f7979e-63f97bc51f.zip/node_modules/expect/build/index.js:320:21) at Object.<anonymous> (packages/@o3r/workspace/schematics/index.it.spec.ts:118:115) at Object.<anonymous> (schematics/index.it.spec.ts:118:115)

Check failure on line 118 in packages/@o3r/workspace/schematics/index.it.spec.ts

View workflow job for this annotation

GitHub Actions / it-tests / it-tests (ubuntu-latest, npm, o3r-project-with-app)

new otter workspace › should add a library to an existing workspace

expect(received).not.toThrow() Error name: "Error" Error message: "Command failed: npm exec ng test test-library c lerna STDERR: Error: Unknown arguments: c, lerna· OUTPUT: ,,Error: Unknown arguments: c, lerna " 115 | // Yarn doesn't log errors on stderr, so we need to get them from stdout to have them in the reports 116 | > 117 | throw new Error(`Command failed: ${args.join(' ')}\nSTDERR:\n${err.stderr?.toString() || ''}\nOUTPUT:\n${err.output?.toString() || ''}`); | ^ 118 | } 119 | } 120 | at execCmd (packages/@o3r/test-helpers/src/utilities/package-manager.ts:117:11) at packageManagerExec (packages/@o3r/test-helpers/src/utilities/package-manager.ts:178:10) at packages/@o3r/workspace/schematics/index.it.spec.ts:118:36 at Object.<anonymous> (.yarn/cache/expect-npm-29.7.0-62e9f7979e-63f97bc51f.zip/node_modules/expect/build/toThrowMatchers.js:74:11) at Object.throwingMatcher [as toThrow] (.yarn/cache/expect-npm-29.7.0-62e9f7979e-63f97bc51f.zip/node_modules/expect/build/index.js:320:21) at Object.<anonymous> (packages/@o3r/workspace/schematics/index.it.spec.ts:118:115) at Object.<anonymous> (schematics/index.it.spec.ts:118:115)
expect(() => packageManagerExec({ script: 'ng', args: ['test'] }, 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 -c lerna');
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');
});
});
});
83 changes: 78 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,49 @@ import {
updatePackageDependenciesFactory,
} from './shared';

/**
* Set jest files and script in the generated library.
* @param options
*/
function setUpAngularTestPackageJson(options: NgGenerateModuleSchema & { targetPath: string; configuration?: 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} ${options.configuration ? '-c ' + options.configuration : ''}`;
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: `${options.targetPath}/testing/setup-jest.ts`
},
configurations: {
lerna: {
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 +96,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, configuration: 'lerna' })
]
: [
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
Loading