diff --git a/src/application/project/configuration/manager/jsonConfigurationFileManager.ts b/src/application/project/configuration/manager/jsonConfigurationFileManager.ts index 7c698a2a..9196a0c9 100644 --- a/src/application/project/configuration/manager/jsonConfigurationFileManager.ts +++ b/src/application/project/configuration/manager/jsonConfigurationFileManager.ts @@ -39,6 +39,8 @@ export class JsonConfigurationFileManager implements ConfigurationManager { private readonly fileSystem: FileSystem; + private readonly projectDirectory: WorkingDirectory; + private readonly fullValidator: Validator; private readonly partialValidator: Validator; @@ -47,6 +49,7 @@ export class JsonConfigurationFileManager implements ConfigurationManager { public constructor(configuration: Configuration) { this.fileSystem = configuration.fileSystem; + this.projectDirectory = configuration.projectDirectory; this.fullValidator = configuration.fullValidator; this.partialValidator = configuration.partialValidator; this.configurationFile = configuration.configurationFile; @@ -54,7 +57,7 @@ export class JsonConfigurationFileManager implements ConfigurationManager { public async isInitialized(state: InitializationState = InitializationState.ANY): Promise { if (state === InitializationState.ANY) { - return this.fileSystem.exists(this.configurationFile); + return this.fileSystem.exists(this.getConfigurationFilePath()); } const validator = state === InitializationState.FULL @@ -159,7 +162,7 @@ export class JsonConfigurationFileManager implements ConfigurationManager { validator: Validator, ): Promise>> { const file: LoadedFile = { - path: this.configurationFile, + path: this.getConfigurationFilePath(), source: null, configuration: null, }; @@ -184,6 +187,12 @@ export class JsonConfigurationFileManager implements ConfigurationManager { return file; } + private getConfigurationFilePath(): string { + return this.fileSystem.isAbsolutePath(this.configurationFile) + ? this.configurationFile + : this.fileSystem.joinPaths(this.projectDirectory.get(), this.configurationFile); + } + private async validateConfiguration( validator: Validator, value: JsonValue, diff --git a/src/infrastructure/application/cli/cli.ts b/src/infrastructure/application/cli/cli.ts index d4725c46..2696acde 100644 --- a/src/infrastructure/application/cli/cli.ts +++ b/src/infrastructure/application/cli/cli.ts @@ -2818,12 +2818,7 @@ export class Cli { fullValidator: new FullCroctConfigurationValidator(), partialValidator: new PartialCroctConfigurationValidator(), projectDirectory: this.workingDirectory, - configurationFile: fileSystem.isAbsolutePath(this.configuration.configurationFile) - ? this.configuration.configurationFile - : fileSystem.joinPaths( - this.workingDirectory.get(), - this.configuration.configurationFile, - ), + configurationFile: this.configuration.configurationFile, }); return new IndexedConfigurationManager({ diff --git a/test/application/project/configuration/jsonConfigurationFileManager.test.ts b/test/application/project/configuration/jsonConfigurationFileManager.test.ts new file mode 100644 index 00000000..9e0fcae8 --- /dev/null +++ b/test/application/project/configuration/jsonConfigurationFileManager.test.ts @@ -0,0 +1,115 @@ +import type {FileSystem} from '@/application/fs/fileSystem'; +import type {Validator, ValidationResult} from '@/application/validation'; +import {VirtualizedWorkingDirectory} from '@/application/fs/workingDirectory/virtualizedWorkingDirectory'; +import type { + JsonProjectConfiguration, + JsonPartialProjectConfiguration, +} from '@/application/project/configuration/manager/jsonConfigurationFileManager'; +import {JsonConfigurationFileManager} from '@/application/project/configuration/manager/jsonConfigurationFileManager'; +import type {ProjectConfiguration} from '@/application/project/configuration/projectConfiguration'; + +describe('JsonConfigurationFileManager', () => { + const configuration: ProjectConfiguration = { + organization: 'org', + workspace: 'workspace', + applications: { + development: 'dev', + }, + defaultLocale: 'en', + locales: ['en'], + slots: {}, + components: {}, + }; + + function createFileSystem(files: Map): FileSystem { + return { + exists: (path: string): Promise => Promise.resolve(files.has(path)), + readTextFile: (path: string): Promise => { + const content = files.get(path); + + if (content === undefined) { + return Promise.reject(new Error(`File not found: ${path}`)); + } + + return Promise.resolve(content); + }, + writeTextFile: (path: string, content: string): Promise => { + files.set(path, content); + + return Promise.resolve(); + }, + isAbsolutePath: (path: string): boolean => path.startsWith('/'), + joinPaths: (...paths: string[]): string => paths.join('/'), + } as Partial as FileSystem; + } + + function createValidator(): Validator { + return { + validate: (data: unknown): ValidationResult => ({ + valid: true, + data: data as T, + }), + }; + } + + it('should resolve the configuration file against the current project directory', async () => { + const files = new Map(); + const projectDirectory = new VirtualizedWorkingDirectory('/initial'); + + const manager = new JsonConfigurationFileManager({ + fileSystem: createFileSystem(files), + projectDirectory: projectDirectory, + fullValidator: createValidator(), + partialValidator: createValidator(), + configurationFile: 'croct.json', + }); + + projectDirectory.setCurrentDirectory('/initial/project'); + + await manager.update(configuration); + + expect(files.has('/initial/croct.json')).toBe(false); + expect(files.has('/initial/project/croct.json')).toBe(true); + }); + + it('should load the configuration from the current project directory', async () => { + const files = new Map(); + const projectDirectory = new VirtualizedWorkingDirectory('/initial'); + + const manager = new JsonConfigurationFileManager({ + fileSystem: createFileSystem(files), + projectDirectory: projectDirectory, + fullValidator: createValidator(), + partialValidator: createValidator(), + configurationFile: 'croct.json', + }); + + files.set('/initial/project/croct.json', JSON.stringify(configuration)); + + await expect(manager.isInitialized()).resolves.toBe(false); + + projectDirectory.setCurrentDirectory('/initial/project'); + + await expect(manager.isInitialized()).resolves.toBe(true); + await expect(manager.load()).resolves.toEqual(configuration); + }); + + it('should use an absolute configuration file path as given', async () => { + const files = new Map(); + const projectDirectory = new VirtualizedWorkingDirectory('/initial'); + + const manager = new JsonConfigurationFileManager({ + fileSystem: createFileSystem(files), + projectDirectory: projectDirectory, + fullValidator: createValidator(), + partialValidator: createValidator(), + configurationFile: '/custom/croct.json', + }); + + projectDirectory.setCurrentDirectory('/initial/project'); + + await manager.update(configuration); + + expect(files.has('/custom/croct.json')).toBe(true); + }); +});