From 27067dc80a61f1f571b3e9cb7090e4a485cc8005 Mon Sep 17 00:00:00 2001 From: Ricardo Devis Agullo Date: Wed, 27 Aug 2025 08:25:10 +0200 Subject: [PATCH] Fix loading info correctly --- src/cli/domain/get-mocked-plugins.ts | 38 ++--------- src/cli/domain/ocConfig.ts | 42 ++++++++++-- src/cli/facade/dev.ts | 5 +- src/registry/routes/component-preview.ts | 2 +- test/unit/cli-domain-get-mocked-plugins.js | 78 ++++++---------------- test/unit/cli-domain-ocConfig.js | 74 +++++++++++++++++++- 6 files changed, 135 insertions(+), 104 deletions(-) diff --git a/src/cli/domain/get-mocked-plugins.ts b/src/cli/domain/get-mocked-plugins.ts index a3f06879..99daa246 100644 --- a/src/cli/domain/get-mocked-plugins.ts +++ b/src/cli/domain/get-mocked-plugins.ts @@ -1,8 +1,6 @@ import path from 'node:path'; -import fs from 'fs-extra'; import strings from '../../resources/'; -import settings from '../../resources/settings'; import type { Logger } from '../logger'; import { getOcConfig } from './ocConfig'; @@ -98,44 +96,18 @@ const registerDynamicMocks = ( }) .filter((pluginMock): pluginMock is PluginMock => !!pluginMock); -const findPath = ( - pathToResolve: string, - fileName: string -): string | undefined => { - const rootDir = fs.realpathSync('.'); - const fileToResolve = path.join(pathToResolve, fileName); - - if (!fs.existsSync(fileToResolve)) { - if (pathToResolve === rootDir) { - return undefined; - } - const getParent = (pathToResolve: string) => - pathToResolve.split('/').slice(0, -1).join('/'); - - const parentDir = pathToResolve ? getParent(pathToResolve) : rootDir; - - return findPath(parentDir, fileName); - } - - return fileToResolve; -}; - export default function getMockedPlugins( logger: Logger, - componentsDir: string + componentsDir?: string ): PluginMock[] { componentsDir = path.resolve(componentsDir || '.'); let plugins: PluginMock[] = []; - const ocJsonFileName = settings.configFile.src.replace('./', ''); - const ocJsonPath = findPath(componentsDir, ocJsonFileName); - - if (!ocJsonPath) { - return plugins; - } - const content = getOcConfig(ocJsonPath); - const ocJsonLocation = ocJsonPath.slice(0, -ocJsonFileName.length); + const content = getOcConfig(componentsDir); + const ocJsonLocation = content.sourcePath + ? path.dirname(content.sourcePath) + : componentsDir; if (!content.development?.plugins) { return plugins; diff --git a/src/cli/domain/ocConfig.ts b/src/cli/domain/ocConfig.ts index a26250d2..93ed681e 100644 --- a/src/cli/domain/ocConfig.ts +++ b/src/cli/domain/ocConfig.ts @@ -1,4 +1,5 @@ import fs from 'node:fs'; +import path from 'node:path'; import settings from '../../resources/settings'; export interface OpenComponentsConfig { @@ -37,6 +38,7 @@ export interface OpenComponentsConfig { } type ParsedConfig = { + sourcePath?: string; registries: string[]; development: { plugins: { @@ -50,6 +52,28 @@ type ParsedConfig = { }; }; +const findPath = ( + pathToResolve: string, + fileName: string +): string | undefined => { + const rootDir = fs.realpathSync('.'); + const fileToResolve = path.join(pathToResolve, fileName); + + if (!fs.existsSync(fileToResolve)) { + if (pathToResolve === rootDir) { + return undefined; + } + const getParent = (pathToResolve: string) => + pathToResolve.split('/').slice(0, -1).join('/'); + + const parentDir = pathToResolve ? getParent(pathToResolve) : rootDir; + + return findPath(parentDir, fileName); + } + + return fileToResolve; +}; + function parseConfig(config: OpenComponentsConfig): ParsedConfig { const plugins = { ...(config.mocks?.plugins || {}), @@ -68,12 +92,15 @@ function parseConfig(config: OpenComponentsConfig): ParsedConfig { return parsedConfig; } -export function getOcConfig(path?: string): ParsedConfig { +export function getOcConfig(folder?: string): ParsedConfig { + const configPath = folder + ? findPath(folder, settings.configFile.src.replace('./', '')) || + settings.configFile.src + : settings.configFile.src; + try { - const config = JSON.parse( - fs.readFileSync(path || settings.configFile.src, 'utf8') - ); - return parseConfig(config); + const config = JSON.parse(fs.readFileSync(configPath, 'utf8')); + return { ...parseConfig(config), sourcePath: configPath }; } catch { return { registries: [], @@ -85,8 +112,9 @@ export function getOcConfig(path?: string): ParsedConfig { } export function setOcConfig(config: ParsedConfig, path?: string) { + const { sourcePath, ...rest } = config; fs.writeFileSync( - path || settings.configFile.src, - JSON.stringify(parseConfig(config), null, 2) + path || sourcePath || settings.configFile.src, + JSON.stringify(rest, null, 2) ); } diff --git a/src/cli/facade/dev.ts b/src/cli/facade/dev.ts index 56ce41da..d20717a0 100644 --- a/src/cli/facade/dev.ts +++ b/src/cli/facade/dev.ts @@ -1,17 +1,16 @@ import path from 'node:path'; import { promisify } from 'node:util'; import colors from 'colors/safe'; -import fs from 'fs-extra'; import getPortCb from 'getport'; import livereload from 'livereload'; import { fromPromise } from 'universalify'; import * as oc from '../../index'; import strings from '../../resources/index'; -import settings from '../../resources/settings'; import getMockedPlugins from '../domain/get-mocked-plugins'; import handleDependencies from '../domain/handle-dependencies'; import type { Local } from '../domain/local'; +import { getOcConfig } from '../domain/ocConfig'; import watch from '../domain/watch'; import type { Logger } from '../logger'; @@ -46,7 +45,7 @@ const dev = ({ local, logger }: { logger: Logger; local: Local }) => let fallbackClient = false; if (!fallbackRegistryUrl) { try { - const localConfig = await fs.readJson(settings.configFile.src); + const localConfig = getOcConfig(componentsDir); if ( !fallbackRegistryUrl && typeof localConfig.development?.fallback?.url === 'string' diff --git a/src/registry/routes/component-preview.ts b/src/registry/routes/component-preview.ts index 431dbc79..f18c842a 100644 --- a/src/registry/routes/component-preview.ts +++ b/src/registry/routes/component-preview.ts @@ -33,7 +33,7 @@ function componentPreview( previewView({ component, fallbackClient: res.conf.fallbackClient - ? res.conf.fallbackRegistryUrl + ? `${res.conf.fallbackRegistryUrl.replace(/\/$/, '')}/oc-client/client.dev.js` : undefined, href: res.conf.baseUrl, liveReload, diff --git a/test/unit/cli-domain-get-mocked-plugins.js b/test/unit/cli-domain-get-mocked-plugins.js index b6cee50d..2a3b9f1b 100644 --- a/test/unit/cli-domain-get-mocked-plugins.js +++ b/test/unit/cli-domain-get-mocked-plugins.js @@ -51,28 +51,32 @@ describe('cli : domain : get-mocked-plugins', () => { describe('when setting up mocked plugins', () => { describe('when componentsDir parameter is undefined', () => { - const joinStub = sinon.stub(); + let getOcConfigMock; beforeEach(() => { - initialise({ pathJoin: joinStub }); + getOcConfigMock = sinon.stub().returns({ registries: [], mocks: { plugins: {} } }); + initialise({ getOcConfig: getOcConfigMock }); getMockedPlugins(logMock, undefined); }); it('should use . as default', () => { - expect(joinStub.args[0][0]).to.equal('.'); + expect(getOcConfigMock.called).to.be.true; + expect(getOcConfigMock.args[0][0]).to.equal('.'); }); }); describe('when componentsDir parameter is omitted', () => { - const joinStub = sinon.stub(); + let getOcConfigMock; beforeEach(() => { - initialise({ pathJoin: joinStub }); + getOcConfigMock = sinon.stub().returns({ registries: [], mocks: { plugins: {} } }); + initialise({ getOcConfig: getOcConfigMock }); getMockedPlugins(logMock); }); it('should use . as default', () => { - expect(joinStub.args[0][0]).to.equal('.'); + expect(getOcConfigMock.called).to.be.true; + expect(getOcConfigMock.args[0][0]).to.equal('.'); }); }); @@ -90,65 +94,26 @@ describe('cli : domain : get-mocked-plugins', () => { const getOcConfigMock = sinon.stub().returns(ocJsonComponent); beforeEach(() => { - initialise({fs: { - existsSync: sinon.stub().returns(true), - }, getOcConfig: getOcConfigMock}); + initialise({ getOcConfig: getOcConfigMock }); result = getMockedPlugins(logMock, '/root/components/'); }); - it('should use components folder oc.json as default', () => { + it('should return plugins from the provided components folder config', () => { expect(getOcConfigMock.calledOnce).to.be.true; - expect(getOcConfigMock.args[0][0]).to.equal('/root/components/oc.json'); + expect(getOcConfigMock.args[0][0]).to.equal('/root/components/'); expect(result.length).to.equal(2); }); }); - describe('when oc.json is in root folder', () => { - let result; - const ocJsonComponent = { - registries: [], - development: { - plugins: { - static: { foo: 1, bar: 2 } - } - } - }; - const ocJsonRoot = { - registries: [], - development: { - plugins: { - static: { foo: 1, bar: 2, baz: 3 } - } - } - }; - - const getOcConfigMock = sinon.stub(); - const existsMock = sinon.stub(); - - getOcConfigMock.withArgs('/root/components/oc.json').returns(ocJsonComponent); - getOcConfigMock.withArgs('/root/oc.json').returns(ocJsonRoot); - - existsMock.withArgs('/root/components/oc.json').returns(false); - existsMock.withArgs('/root/oc.json').returns(true); - - beforeEach(() => { - initialise({fs:{ - existsSync: existsMock, - }, getOcConfig: getOcConfigMock}); - result = getMockedPlugins(logMock, '/root/components/'); - }); - - it('should use root oc.json', () => { - expect(result.length).to.equal(3); - }); - }); describe('when oc.json is missing', () => { let result; beforeEach(() => { - initialise({fs:{ - existsSync: sinon.stub().returns(false) - }}); + const getOcConfigMock = sinon.stub().returns({ + registries: [], + development: { plugins: {} } + }); + initialise({ getOcConfig: getOcConfigMock }); result = getMockedPlugins(logMock, '/root/components/'); }); @@ -161,16 +126,13 @@ describe('cli : domain : get-mocked-plugins', () => { let result; const ocJson = { registries: [], - mocks: { + development: { plugins: {} } }; beforeEach(() => { - initialise({fs:{ - existsSync: sinon.stub().returns(true), - readJsonSync: sinon.stub().returns(ocJson) - }}); + initialise({ getOcConfig: sinon.stub().returns(ocJson) }); result = getMockedPlugins(logMock, '/root/components/'); }); diff --git a/test/unit/cli-domain-ocConfig.js b/test/unit/cli-domain-ocConfig.js index a49d1257..f3b2ad37 100644 --- a/test/unit/cli-domain-ocConfig.js +++ b/test/unit/cli-domain-ocConfig.js @@ -5,7 +5,9 @@ const sinon = require('sinon'); const initialise = () => { const fsMock = { readFileSync: sinon.stub(), - writeFileSync: sinon.stub() + writeFileSync: sinon.stub(), + realpathSync: sinon.stub().returns('/root/'), + existsSync: sinon.stub().returns(true) }; const settingsMock = { @@ -14,10 +16,15 @@ const initialise = () => { } }; + const pathMock = { + join: (...args) => args.join('/') + }; + const ocConfig = injectr( '../../dist/cli/domain/ocConfig.js', { 'node:fs': fsMock, + 'node:path': pathMock, '../../resources/settings': settingsMock }, { __dirname: '' } @@ -67,14 +74,23 @@ describe('cli : domain : ocConfig', () => { }); }); + it('should include sourcePath in result', () => { + const result = data.ocConfig.getOcConfig(); + expect(result.sourcePath).to.equal('./oc.json'); + }); + it('should use default config file path when no path provided', () => { data.ocConfig.getOcConfig(); expect(data.fs.readFileSync.calledWith('./oc.json', 'utf8')).to.be.true; }); it('should use provided path when specified', () => { + // Reset existsSync to return false by default, then allow the specific path + data.fs.existsSync.reset(); + data.fs.existsSync.returns(false); + data.fs.existsSync.withArgs('./custom-config.json/oc.json').returns(true); data.ocConfig.getOcConfig('./custom-config.json'); - expect(data.fs.readFileSync.calledWith('./custom-config.json', 'utf8')).to.be.true; + expect(data.fs.readFileSync.calledWith('./custom-config.json/oc.json', 'utf8')).to.be.true; }); }); @@ -196,6 +212,60 @@ describe('cli : domain : ocConfig', () => { }); }); }); + + describe('when oc.json is in both root and component folder', () => { + let data; + beforeEach(() => { + data = initialise(); + const mockConfig = { + registries: ['http://registry1.com'], + development: { + plugins: { + static: { testPlugin: 'testValue' } + } + } + }; + data.fs.readFileSync.returns(JSON.stringify(mockConfig)); + // Reset existsSync to return false by default + data.fs.existsSync.reset(); + data.fs.existsSync.returns(false); + // Set up the path resolution: component folder has oc.json + data.fs.existsSync.withArgs('/root/components/oc.json').returns(true); + }); + + it('should use components folder oc.json as default', () => { + const result = data.ocConfig.getOcConfig('/root/components/'); + expect(data.fs.readFileSync.calledWith('/root/components/oc.json', 'utf8')).to.be.true; + }); + }); + + describe('when oc.json is in root folder but not component folder', () => { + let data; + beforeEach(() => { + data = initialise(); + const mockConfig = { + registries: ['http://registry1.com'], + development: { + plugins: { + static: { testPlugin: 'testValue' } + } + } + }; + data.fs.readFileSync.returns(JSON.stringify(mockConfig)); + // Reset existsSync to return false by default + data.fs.existsSync.reset(); + data.fs.existsSync.returns(false); + // Set up the path resolution: component folder doesn't have oc.json, but root does + data.fs.existsSync.withArgs('/root/components/oc.json').returns(false); + data.fs.existsSync.withArgs('/root/oc.json').returns(true); + }); + + it('should use root oc.json', () => { + const result = data.ocConfig.getOcConfig('/root/components/'); + expect(data.fs.readFileSync.calledWith('/root/oc.json', 'utf8')).to.be.true; + expect(result.sourcePath).to.equal('/root/oc.json'); + }); + }); }); describe('setOcConfig', () => {