diff --git a/packages/@ama-sdk/create/src/index.it.spec.ts b/packages/@ama-sdk/create/src/index.it.spec.ts index aaf653bf86..7178fd41e4 100644 --- a/packages/@ama-sdk/create/src/index.it.spec.ts +++ b/packages/@ama-sdk/create/src/index.it.spec.ts @@ -1,3 +1,11 @@ +/** + * Test environment exported by O3rEnvironment, must be first line of the file + * @jest-environment @o3r/test-helpers/jest-environment + * @jest-environment-o3r-app-folder test-create-sdk + * @jest-environment-o3r-type blank + */ +const o3rEnvironment = globalThis.o3rEnvironment; + import { getDefaultExecSyncOptions, getPackageManager, @@ -5,28 +13,23 @@ import { packageManagerCreate, packageManagerExec, packageManagerInstall, - packageManagerRun, - prepareTestEnv, - setupLocalRegistry + packageManagerRun } from '@o3r/test-helpers'; import * as fs from 'node:fs'; import { cpSync, mkdirSync, renameSync } from 'node:fs'; import * as path from 'node:path'; -const projectName = 'test-sdk'; const sdkPackageName = '@my-test/sdk'; -const o3rVersion = '999.0.0'; let sdkFolderPath: string; let sdkPackagePath: string; const execAppOptions = getDefaultExecSyncOptions(); const packageManager = getPackageManager(); describe('Create new sdk command', () => { - setupLocalRegistry(); - beforeEach(async () => { + beforeEach(() => { const isYarnTest = packageManager.startsWith('yarn'); const yarnVersion = isYarnTest ? getYarnVersionFromRoot(process.cwd()) || 'latest' : undefined; - sdkFolderPath = (await prepareTestEnv(projectName, {type: 'blank', yarnVersion })).workspacePath; + sdkFolderPath = o3rEnvironment.testEnvironment.workspacePath; sdkPackagePath = path.join(sdkFolderPath, sdkPackageName.replace(/^@/, '')); execAppOptions.cwd = sdkFolderPath; @@ -98,7 +101,7 @@ describe('Create new sdk command', () => { test('should use pinned versions when --exact-o3r-version is used', () => { expect(() => packageManagerCreate({ - script: `@ama-sdk@${o3rVersion}`, + script: `@ama-sdk@${o3rEnvironment.testEnvironment.o3rVersion}`, args: ['typescript', sdkPackageName, '--exact-o3r-version', '--package-manager', packageManager, '--spec-path', path.join(sdkFolderPath, 'swagger-spec.yml')] }, execAppOptions) ).not.toThrow(); @@ -109,7 +112,7 @@ describe('Create new sdk command', () => { [ ...Object.entries(packageJson.dependencies), ...Object.entries(packageJson.devDependencies), ...Object.entries(resolutions) ].filter(([dep]) => dep.startsWith('@o3r/') || dep.startsWith('@ama-sdk/')).forEach(([,version]) => { - expect(version).toBe(o3rVersion); + expect(version).toBe(o3rEnvironment.testEnvironment.o3rVersion); }); }); }); diff --git a/packages/@o3r/analytics/schematics/index.it.spec.ts b/packages/@o3r/analytics/schematics/index.it.spec.ts index 60bc1bad5b..d1266fbe31 100644 --- a/packages/@o3r/analytics/schematics/index.it.spec.ts +++ b/packages/@o3r/analytics/schematics/index.it.spec.ts @@ -1,41 +1,31 @@ +/** + * Test environment exported by O3rEnvironment, must be first line of the file + * @jest-environment @o3r/test-helpers/jest-environment + * @jest-environment-o3r-app-folder test-app-analytics + */ +const o3rEnvironment = globalThis.o3rEnvironment; + import { addImportToAppModule, getDefaultExecSyncOptions, getGitDiff, packageManagerExec, packageManagerInstall, - packageManagerRunOnProject, - prepareTestEnv, - setupLocalRegistry + packageManagerRunOnProject } from '@o3r/test-helpers'; -import { rm } from 'node:fs/promises'; import * as path from 'node:path'; -const appFolder = 'test-app-analytics'; -const o3rVersion = '999.0.0'; -const execAppOptions = getDefaultExecSyncOptions(); -let projectPath: string; -let isInWorkspace: boolean; -let workspacePath: string; -let projectName: string; -let untouchedProjectPath: undefined | string; describe('new otter application with analytics', () => { - setupLocalRegistry(); - beforeAll(async () => { - ({ projectPath, workspacePath, projectName, isInWorkspace, untouchedProjectPath } = await prepareTestEnv(appFolder)); - execAppOptions.cwd = workspacePath; - }); - afterAll(async () => { - try { await rm(workspacePath, { recursive: true }); } catch { /* ignore error */ } - }); - test('should add analytics to existing application', () => { + test('should add analytics to existing application', async () => { + const { projectPath, workspacePath, projectName, isInWorkspace, untouchedProjectPath, o3rVersion } = o3rEnvironment.testEnvironment; + const execAppOptions = {...getDefaultExecSyncOptions(), cwd: workspacePath}; const relativeProjectPath = path.relative(workspacePath, projectPath); packageManagerExec({script: 'ng', args: ['add', `@o3r/analytics@${o3rVersion}`, '--project-name', projectName, '--skip-confirmation']}, execAppOptions); packageManagerExec({script: 'ng', args: ['g', '@o3r/core:component', 'test-component', '--use-otter-analytics', 'false', '--project-name', projectName]}, execAppOptions); const componentPath = path.normalize(path.join(relativeProjectPath, 'src/components/test-component/test-component.component.ts')); packageManagerExec({script: 'ng', args: ['g', '@o3r/analytics:add-analytics', '--path', componentPath]}, execAppOptions); - addImportToAppModule(projectPath, 'TestComponentModule', 'src/components/test-component'); + await addImportToAppModule(projectPath, 'TestComponentModule', 'src/components/test-component'); const diff = getGitDiff(workspacePath); expect(diff.all.some((file) => /projects[\\/]dont-modify-me/.test(file))).toBe(false); diff --git a/packages/@o3r/apis-manager/schematics/index.it.spec.ts b/packages/@o3r/apis-manager/schematics/index.it.spec.ts index 7b41fdd4fb..7007c1b654 100644 --- a/packages/@o3r/apis-manager/schematics/index.it.spec.ts +++ b/packages/@o3r/apis-manager/schematics/index.it.spec.ts @@ -1,32 +1,23 @@ +/** + * Test environment exported by O3rEnvironment, must be first line of the file + * @jest-environment @o3r/test-helpers/jest-environment + * @jest-environment-o3r-app-folder test-app-apis-manager + */ +const o3rEnvironment = globalThis.o3rEnvironment; + import { getDefaultExecSyncOptions, getGitDiff, packageManagerExec, packageManagerInstall, - packageManagerRunOnProject, - prepareTestEnv, - setupLocalRegistry + packageManagerRunOnProject } from '@o3r/test-helpers'; import * as path from 'node:path'; -import { rm } from 'node:fs/promises'; -const appFolder = 'test-app-apis-manager'; -const o3rVersion = '999.0.0'; -const execAppOptions = getDefaultExecSyncOptions(); -let workspacePath: string; -let projectName: string; -let isInWorkspace: boolean; -let untouchedProjectPath: undefined | string; describe('new otter application with apis-manager', () => { - setupLocalRegistry(); - beforeAll(async () => { - ({ workspacePath, projectName, isInWorkspace, untouchedProjectPath } = await prepareTestEnv(appFolder)); - execAppOptions.cwd = workspacePath; - }); - afterAll(async () => { - try { await rm(workspacePath, { recursive: true }); } catch { /* ignore error */ } - }); test('should add apis-manager to existing application', () => { + const { workspacePath, projectName, isInWorkspace, untouchedProjectPath, o3rVersion } = o3rEnvironment.testEnvironment; + const execAppOptions = {...getDefaultExecSyncOptions(), cwd: workspacePath}; packageManagerExec({script: 'ng', args: ['add', `@o3r/apis-manager@${o3rVersion}`, '--skip-confirmation', '--project-name', projectName]}, execAppOptions); expect(() => packageManagerInstall(execAppOptions)).not.toThrow(); diff --git a/packages/@o3r/components/schematics/index.it.spec.ts b/packages/@o3r/components/schematics/index.it.spec.ts index 5af250f483..7112edcef4 100644 --- a/packages/@o3r/components/schematics/index.it.spec.ts +++ b/packages/@o3r/components/schematics/index.it.spec.ts @@ -1,32 +1,23 @@ +/** + * Test environment exported by O3rEnvironment, must be first line of the file + * @jest-environment @o3r/test-helpers/jest-environment + * @jest-environment-o3r-app-folder test-app-components + */ +const o3rEnvironment = globalThis.o3rEnvironment; + import { getDefaultExecSyncOptions, getGitDiff, packageManagerExec, packageManagerInstall, - packageManagerRunOnProject, - prepareTestEnv, - setupLocalRegistry + packageManagerRunOnProject } from '@o3r/test-helpers'; import * as path from 'node:path'; -import { rm } from 'node:fs/promises'; -const appFolder = 'test-app-components'; -const o3rVersion = '999.0.0'; -const execAppOptions = getDefaultExecSyncOptions(); -let workspacePath: string; -let projectName: string; -let isInWorkspace: boolean; -let untouchedProjectPath: undefined | string; describe('new otter application with components', () => { - setupLocalRegistry(); - beforeAll(async () => { - ({ workspacePath, projectName, isInWorkspace, untouchedProjectPath } = await prepareTestEnv(appFolder)); - execAppOptions.cwd = workspacePath; - }); - afterAll(async () => { - try { await rm(workspacePath, { recursive: true }); } catch { /* ignore error */ } - }); test('should add components to existing application', () => { + const { workspacePath, projectName, isInWorkspace, untouchedProjectPath, o3rVersion } = o3rEnvironment.testEnvironment; + const execAppOptions = {...getDefaultExecSyncOptions(), cwd: workspacePath}; packageManagerExec({script: 'ng', args: ['add', `@o3r/components@${o3rVersion}`, '--skip-confirmation', '--enable-metadata-extract', '--project-name', projectName]}, execAppOptions); expect(() => packageManagerInstall(execAppOptions)).not.toThrow(); diff --git a/packages/@o3r/configuration/schematics/index.it.spec.ts b/packages/@o3r/configuration/schematics/index.it.spec.ts index 2b3df9dde5..5416cbf7d5 100644 --- a/packages/@o3r/configuration/schematics/index.it.spec.ts +++ b/packages/@o3r/configuration/schematics/index.it.spec.ts @@ -1,34 +1,24 @@ +/** + * Test environment exported by O3rEnvironment, must be first line of the file + * @jest-environment @o3r/test-helpers/jest-environment + * @jest-environment-o3r-app-folder test-app-configuration + */ +const o3rEnvironment = globalThis.o3rEnvironment; + import { addImportToAppModule, getDefaultExecSyncOptions, getGitDiff, packageManagerExec, packageManagerInstall, - packageManagerRunOnProject, - prepareTestEnv, - setupLocalRegistry + packageManagerRunOnProject } from '@o3r/test-helpers'; -import { rm } from 'node:fs/promises'; import * as path from 'node:path'; -const appFolder = 'test-app-configuration'; -const o3rVersion = '999.0.0'; -const execAppOptions = getDefaultExecSyncOptions(); -let projectPath: string; -let workspacePath: string; -let projectName: string; -let isInWorkspace: boolean; -let untouchedProjectPath: undefined | string; describe('new otter application with configuration', () => { - setupLocalRegistry(); - beforeAll(async () => { - ({ projectPath, workspacePath, projectName, isInWorkspace, untouchedProjectPath } = await prepareTestEnv(appFolder)); - execAppOptions.cwd = workspacePath; - }); - afterAll(async () => { - try { await rm(workspacePath, { recursive: true }); } catch { /* ignore error */ } - }); test('should add configuration to existing application', async () => { + const { projectPath, workspacePath, projectName, isInWorkspace, untouchedProjectPath, o3rVersion } = o3rEnvironment.testEnvironment; + const execAppOptions = {...getDefaultExecSyncOptions(), cwd: workspacePath}; const relativeProjectPath = path.relative(workspacePath, projectPath); packageManagerExec({script: 'ng', args: ['add', `@o3r/configuration@${o3rVersion}`, '--skip-confirmation', '--project-name', projectName]}, execAppOptions); diff --git a/packages/@o3r/core/schematics/index.it.spec.ts b/packages/@o3r/core/schematics/index.it.spec.ts index fed8f82f98..b3bd366736 100644 --- a/packages/@o3r/core/schematics/index.it.spec.ts +++ b/packages/@o3r/core/schematics/index.it.spec.ts @@ -1,3 +1,10 @@ +/** + * Test environment exported by O3rEnvironment, must be first line of the file + * @jest-environment @o3r/test-helpers/jest-environment + * @jest-environment-o3r-app-folder test-app-core + */ +const o3rEnvironment = globalThis.o3rEnvironment; + import { addImportToAppModule, getDefaultExecSyncOptions, @@ -5,31 +12,17 @@ import { packageManagerExec, packageManagerExecOnProject, packageManagerInstall, - packageManagerRunOnProject, - prepareTestEnv, - setupLocalRegistry + packageManagerRunOnProject } from '@o3r/test-helpers'; import * as path from 'node:path'; import { execSync, spawn } from 'node:child_process'; import getPidFromPort from 'pid-from-port'; -import { rm } from 'node:fs/promises'; const devServerPort = 4200; -const appFolder = 'test-app-core'; -const o3rVersion = '999.0.0'; -const execAppOptions = getDefaultExecSyncOptions(); -let projectPath: string; -let workspacePath: string; -let projectName: string; -let isInWorkspace: boolean; -let untouchedProjectPath: undefined | string; describe('new otter application', () => { - setupLocalRegistry(); - beforeAll(async () => { - ({ projectPath, workspacePath, projectName, isInWorkspace, untouchedProjectPath } = await prepareTestEnv(appFolder)); - execAppOptions.cwd = workspacePath; - }); test('should build empty app', async () => { + const { projectPath, workspacePath, projectName, isInWorkspace, untouchedProjectPath, o3rVersion } = o3rEnvironment.testEnvironment; + const execAppOptions = {...getDefaultExecSyncOptions(), cwd: workspacePath}; const relativeProjectPath = path.relative(workspacePath, projectPath); const projectNameOptions = ['--project-name', projectName]; packageManagerExec({script: 'ng', args: ['add', `@o3r/core@${o3rVersion}`, '--preset', 'all', ...projectNameOptions, '--skip-confirmation']}, execAppOptions); @@ -110,7 +103,7 @@ describe('new otter application', () => { packageManagerExec({script: 'ng', args: ['g', '@o3r/testing:playwright-scenario', '--name', 'test-scenario', ...projectNameOptions]}, execAppOptions); packageManagerExec({script: 'ng', args: ['g', '@o3r/testing:playwright-sanity', '--name', 'test-sanity', ...projectNameOptions]}, execAppOptions); - const diff = getGitDiff(execAppOptions.cwd as string); + const diff = getGitDiff(execAppOptions.cwd); if (untouchedProjectPath) { const relativeUntouchedProjectPath = path.relative(workspacePath, untouchedProjectPath); @@ -149,7 +142,4 @@ describe('new otter application', () => { // http-server already off } }); - afterAll(async () => { - try { await rm(workspacePath, { recursive: true }); } catch { /* ignore error */ } - }); }); diff --git a/packages/@o3r/create/src/index.it.spec.ts b/packages/@o3r/create/src/index.it.spec.ts index 9885f02001..bde9e52255 100644 --- a/packages/@o3r/create/src/index.it.spec.ts +++ b/packages/@o3r/create/src/index.it.spec.ts @@ -1,40 +1,33 @@ +/** + * Test environment exported by O3rEnvironment, must be first line of the file + * @jest-environment @o3r/test-helpers/jest-environment + * @jest-environment-o3r-app-folder test-create-app + * @jest-environment-o3r-type blank + */ +const o3rEnvironment = globalThis.o3rEnvironment; + import { getDefaultExecSyncOptions, getPackageManager, - type PackageManagerConfig, packageManagerCreate, packageManagerExec, packageManagerInstall, packageManagerRunOnProject, - prepareTestEnv, - setPackagerManagerConfig, - setupLocalRegistry + setPackagerManagerConfig } from '@o3r/test-helpers'; import { existsSync, promises as fs } from 'node:fs'; import * as path from 'node:path'; -const appFolder = 'test-create-app'; +const defaultExecOptions = getDefaultExecSyncOptions(); const workspaceProjectName = 'my-project'; -const o3rVersion = '999.0.0'; -let workspacePath: string; -let packageManagerConfig: PackageManagerConfig; -const execWorkspaceOptions = getDefaultExecSyncOptions(); describe('Create new otter project command', () => { - setupLocalRegistry(); - beforeEach(async () => { - ({ workspacePath, packageManagerConfig, workspacePath } = (await prepareTestEnv(appFolder, {type: 'blank' }))); - execWorkspaceOptions.cwd = workspacePath; - }); - - afterAll(async () => { - try { await fs.rm(workspacePath, { recursive: true }); } catch { /* ignore error */ } - }); - test('should generate a project with an application', async () => { - const createOptions = ['--package-manager', getPackageManager(), '--skip-confirmation', ...(packageManagerConfig.yarnVersion ? ['--yarn-version', packageManagerConfig.yarnVersion] : [])]; + const { workspacePath, packageManagerConfig, o3rVersion } = o3rEnvironment.testEnvironment; const inAppPath = path.join(workspacePath, workspaceProjectName); - const execInAppOptions = {...execWorkspaceOptions, cwd: inAppPath }; + const execWorkspaceOptions = {...defaultExecOptions, cwd: workspacePath }; + const execInAppOptions = {...defaultExecOptions, cwd: inAppPath }; + const createOptions = ['--package-manager', getPackageManager(), '--skip-confirmation', ...(packageManagerConfig.yarnVersion ? ['--yarn-version', packageManagerConfig.yarnVersion] : [])]; // TODO: remove it when fixing #1356 await fs.mkdir(inAppPath, { recursive: true }); @@ -52,11 +45,13 @@ describe('Create new otter project command', () => { }); test('should generate a project with an application with --exact-o3r-version', async () => { + const { workspacePath, packageManagerConfig, o3rVersion } = o3rEnvironment.testEnvironment; + const inAppPath = path.join(workspacePath, workspaceProjectName); + const execWorkspaceOptions = {...defaultExecOptions, cwd: workspacePath }; + const execInAppOptions = {...defaultExecOptions, cwd: inAppPath }; const packageManager = getPackageManager(); const createOptions = ['--package-manager', packageManager, '--skip-confirmation', '--exact-o3r-version', ...(packageManagerConfig.yarnVersion ? ['--yarn-version', packageManagerConfig.yarnVersion] : [])]; - const inAppPath = path.join(workspacePath, workspaceProjectName); - const execInAppOptions = {...execWorkspaceOptions, cwd: inAppPath }; // TODO: remove it when fixing #1356 await fs.mkdir(inAppPath, { recursive: true }); diff --git a/packages/@o3r/design/schematics/index.it.spec.ts b/packages/@o3r/design/schematics/index.it.spec.ts index 6cdedbc293..b5dc9efd47 100644 --- a/packages/@o3r/design/schematics/index.it.spec.ts +++ b/packages/@o3r/design/schematics/index.it.spec.ts @@ -1,32 +1,23 @@ +/** + * Test environment exported by O3rEnvironment, must be first line of the file + * @jest-environment @o3r/test-helpers/jest-environment + * @jest-environment-o3r-app-folder test-app-design + */ +const o3rEnvironment = globalThis.o3rEnvironment; + import { getDefaultExecSyncOptions, getGitDiff, packageManagerExec, packageManagerInstall, - packageManagerRunOnProject, - prepareTestEnv, - setupLocalRegistry + packageManagerRunOnProject } from '@o3r/test-helpers'; import * as path from 'node:path'; -import { rm } from 'node:fs/promises'; -const appFolder = 'test-app-design'; -const o3rVersion = '999.0.0'; -const execAppOptions = getDefaultExecSyncOptions(); -let workspacePath: string; -let projectName: string; -let isInWorkspace: boolean; -let untouchedProjectPath: undefined | string; describe('new otter application with Design', () => { - setupLocalRegistry(); - beforeAll(async () => { - ({ projectName, isInWorkspace, workspacePath } = await prepareTestEnv(appFolder)); - execAppOptions.cwd = workspacePath; - }); - afterAll(async () => { - try { await rm(workspacePath, { recursive: true }); } catch { /* ignore error */ } - }); test('should add design to existing application', () => { + const { workspacePath, projectName, isInWorkspace, untouchedProjectPath, o3rVersion } = o3rEnvironment.testEnvironment; + const execAppOptions = {...getDefaultExecSyncOptions(), cwd: workspacePath}; packageManagerExec({script: 'ng', args: ['add', `@o3r/design@${o3rVersion}`, '--skip-confirmation', '--project-name', projectName]}, execAppOptions); expect(() => packageManagerInstall(execAppOptions)).not.toThrow(); diff --git a/packages/@o3r/extractors/schematics/index.it.spec.ts b/packages/@o3r/extractors/schematics/index.it.spec.ts index 1dcedc72e0..f0ab99f040 100644 --- a/packages/@o3r/extractors/schematics/index.it.spec.ts +++ b/packages/@o3r/extractors/schematics/index.it.spec.ts @@ -1,32 +1,23 @@ +/** + * Test environment exported by O3rEnvironment, must be first line of the file + * @jest-environment @o3r/test-helpers/jest-environment + * @jest-environment-o3r-app-folder test-app-extractors + */ +const o3rEnvironment = globalThis.o3rEnvironment; + import { getDefaultExecSyncOptions, getGitDiff, packageManagerExec, packageManagerInstall, - packageManagerRunOnProject, - prepareTestEnv, - setupLocalRegistry + packageManagerRunOnProject } from '@o3r/test-helpers'; import * as path from 'node:path'; -import { rm } from 'node:fs/promises'; -const appFolder = 'test-app-extractors'; -const o3rVersion = '999.0.0'; -const execAppOptions = getDefaultExecSyncOptions(); -let workspacePath: string; -let projectName: string; -let isInWorkspace: boolean; -let untouchedProjectPath: undefined | string; describe('new otter application with extractors', () => { - setupLocalRegistry(); - beforeAll(async () => { - ({ workspacePath, projectName, isInWorkspace, untouchedProjectPath } = await prepareTestEnv(appFolder)); - execAppOptions.cwd = workspacePath; - }); - afterAll(async () => { - try { await rm(workspacePath, { recursive: true }); } catch { /* ignore error */ } - }); test('should add extractors to existing application', () => { + const { workspacePath, projectName, isInWorkspace, untouchedProjectPath, o3rVersion } = o3rEnvironment.testEnvironment; + const execAppOptions = {...getDefaultExecSyncOptions(), cwd: workspacePath}; packageManagerExec({script: 'ng', args: ['add', `@o3r/extractors@${o3rVersion}`, '--skip-confirmation', '--project-name', projectName]}, execAppOptions); const diff = getGitDiff(workspacePath); diff --git a/packages/@o3r/localization/schematics/index.it.spec.ts b/packages/@o3r/localization/schematics/index.it.spec.ts index 642cd635a1..741e0b8226 100644 --- a/packages/@o3r/localization/schematics/index.it.spec.ts +++ b/packages/@o3r/localization/schematics/index.it.spec.ts @@ -1,34 +1,24 @@ +/** + * Test environment exported by O3rEnvironment, must be first line of the file + * @jest-environment @o3r/test-helpers/jest-environment + * @jest-environment-o3r-app-folder test-app-localization + */ +const o3rEnvironment = globalThis.o3rEnvironment; + import { addImportToAppModule, getDefaultExecSyncOptions, getGitDiff, packageManagerExec, packageManagerInstall, - packageManagerRunOnProject, - prepareTestEnv, - setupLocalRegistry + packageManagerRunOnProject } from '@o3r/test-helpers'; -import { rm } from 'node:fs/promises'; import * as path from 'node:path'; -const appFolder = 'test-app-localization'; -const o3rVersion = '999.0.0'; -const execAppOptions = getDefaultExecSyncOptions(); -let projectPath: string; -let workspacePath: string; -let projectName: string; -let isInWorkspace: boolean; -let untouchedProjectPath: undefined | string; describe('new otter application with localization', () => { - setupLocalRegistry(); - beforeAll(async () => { - ({ projectPath, workspacePath, projectName, isInWorkspace, untouchedProjectPath } = await prepareTestEnv(appFolder)); - execAppOptions.cwd = workspacePath; - }); - afterAll(async () => { - try { await rm(workspacePath, { recursive: true }); } catch { /* ignore error */ } - }); test('should add localization to existing application', async () => { + const { projectPath, workspacePath, projectName, isInWorkspace, untouchedProjectPath, o3rVersion } = o3rEnvironment.testEnvironment; + const execAppOptions = {...getDefaultExecSyncOptions(), cwd: workspacePath}; const relativeProjectPath = path.relative(workspacePath, projectPath); packageManagerExec({script: 'ng', args: ['add', `@o3r/localization@${o3rVersion}`, '--skip-confirmation', '--project-name', projectName]}, execAppOptions); diff --git a/packages/@o3r/rules-engine/schematics/index.it.spec.ts b/packages/@o3r/rules-engine/schematics/index.it.spec.ts index 58b26bef12..99c4a40c6b 100644 --- a/packages/@o3r/rules-engine/schematics/index.it.spec.ts +++ b/packages/@o3r/rules-engine/schematics/index.it.spec.ts @@ -1,34 +1,24 @@ +/** + * Test environment exported by O3rEnvironment, must be first line of the file + * @jest-environment @o3r/test-helpers/jest-environment + * @jest-environment-o3r-app-folder test-app-rules-engine + */ +const o3rEnvironment = globalThis.o3rEnvironment; + import { addImportToAppModule, getDefaultExecSyncOptions, getGitDiff, packageManagerExec, packageManagerInstall, - packageManagerRunOnProject, - prepareTestEnv, - setupLocalRegistry + packageManagerRunOnProject } from '@o3r/test-helpers'; -import { rm } from 'node:fs/promises'; import * as path from 'node:path'; -const appFolder = 'test-app-rules-engine'; -const o3rVersion = '999.0.0'; -const execAppOptions = getDefaultExecSyncOptions(); -let projectPath: string; -let workspacePath: string; -let projectName: string; -let isInWorkspace: boolean; -let untouchedProjectPath: undefined | string; describe('new otter application with rules-engine', () => { - setupLocalRegistry(); - beforeAll(async () => { - ({ projectPath, workspacePath, projectName, isInWorkspace, untouchedProjectPath } = await prepareTestEnv(appFolder)); - execAppOptions.cwd = workspacePath; - }); - afterAll(async () => { - try { await rm(workspacePath, { recursive: true }); } catch { /* ignore error */ } - }); test('should add rules engine to existing application', async () => { + const { projectPath, workspacePath, projectName, isInWorkspace, untouchedProjectPath, o3rVersion } = o3rEnvironment.testEnvironment; + const execAppOptions = {...getDefaultExecSyncOptions(), cwd: workspacePath}; const relativeProjectPath = path.relative(workspacePath, projectPath); packageManagerExec({script: 'ng', args: ['add', `@o3r/rules-engine@${o3rVersion}`, '--enable-metadata-extract', '--project-name', projectName, '--skip-confirmation']}, execAppOptions); diff --git a/packages/@o3r/styling/schematics/index.it.spec.ts b/packages/@o3r/styling/schematics/index.it.spec.ts index 1f17619e6a..cc7f06c8a7 100644 --- a/packages/@o3r/styling/schematics/index.it.spec.ts +++ b/packages/@o3r/styling/schematics/index.it.spec.ts @@ -1,45 +1,33 @@ +/** + * Test environment exported by O3rEnvironment, must be first line of the file + * @jest-environment @o3r/test-helpers/jest-environment + * @jest-environment-o3r-app-folder test-app-styling + */ +const o3rEnvironment = globalThis.o3rEnvironment; + import { addImportToAppModule, getDefaultExecSyncOptions, getGitDiff, packageManagerExec, packageManagerInstall, - packageManagerRunOnProject, - prepareTestEnv, - setupLocalRegistry + packageManagerRunOnProject } from '@o3r/test-helpers'; -import { rm } from 'node:fs/promises'; import * as path from 'node:path'; -const appFolder = 'test-app-styling'; -const o3rVersion = '999.0.0'; -const execAppOptions = getDefaultExecSyncOptions(); -let projectPath: string; -let workspacePath: string; -let projectName: string; -let isInWorkspace: boolean; -let untouchedProjectPath: undefined | string; describe('new otter application with styling', () => { - setupLocalRegistry(); - beforeAll(async () => { - ({ projectPath, workspacePath, projectName, isInWorkspace, untouchedProjectPath } = await prepareTestEnv(appFolder)); - execAppOptions.cwd = workspacePath; - }); - afterAll(async () => { - try { await rm(workspacePath, { recursive: true }); } catch { /* ignore error */ } - }); test('should add styling to existing application', async () => { + const { projectPath, workspacePath, projectName, isInWorkspace, untouchedProjectPath, o3rVersion } = o3rEnvironment.testEnvironment; + const execAppOptions = {...getDefaultExecSyncOptions(), cwd: workspacePath}; const relativeProjectPath = path.relative(workspacePath, projectPath); packageManagerExec({script: 'ng', args: ['add', `@o3r/styling@${o3rVersion}`, '--enable-metadata-extract', '--skip-confirmation', '--project-name', projectName]}, execAppOptions); packageManagerExec({script: 'ng', args: ['g', '@o3r/core:component', '--defaults', 'true', 'test-component', '--use-otter-theming', 'false', '--project-name', projectName]}, execAppOptions); const filePath = path.normalize(path.join(relativeProjectPath, 'src/components/test-component/test-component.style.scss')); packageManagerExec({script: 'ng', args: ['g', '@o3r/styling:add-theming', '--path', filePath]}, execAppOptions); - addImportToAppModule(projectPath, 'TestComponentModule', 'src/components/test-component'); - await addImportToAppModule(projectPath, 'TestComponentModule', 'src/components/test-component'); - const diff = getGitDiff(execAppOptions.cwd as string); + const diff = getGitDiff(execAppOptions.cwd); expect(diff.modified).toContain('package.json'); expect(diff.added).toContain(path.join(relativeProjectPath, 'src/components/test-component/test-component.style.theme.scss').replace(/[\\/]+/g, '/')); diff --git a/packages/@o3r/test-helpers/package.json b/packages/@o3r/test-helpers/package.json index f8330620ad..de28b65779 100644 --- a/packages/@o3r/test-helpers/package.json +++ b/packages/@o3r/test-helpers/package.json @@ -12,6 +12,10 @@ "./package.json": { "default": "./package.json" }, + "./jest-environment": { + "types": "./src/jest-environment/index.ts", + "default": "./src/jest-environment/index.ts" + }, "./setup-jest-builders": { "types": "./src/setup-jest-builders/index.ts", "default": "./src/setup-jest-builders/index.ts" @@ -20,6 +24,7 @@ "peerDependencies": { "@angular-devkit/schematics": "~17.3.0", "@o3r/schematics": "workspace:^", + "jest-environment-node": "~29.7.0", "memfs": "~4.8.0", "minimist": "^1.2.6", "pid-from-port": "^1.1.3", @@ -39,6 +44,8 @@ "devDependencies": { "@angular-devkit/schematics": "~17.3.0", "@angular-eslint/eslint-plugin": "~17.3.0", + "@jest/environment": "~29.7.0", + "@jest/types": "~29.6.3", "@nx/eslint-plugin": "~18.1.0", "@o3r/eslint-plugin": "workspace:^", "@o3r/schematics": "workspace:^", @@ -58,6 +65,7 @@ "eslint-plugin-prefer-arrow": "~1.2.3", "eslint-plugin-unicorn": "^51.0.1", "jest": "~29.7.0", + "jest-environment-node": "~29.7.0", "jest-junit": "~16.0.0", "jsonc-eslint-parser": "~2.4.0", "memfs": "~4.8.0", @@ -82,6 +90,9 @@ "@o3r/schematics": { "optional": true }, + "jest-environment-node": { + "optional": true + }, "memfs": { "optional": true }, diff --git a/packages/@o3r/test-helpers/src/jest-environment/index.ts b/packages/@o3r/test-helpers/src/jest-environment/index.ts new file mode 100644 index 0000000000..6f81ce0abd --- /dev/null +++ b/packages/@o3r/test-helpers/src/jest-environment/index.ts @@ -0,0 +1,117 @@ +import type { EnvironmentContext, JestEnvironmentConfig } from '@jest/environment'; +import type { Circus } from '@jest/types'; +import { TestEnvironment as NodeTestEnvironment } from 'jest-environment-node'; +import { execSync } from 'node:child_process'; +import pidFromPort from 'pid-from-port'; +import { rm } from 'node:fs/promises'; +import path from 'node:path'; +import { prepareTestEnv, type PrepareTestEnvType } from '../prepare-test-env'; + +/** + * Return type of prepareTestEnv + */ +export type TestEnvironment = Awaited>; + +declare global { + // eslint-disable-next-line no-var + var o3rEnvironment: {testEnvironment: TestEnvironment}; +} + +const rootFolder = path.join(__dirname, '..', '..', '..', '..'); + +/** + * Custom Jest environment used to manage test environments with Verdaccio setup + */ +export class JestEnvironmentO3r extends NodeTestEnvironment { + /** + * Stop Verdaccio server at the end of the test + */ + private shouldHandleVerdaccio = false; + + /** + * Folder containing the generated files + */ + private readonly appFolder: string; + + /** + * Increment used in folder name in case of multiples tests + */ + private appIndex = 0; + + /** + * Type of test environment to be created + */ + private readonly prepareTestEnvType: PrepareTestEnvType | undefined; + + /** + * Map test name with test environment + */ + private readonly testEnvironments: Record = {}; + + constructor(config: JestEnvironmentConfig, context: EnvironmentContext) { + super(config, context); + // testEnvironment is undefined now but will be defined when test runs + this.global.o3rEnvironment = {} as typeof this.global.o3rEnvironment; + this.appFolder = context.docblockPragmas['jest-environment-o3r-app-folder'] as string; + this.prepareTestEnvType = context.docblockPragmas['jest-environment-o3r-type'] as PrepareTestEnvType | undefined; + } + + /** + * Start Verdaccio server if not already running on localhost:4873 + */ + private async startVerdaccio() { + try { + await pidFromPort(4873); + } catch (ex) { + this.shouldHandleVerdaccio = true; + execSync('yarn verdaccio:start', {cwd: rootFolder, stdio: 'inherit'}); + execSync('yarn verdaccio:publish', {cwd: rootFolder, stdio: 'inherit'}); + } + } + + /** + * Stop Verdaccio server if it was started by this class + */ + private stopVerdaccio() { + if (this.shouldHandleVerdaccio) { + execSync('yarn verdaccio:stop', {cwd: rootFolder, stdio: 'inherit'}); + } + } + + /** + * Catch Jest lifecycle events + * @param event + * @param _state + */ + public async handleTestEvent(event: Circus.AsyncEvent, _state: Circus.State) { + // Create test environment before test starts + if (event.name === 'test_start') { + const appFolder = `${this.appFolder}${this.appIndex++ || ''}`; + this.testEnvironments[event.test.name] = await prepareTestEnv(appFolder, {type: this.prepareTestEnvType}); + this.global.o3rEnvironment.testEnvironment = this.testEnvironments[event.test.name]; + } + // Cleanup test environment after test succeeds + if (event.name === 'test_fn_success' && this.testEnvironments[event.test.name]?.workspacePath) { + try { await rm(this.testEnvironments[event.test.name].workspacePath, { recursive: true }); } + catch { /* ignore error */ } + } + } + + /** + * Executed before any test starts + */ + public async setup() { + await this.startVerdaccio(); + await super.setup(); + } + + /** + * Executed after all tests are finished + */ + public async teardown() { + await super.teardown(); + this.stopVerdaccio(); + } +} + +export default JestEnvironmentO3r; diff --git a/packages/@o3r/test-helpers/src/prepare-test-env.ts b/packages/@o3r/test-helpers/src/prepare-test-env.ts index 854c09d39f..afeb31a167 100644 --- a/packages/@o3r/test-helpers/src/prepare-test-env.ts +++ b/packages/@o3r/test-helpers/src/prepare-test-env.ts @@ -47,6 +47,7 @@ export async function prepareTestEnv(folderName: string, options?: PrepareTestEn const workspacePath = path.resolve(itTestsFolderPath, folderName); const globalFolderPath = path.resolve(rootFolderPath, '.cache', 'test-app'); const cacheFolderPath = path.resolve(globalFolderPath, 'cache'); + const o3rVersion = '999.0.0'; JSON.parse(readFileSync(path.join(rootFolderPath, 'packages', '@o3r', 'core', 'package.json')).toString()); const yarnVersion: string = yarnVersionParam || getYarnVersionFromRoot(rootFolderPath); @@ -128,6 +129,7 @@ export async function prepareTestEnv(folderName: string, options?: PrepareTestEn projectName, appDirectory, cwd: itTestsFolderPath, + o3rVersion, logger, ...packageManagerConfig, replaceExisting: !process.env.CI @@ -155,6 +157,7 @@ export async function prepareTestEnv(folderName: string, options?: PrepareTestEn isInWorkspace, untouchedProject, untouchedProjectPath, - packageManagerConfig + packageManagerConfig, + o3rVersion }; } diff --git a/packages/@o3r/test-helpers/src/public_api.ts b/packages/@o3r/test-helpers/src/public_api.ts index 3825ffaf14..72a3278629 100644 --- a/packages/@o3r/test-helpers/src/public_api.ts +++ b/packages/@o3r/test-helpers/src/public_api.ts @@ -1,3 +1,4 @@ +export * from './jest-environment/index'; export * from './prepare-test-env'; export * from './test-environments/index'; export * from './utilities/index'; diff --git a/packages/@o3r/testing/schematics/index.it.spec.ts b/packages/@o3r/testing/schematics/index.it.spec.ts index 4074a0d78e..efc587d15a 100644 --- a/packages/@o3r/testing/schematics/index.it.spec.ts +++ b/packages/@o3r/testing/schematics/index.it.spec.ts @@ -1,34 +1,24 @@ +/** + * Test environment exported by O3rEnvironment, must be first line of the file + * @jest-environment @o3r/test-helpers/jest-environment + * @jest-environment-o3r-app-folder test-app-testing + */ +const o3rEnvironment = globalThis.o3rEnvironment; + import { addImportToAppModule, getDefaultExecSyncOptions, getGitDiff, packageManagerExec, packageManagerInstall, - packageManagerRunOnProject, - prepareTestEnv, - setupLocalRegistry + packageManagerRunOnProject } from '@o3r/test-helpers'; -import { rm } from 'node:fs/promises'; import * as path from 'node:path'; -const appFolder = 'test-app-testing'; -const o3rVersion = '999.0.0'; -const execAppOptions = getDefaultExecSyncOptions(); -let projectPath: string; -let workspacePath: string; -let projectName: string; -let isInWorkspace: boolean; -let untouchedProjectPath: undefined | string; describe('new otter application with testing', () => { - setupLocalRegistry(); - beforeAll(async () => { - ({ projectPath, workspacePath, projectName, isInWorkspace, untouchedProjectPath } = await prepareTestEnv(appFolder)); - execAppOptions.cwd = workspacePath; - }); - afterAll(async () => { - try { await rm(workspacePath, { recursive: true }); } catch { /* ignore error */ } - }); test('should add testing to existing application', async () => { + const { projectPath, workspacePath, projectName, isInWorkspace, untouchedProjectPath, o3rVersion } = o3rEnvironment.testEnvironment; + const execAppOptions = {...getDefaultExecSyncOptions(), cwd: workspacePath}; const relativeProjectPath = path.relative(workspacePath, projectPath); packageManagerExec({script: 'ng', args: ['add', `@o3r/testing@${o3rVersion}`, '--skip-confirmation', '--project-name', projectName]}, execAppOptions); @@ -38,7 +28,7 @@ describe('new otter application with testing', () => { packageManagerExec({script: 'ng', args: ['g', '@o3r/testing:add-fixture', '--path', componentPath]}, execAppOptions); await addImportToAppModule(projectPath, 'TestComponentContModule', 'src/components/test-component'); - const diff = getGitDiff(execAppOptions.cwd as string); + const diff = getGitDiff(execAppOptions.cwd); expect(diff.added).toContain(path.join(relativeProjectPath, 'src/components/test-component/container/test-component-cont.fixture.ts').replace(/[\\/]+/g, '/')); if (untouchedProjectPath) { diff --git a/yarn.lock b/yarn.lock index 2dfc99ca21..24459c2a54 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4360,7 +4360,7 @@ __metadata: languageName: node linkType: hard -"@jest/environment@npm:^29.7.0": +"@jest/environment@npm:^29.7.0, @jest/environment@npm:~29.7.0": version: 29.7.0 resolution: "@jest/environment@npm:29.7.0" dependencies: @@ -4521,7 +4521,7 @@ __metadata: languageName: node linkType: hard -"@jest/types@npm:^29.6.3": +"@jest/types@npm:^29.6.3, @jest/types@npm:~29.6.3": version: 29.6.3 resolution: "@jest/types@npm:29.6.3" dependencies: @@ -8911,6 +8911,8 @@ __metadata: dependencies: "@angular-devkit/schematics": "npm:~17.3.0" "@angular-eslint/eslint-plugin": "npm:~17.3.0" + "@jest/environment": "npm:~29.7.0" + "@jest/types": "npm:~29.6.3" "@nx/eslint-plugin": "npm:~18.1.0" "@o3r/eslint-plugin": "workspace:^" "@o3r/schematics": "workspace:^" @@ -8930,6 +8932,7 @@ __metadata: eslint-plugin-prefer-arrow: "npm:~1.2.3" eslint-plugin-unicorn: "npm:^51.0.1" jest: "npm:~29.7.0" + jest-environment-node: "npm:~29.7.0" jest-junit: "npm:~16.0.0" jsonc-eslint-parser: "npm:~2.4.0" memfs: "npm:~4.8.0" @@ -8946,6 +8949,7 @@ __metadata: peerDependencies: "@angular-devkit/schematics": ~17.3.0 "@o3r/schematics": "workspace:^" + jest-environment-node: ~29.7.0 memfs: ~4.8.0 minimist: ^1.2.6 pid-from-port: ^1.1.3 @@ -8956,6 +8960,8 @@ __metadata: optional: true "@o3r/schematics": optional: true + jest-environment-node: + optional: true memfs: optional: true unionfs: @@ -21196,7 +21202,7 @@ __metadata: languageName: node linkType: hard -"jest-environment-node@npm:^29.7.0": +"jest-environment-node@npm:^29.7.0, jest-environment-node@npm:~29.7.0": version: 29.7.0 resolution: "jest-environment-node@npm:29.7.0" dependencies: