diff --git a/apps/showcase/testing/jest.config.ut.js b/apps/showcase/testing/jest.config.ut.js index f41c7a6fc3..de8c6d5297 100644 --- a/apps/showcase/testing/jest.config.ut.js +++ b/apps/showcase/testing/jest.config.ut.js @@ -9,5 +9,9 @@ module.exports = { ...createCjsPreset(getTsJestBaseConfig()), ...getOtterJestBaseConfig(rootDir), ...getJestUnitTestConfig(), - setupFilesAfterEnv: ['/testing/setup-jest.ts'] + setupFilesAfterEnv: ['/testing/setup-jest.ts'], + coveragePathIgnorePatterns: [ + '/dev-resources/', + '/training-assets/' + ] }; diff --git a/codecov.yml b/codecov.yml index a731428e85..fdb45f70e3 100644 --- a/codecov.yml +++ b/codecov.yml @@ -32,11 +32,6 @@ ignore: - 'apps/@*/*/build' # Generated files - - 'apps/showcase/dev-resources' - - 'apps/showcase/training-assets' - - 'packages/@o3r-training/showcase-sdk/src/api' - - 'packages/@o3r-training/showcase-sdk/src/models/base' - - 'packages/@o3r-training/showcase-sdk/src/spec' - 'tools/github-actions/*/packaged-action' # Templates diff --git a/packages/@ama-sdk/schematics/migration.json b/packages/@ama-sdk/schematics/migration.json index 7ab3dc0fc1..c1257502b4 100644 --- a/packages/@ama-sdk/schematics/migration.json +++ b/packages/@ama-sdk/schematics/migration.json @@ -30,6 +30,11 @@ "version": "12.1.3", "description": "Updates of @ama-sdk/schematics to v12.1.3", "factory": "./schematics/ng-update/index#updateV12_1_3" + }, + "migration-v12_3": { + "version": "12.3.0-prerelease.0", + "description": "Updates of @ama-sdk/schematics to v12.3.*", + "factory": "./schematics/ng-update/index#updateV12_3" } } } diff --git a/packages/@ama-sdk/schematics/package.json b/packages/@ama-sdk/schematics/package.json index 33df374a47..72ecc1c219 100644 --- a/packages/@ama-sdk/schematics/package.json +++ b/packages/@ama-sdk/schematics/package.json @@ -59,6 +59,9 @@ }, "type-fest": { "optional": true + }, + "typescript": { + "optional": true } }, "peerDependencies": { @@ -71,7 +74,8 @@ "@openapitools/openapi-generator-cli": "^2.15.0", "openapi-types": "^12.0.0", "ts-node": "~10.9.2", - "type-fest": "^4.30.1" + "type-fest": "^4.30.1", + "typescript": "^5.5.4" }, "dependencies": { "@angular-devkit/core": "~19.2.0", @@ -146,7 +150,7 @@ "@swc/cli": "~0.7.0", "@swc/core": "~1.11.0", "@swc/helpers": "~0.5.0", - "@typescript-eslint/eslint-plugin": "~8.30.0", + "@typescript-eslint/eslint-plugin": "~8.31.0", "jest-junit": "~16.0.0", "lint-staged": "^15.0.0", "minimist": "^1.2.6", diff --git a/packages/@ama-sdk/schematics/schematics/ng-update/index.ts b/packages/@ama-sdk/schematics/schematics/ng-update/index.ts index d04a0597c4..596f2f369f 100644 --- a/packages/@ama-sdk/schematics/schematics/ng-update/index.ts +++ b/packages/@ama-sdk/schematics/schematics/ng-update/index.ts @@ -11,6 +11,7 @@ import { updateV11_0 as tsUpdateV11_0, updateV11_4 as tsUpdateV11_4, updateV12_1_3 as tsUpdateV12_1_3, + updateV12_3 as tsUpdateV12_3, } from './typescript'; /** @@ -96,3 +97,17 @@ export function updateV12_1_3(): Rule { return tree; }; } + +/** + * update of Otter library V12.3 + */ +// eslint-disable-next-line @typescript-eslint/naming-convention -- function name contains the version +export function updateV12_3(): Rule { + return (tree, context) => { + if (isTypescriptSdk(tree)) { + return tsUpdateV12_3()(tree, context); + } + + return tree; + }; +} diff --git a/packages/@ama-sdk/schematics/schematics/ng-update/typescript/index.ts b/packages/@ama-sdk/schematics/schematics/ng-update/typescript/index.ts index ab185c8d8a..768078b6e9 100644 --- a/packages/@ama-sdk/schematics/schematics/ng-update/typescript/index.ts +++ b/packages/@ama-sdk/schematics/schematics/ng-update/typescript/index.ts @@ -25,6 +25,9 @@ import { import { clearPackageJsonExports, } from './v12.1/clean-packagejson-exports'; +import { + updateJestConfigCoveragePathIgnorePatterns, +} from './v12.3/coverage-ignore'; /** * update of Otter library V10.0 @@ -100,3 +103,15 @@ export function updateV12_1_3(): Rule { return chain(updateRules); } + +/** + * Update of Ama-sdk library V12.3 + */ +// eslint-disable-next-line @typescript-eslint/naming-convention -- function name contains the version +export function updateV12_3(): Rule { + const updateRules: Rule[] = [ + updateJestConfigCoveragePathIgnorePatterns + ]; + + return chain(updateRules); +} diff --git a/packages/@ama-sdk/schematics/schematics/ng-update/typescript/v12.3/coverage-ignore.spec.ts b/packages/@ama-sdk/schematics/schematics/ng-update/typescript/v12.3/coverage-ignore.spec.ts new file mode 100644 index 0000000000..f95be552cf --- /dev/null +++ b/packages/@ama-sdk/schematics/schematics/ng-update/typescript/v12.3/coverage-ignore.spec.ts @@ -0,0 +1,37 @@ +import { + readFileSync, +} from 'node:fs'; +import { + resolve, +} from 'node:path'; +import { + Tree, +} from '@angular-devkit/schematics'; +import { + updateJestConfigCoveragePathIgnorePatterns, +} from './coverage-ignore'; + +describe('updateJestConfigCoveragePathIgnorePatterns', () => { + const mock = readFileSync(resolve(__dirname, '..', '..', '..', '..', 'testing', 'mocks', 'jest-config', 'mock.jest.config.js'), { encoding: 'utf8' }); + const resultContent = readFileSync(resolve(__dirname, '..', '..', '..', '..', 'testing', 'mocks', 'jest-config', 'result.jest.config.js'), { encoding: 'utf8' }); + + beforeEach(() => { + jest.resetModules(); + }); + + test('should not touch other files', async () => { + const tree = Tree.empty(); + tree.create('other.js', mock); + await updateJestConfigCoveragePathIgnorePatterns(tree, { logger: { info: jest.fn() } } as any); + expect(tree.readText('other.js')).toBe(mock); + }); + + test('should update jest.config.js', async () => { + const tree = Tree.empty(); + tree.create('jest.config.js', mock); + const context = { logger: { info: jest.fn(), warn: jest.fn() } } as any; + await updateJestConfigCoveragePathIgnorePatterns(tree, context); + expect(context.logger.warn).not.toHaveBeenCalled(); + expect(tree.readText('jest.config.js')).toBe(resultContent); + }); +}); diff --git a/packages/@ama-sdk/schematics/schematics/ng-update/typescript/v12.3/coverage-ignore.ts b/packages/@ama-sdk/schematics/schematics/ng-update/typescript/v12.3/coverage-ignore.ts new file mode 100644 index 0000000000..cd41179bae --- /dev/null +++ b/packages/@ama-sdk/schematics/schematics/ng-update/typescript/v12.3/coverage-ignore.ts @@ -0,0 +1,83 @@ +import type { + Rule, +} from '@angular-devkit/schematics'; +import * as ts from 'typescript'; + +const coveragePathIgnorePatterns = [ + '/src/api/**/*.ts', + '/src/models/base/**/*.ts', + '/src/spec/api-mock.ts', + '/src/spec/operation-adapter.ts' +]; + +/** + * Update Jest config to ignore coverage of generated path + * @param tree + * @param context + */ +export const updateJestConfigCoveragePathIgnorePatterns: Rule = (tree, context) => { + const filePath = 'jest.config.js'; + if (!tree.exists(filePath)) { + context.logger.info(`No ${filePath} found, the coverage ignore pattern won't be added.`); + return; + } + + const tsSourceFile = ts.createSourceFile( + filePath, + tree.readText(filePath), + ts.ScriptTarget.Latest, + true + ); + + const result = ts.transform(tsSourceFile, [ + (ctx) => (rootNode) => { + const { factory } = ctx; + return ts.visitNode(rootNode, (node) => { + return ts.visitEachChild(node, (statement) => { + if ( + ts.isExpressionStatement(statement) + && ts.isBinaryExpression(statement.expression) + && /module\.exports/.test(statement.expression.left.getText(rootNode)) + && ts.isObjectLiteralExpression(statement.expression.right) + && !statement.expression.right.properties.some((prop) => ts.isPropertyAssignment(prop) && prop.name.getText(rootNode) === 'coveragePathIgnorePatterns') + ) { + return factory.updateExpressionStatement( + statement, + factory.updateBinaryExpression(statement.expression, + statement.expression.left, + statement.expression.operatorToken, + factory.updateObjectLiteralExpression(statement.expression.right, [ + ...statement.expression.right.properties, + factory.createPropertyAssignment('coveragePathIgnorePatterns', factory.createArrayLiteralExpression( + coveragePathIgnorePatterns.map((pattern) => factory.createStringLiteral(pattern, true)), + true + )) + ]) + ) + ); + } + }, ctx); + }) as ts.SourceFile; + } + ]); + + const transformedSourceFile = result.transformed[0]; + const printer = ts.createPrinter({ + removeComments: false, + newLine: ts.NewLineKind.LineFeed + }); + + const content = printer.printFile(transformedSourceFile) + .split('\n') + // migrate from 4 spaces to 2 spaces indent + .map((line) => { + const match = line.match(/^ */); + const numberSpaces = match ? match[0].length : 0; + const newNumber = (numberSpaces - numberSpaces % 2) / 2; + return line.replace(/^ */, Array.from({ length: newNumber }).fill(' ').join('')); + }) + .join('\n'); + + tree.overwrite(filePath, content); + return tree; +}; diff --git a/packages/@ama-sdk/schematics/schematics/typescript/shell/templates/base/jest.config.js.template b/packages/@ama-sdk/schematics/schematics/typescript/shell/templates/base/jest.config.js.template index 1c98da915c..2edbd0de94 100644 --- a/packages/@ama-sdk/schematics/schematics/typescript/shell/templates/base/jest.config.js.template +++ b/packages/@ama-sdk/schematics/schematics/typescript/shell/templates/base/jest.config.js.template @@ -22,5 +22,11 @@ module.exports = { stringifyContentPathRegex: '\\.html$', } ] - } + }, + coveragePathIgnorePatterns: [ + '/src/api/**/*.ts', + '/src/models/base/**/*.ts', + '/src/spec/api-mock.ts', + '/src/spec/operation-adapter.ts' + ] }; diff --git a/packages/@ama-sdk/schematics/testing/mocks/jest-config/mock.jest.config.js b/packages/@ama-sdk/schematics/testing/mocks/jest-config/mock.jest.config.js new file mode 100644 index 0000000000..db425ed2ed --- /dev/null +++ b/packages/@ama-sdk/schematics/testing/mocks/jest-config/mock.jest.config.js @@ -0,0 +1,11 @@ +/** @type {import('ts-jest/dist/types').JestConfigWithTsJest} */ +module.exports = { + displayName: require('./package.json').name, + preset: 'ts-jest', + rootDir: '.', + roots: ['/src/'], + reporters: [ + 'default', + ['jest-junit', { outputDirectory: '/dist-test', suiteName: '<% if (projectName) { %>@<%=projectName%>/<% } %><%=projectPackageName%> unit tests' }] + ] +}; diff --git a/packages/@ama-sdk/schematics/testing/mocks/jest-config/result.jest.config.js b/packages/@ama-sdk/schematics/testing/mocks/jest-config/result.jest.config.js new file mode 100644 index 0000000000..c50bcd9978 --- /dev/null +++ b/packages/@ama-sdk/schematics/testing/mocks/jest-config/result.jest.config.js @@ -0,0 +1,17 @@ +/** @type {import('ts-jest/dist/types').JestConfigWithTsJest} */ +module.exports = { + displayName: require('./package.json').name, + preset: 'ts-jest', + rootDir: '.', + roots: ['/src/'], + reporters: [ + 'default', + ['jest-junit', { outputDirectory: '/dist-test', suiteName: '<% if (projectName) { %>@<%=projectName%>/<% } %><%=projectPackageName%> unit tests' }] + ], + coveragePathIgnorePatterns: [ + '/src/api/**/*.ts', + '/src/models/base/**/*.ts', + '/src/spec/api-mock.ts', + '/src/spec/operation-adapter.ts' + ] +}; diff --git a/packages/@o3r-training/showcase-sdk/testing/jest.config.ut.js b/packages/@o3r-training/showcase-sdk/testing/jest.config.ut.js index 3514638388..96f65b67c7 100644 --- a/packages/@o3r-training/showcase-sdk/testing/jest.config.ut.js +++ b/packages/@o3r-training/showcase-sdk/testing/jest.config.ut.js @@ -8,5 +8,11 @@ const rootDir = path.join(__dirname, '..'); module.exports = { ...createDefaultPreset(getTsJestBaseConfig()), ...getOtterJestBaseConfig(rootDir), - ...getJestUnitTestConfig() + ...getJestUnitTestConfig(), + coveragePathIgnorePatterns: [ + '/src/api/**/*.ts', + '/src/models/base/**/*.ts', + '/src/spec/api-mock.ts', + '/src/spec/operation-adapter.ts' + ] }; diff --git a/packages/@o3r-training/training-sdk/testing/jest.config.ut.js b/packages/@o3r-training/training-sdk/testing/jest.config.ut.js index 3514638388..96f65b67c7 100644 --- a/packages/@o3r-training/training-sdk/testing/jest.config.ut.js +++ b/packages/@o3r-training/training-sdk/testing/jest.config.ut.js @@ -8,5 +8,11 @@ const rootDir = path.join(__dirname, '..'); module.exports = { ...createDefaultPreset(getTsJestBaseConfig()), ...getOtterJestBaseConfig(rootDir), - ...getJestUnitTestConfig() + ...getJestUnitTestConfig(), + coveragePathIgnorePatterns: [ + '/src/api/**/*.ts', + '/src/models/base/**/*.ts', + '/src/spec/api-mock.ts', + '/src/spec/operation-adapter.ts' + ] }; diff --git a/packages/@o3r/core/package.json b/packages/@o3r/core/package.json index 90adf6151d..c1947a3191 100644 --- a/packages/@o3r/core/package.json +++ b/packages/@o3r/core/package.json @@ -170,8 +170,8 @@ "@o3r/store-sync": "workspace:^", "@stylistic/eslint-plugin": "~3.1.0", "@types/jest": "~29.5.2", - "@typescript-eslint/eslint-plugin": "~8.30.0", - "@typescript-eslint/parser": "~8.30.0", + "@typescript-eslint/eslint-plugin": "~8.31.0", + "@typescript-eslint/parser": "~8.31.0", "angular-eslint": "~19.3.0", "cpy-cli": "^5.0.0", "eslint": "~9.25.0", @@ -190,7 +190,7 @@ "jest-preset-angular": "~14.5.0", "jsonc-eslint-parser": "~2.4.0", "nx": "~20.8.0", - "typescript-eslint": "~8.30.0", + "typescript-eslint": "~8.31.0", "zone.js": "~0.15.0" }, "engines": { diff --git a/packages/@o3r/eslint-config-otter/package.json b/packages/@o3r/eslint-config-otter/package.json index 861dc948b4..926d0014e9 100644 --- a/packages/@o3r/eslint-config-otter/package.json +++ b/packages/@o3r/eslint-config-otter/package.json @@ -63,9 +63,9 @@ "typescript": "^5.5.4" }, "generatorDependencies": { - "@typescript-eslint/eslint-plugin": "~8.30.0", - "@typescript-eslint/parser": "~8.30.0", - "@typescript-eslint/utils": "~8.30.0", + "@typescript-eslint/eslint-plugin": "~8.31.0", + "@typescript-eslint/parser": "~8.31.0", + "@typescript-eslint/utils": "~8.31.0", "eslint": "~9.25.0", "eslint-plugin-jsdoc": "~50.6.0", "eslint-plugin-unicorn": "~56.0.0" diff --git a/yarn.lock b/yarn.lock index 4b1b77b4b2..109cb9c0b3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -879,6 +879,7 @@ __metadata: openapi-types: ^12.0.0 ts-node: ~10.9.2 type-fest: ^4.30.1 + typescript: ^5.5.4 peerDependenciesMeta: "@ama-sdk/core": optional: true @@ -896,6 +897,8 @@ __metadata: optional: true type-fest: optional: true + typescript: + optional: true bin: amasdk-clear-index: ./dist/cli/clear-index.cjs amasdk-files-pack: ./dist/cli/files-pack.cjs