diff --git a/tooling/build-env/src/internal/utils/logging.spec.ts b/tooling/build-env/src/internal/utils/logging.spec.ts index 233d226b..3067871e 100644 --- a/tooling/build-env/src/internal/utils/logging.spec.ts +++ b/tooling/build-env/src/internal/utils/logging.spec.ts @@ -1,27 +1,18 @@ -import { beforeEach, describe, expect, it, vi } from 'vitest'; -import { error, info } from './logging'; +import { describe, expect, it } from 'vitest'; import { bold, gray, red } from 'ansis'; +import { formatError, formatInfo } from './logging'; -describe('info', () => { - let consoleInfoSpy; - let consoleErrorSpy; - beforeEach(() => { - consoleInfoSpy = vi.spyOn(console, 'info').mockImplementation(vi.fn()); - consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(vi.fn()); - }); - - it('should log info', () => { - info('message', 'token'); - expect(consoleInfoSpy).toHaveBeenCalledTimes(1); - expect(consoleInfoSpy).toHaveBeenCalledWith( +describe('formatInfo', () => { + it('should format info message correctly', () => { + expect(formatInfo('message', 'token')).toBe( `${gray('>')} ${gray(bold('token'))} ${'message'}` ); }); +}); - it('should log error', () => { - error('message', 'token'); - expect(consoleErrorSpy).toHaveBeenCalledTimes(1); - expect(consoleErrorSpy).toHaveBeenCalledWith( +describe('formatError', () => { + it('should format error message correctly', () => { + expect(formatError('message', 'token')).toBe( `${red('>')} ${red(bold('token'))} ${'message'}` ); }); diff --git a/tooling/build-env/src/internal/utils/logging.ts b/tooling/build-env/src/internal/utils/logging.ts index 2cb86b9d..07f48a36 100644 --- a/tooling/build-env/src/internal/utils/logging.ts +++ b/tooling/build-env/src/internal/utils/logging.ts @@ -1,8 +1,8 @@ import { bold, gray, red } from 'ansis'; -export function info(message: string, token: string) { - console.info(`${gray('>')} ${gray(bold(token))} ${message}`); +export function formatInfo(message: string, token: string) { + return `${gray('>')} ${gray(bold(token))} ${message}`; } -export function error(message: string, token: string) { - console.error(`${red('>')} ${red(bold(token))} ${message}`); +export function formatError(message: string, token: string) { + return `${red('>')} ${red(bold(token))} ${message}`; } diff --git a/tooling/build-env/src/internal/utils/npm.ts b/tooling/build-env/src/internal/utils/npm.ts index b7e0f340..4558cf01 100644 --- a/tooling/build-env/src/internal/utils/npm.ts +++ b/tooling/build-env/src/internal/utils/npm.ts @@ -1,18 +1,13 @@ import { execFileSync } from 'node:child_process'; import { join } from 'node:path'; import { ensureDirectoryExists } from './file-system'; -import { error, info } from './logging'; -import * as process from 'process'; +import { formatError, formatInfo } from './logging'; +import { logger } from '@nx/devkit'; -export function logInfo(msg: string) { - info(msg, 'Npm Env: '); -} - -export function logError(msg: string) { - error(msg, 'Npm Env: '); -} +export const NPM_ENV_TOKEN = 'Npm Env: '; /* +@TODO: This is here to be able to better mock chdir. We should definitely find a better solution that mocks it directly and avoids this wrapper completely. */ @@ -25,7 +20,12 @@ export async function setupNpmWorkspace( verbose?: boolean ): Promise { if (verbose) { - logInfo(`Execute: npm init in directory ${environmentRoot}`); + logger.info( + formatInfo( + `Execute: npm init in directory ${environmentRoot}`, + NPM_ENV_TOKEN + ) + ); } const cwd = process.cwd(); await ensureDirectoryExists(environmentRoot); @@ -33,7 +33,12 @@ export async function setupNpmWorkspace( try { execFileSync('npm', ['init', '--force']).toString(); } catch (error) { - logError(`Error creating NPM workspace: ${(error as Error).message}`); + logger.error( + formatError( + `Error creating NPM workspace: ${(error as Error).message}`, + NPM_ENV_TOKEN + ) + ); } finally { chdir(cwd); } diff --git a/tooling/build-env/src/internal/utils/npm.unit-test.ts b/tooling/build-env/src/internal/utils/npm.unit-test.ts index af5b5c0f..86572c48 100644 --- a/tooling/build-env/src/internal/utils/npm.unit-test.ts +++ b/tooling/build-env/src/internal/utils/npm.unit-test.ts @@ -1,66 +1,36 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; -import { bold, gray, red } from 'ansis'; +import { bold, red } from 'ansis'; import { MEMFS_VOLUME } from '@org/test-utils'; -import { logError, logInfo, setupNpmWorkspace } from './npm'; - -describe('logInfo', () => { - let consoleInfoSpy; - beforeEach(() => { - consoleInfoSpy = vi.spyOn(console, 'info').mockImplementation(vi.fn()); - }); - - it('should log info', () => { - logInfo('message'); - expect(consoleInfoSpy).toHaveBeenCalledTimes(1); - expect(consoleInfoSpy).toHaveBeenCalledWith( - `${gray('>')} ${gray(bold('Npm Env: '))} ${'message'}` - ); - }); -}); - -describe('logError', () => { - let consoleErrorSpy; - beforeEach(() => { - consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(vi.fn()); - }); - - it('should log error', () => { - logError('message'); - expect(consoleErrorSpy).toHaveBeenCalledTimes(1); - expect(consoleErrorSpy).toHaveBeenCalledWith( - `${red('>')} ${red(bold('Npm Env: '))} ${'message'}` - ); - }); -}); +import { setupNpmWorkspace } from './npm'; describe.skip('setupNpmWorkspace', () => { let cwdSpy; let chdirSpy; - let logInfoSpy; + let consoleInfoSpy; beforeEach(() => { cwdSpy = vi.spyOn(process, 'cwd').mockReturnValue(MEMFS_VOLUME); chdirSpy = vi.spyOn(process, 'chdir').mockImplementation(vi.fn()); - logInfoSpy = vi.mocked(logInfo).mockImplementation(vi.fn()); + consoleInfoSpy = vi.spyOn(console, 'info').mockImplementation(vi.fn()); }); afterEach(() => { cwdSpy.mockRestore(); chdirSpy.mockRestore(); - logInfoSpy.mockRestore(); + consoleInfoSpy.mockRestore(); }); it('should create npm workspace in given folder', () => { setupNpmWorkspace('tmp'); expect(chdirSpy).toHaveBeenCalledTimes(1); expect(chdirSpy).toHaveBeenCalledWith('tmp'); - expect(logInfoSpy).not.toHaveBeenCalled(); + expect(consoleInfoSpy).not.toHaveBeenCalled(); }); it('should call infoLog if verbose is given', () => { setupNpmWorkspace('tmp', true); - expect(logInfoSpy).toHaveBeenCalledTimes(1); - expect(logInfoSpy).toHaveBeenCalledWith( + expect(consoleInfoSpy).toHaveBeenCalledTimes(1); + expect(consoleInfoSpy).toHaveBeenCalledWith( `${red('>')} ${red(bold('Npm Env: '))} Execute: npm init in directory tmp` ); }); diff --git a/tooling/build-env/src/internal/verdaccio/verdaccio-npm-env.ts b/tooling/build-env/src/internal/verdaccio/verdaccio-npm-env.ts index 18aecb1c..aedc3dad 100644 --- a/tooling/build-env/src/internal/verdaccio/verdaccio-npm-env.ts +++ b/tooling/build-env/src/internal/verdaccio/verdaccio-npm-env.ts @@ -7,23 +7,13 @@ import { } from './verdaccio-registry'; import { writeFile } from 'node:fs/promises'; import { setupNpmWorkspace } from '../utils/npm'; -import { error, info } from '../utils/logging'; +import { formatInfo } from '../utils/logging'; import { objectToCliArgs } from '../utils/terminal'; import { execSync } from 'node:child_process'; import { VERDACCIO_REGISTRY_JSON } from './constants'; +import { logger } from '@nx/devkit'; -function logInfo(msg: string) { - info(msg, 'Verdaccio Env: '); -} - -function errorLog(msg: string) { - error(msg, 'Verdaccio Env: '); -} - -export const verdaccioEnvLogger = { - info: logInfo, - error: errorLog, -}; +export const VERDACCIO_ENV_TOKEN = 'Verdaccio Env: '; export type Environment = { root: string; @@ -63,15 +53,23 @@ export async function bootstrapEnvironment({ root: environmentRoot, }; - logInfo( - `Save active verdaccio registry data to file: ${activeRegistry.root}` + logger.info( + formatInfo( + `Save active verdaccio registry data to file: ${activeRegistry.root}`, + VERDACCIO_ENV_TOKEN + ) ); await writeFile( join(activeRegistry.root, VERDACCIO_REGISTRY_JSON), JSON.stringify(activeRegistry.registry, null, 2) ); - logInfo(`Environment ready under: ${activeRegistry.root}`); + logger.info( + formatInfo( + `Environment ready under: ${activeRegistry.root}`, + VERDACCIO_ENV_TOKEN + ) + ); return activeRegistry; } @@ -87,7 +85,9 @@ export function configureRegistry( userconfig, }).join(' ')}`; if (verbose) { - logInfo(`Set registry:\n${setRegistry}`); + logger.info( + formatInfo(`Set registry:\n${setRegistry}`, VERDACCIO_ENV_TOKEN) + ); } execSync(setRegistry); @@ -103,7 +103,9 @@ export function configureRegistry( { userconfig } ).join(' ')}`; if (verbose) { - logInfo(`Set authToken:\n${setAuthToken}`); + logger.info( + formatInfo(`Set authToken:\n${setAuthToken}`, VERDACCIO_ENV_TOKEN) + ); } execSync(setAuthToken); } @@ -117,7 +119,9 @@ export function unconfigureRegistry( { userconfig } ).join(' ')}`; if (verbose) { - logInfo(`Delete authToken:\n${setAuthToken}`); + logger.info( + formatInfo(`Delete authToken:\n${setAuthToken}`, VERDACCIO_ENV_TOKEN) + ); } execSync(setAuthToken); @@ -125,7 +129,9 @@ export function unconfigureRegistry( userconfig, }).join(' ')}`; if (verbose) { - logInfo(`Delete registry:\n${setRegistry}`); + logger.info( + formatInfo(`Delete registry:\n${setRegistry}`, VERDACCIO_ENV_TOKEN) + ); } execSync(setRegistry); } diff --git a/tooling/build-env/src/internal/verdaccio/verdaccio-npm-env.unit-test.ts b/tooling/build-env/src/internal/verdaccio/verdaccio-npm-env.unit-test.ts index b23aa19e..981e5e6b 100644 --- a/tooling/build-env/src/internal/verdaccio/verdaccio-npm-env.unit-test.ts +++ b/tooling/build-env/src/internal/verdaccio/verdaccio-npm-env.unit-test.ts @@ -1,43 +1,36 @@ -import { beforeEach, describe, expect, it, vi } from 'vitest'; -import { configureRegistry, verdaccioEnvLogger } from './verdaccio-npm-env'; -import { bold, gray, red } from 'ansis'; +import { describe, expect, it, vi } from 'vitest'; +import { + configureRegistry, + ConfigureRegistryOptions, + VERDACCIO_ENV_TOKEN, +} from './verdaccio-npm-env'; import { execSync } from 'node:child_process'; -import { objectToCliArgs } from '../utils/terminal'; -import type { VerdaccioProcessResult } from './verdaccio-registry'; +import { logger } from '@nx/devkit'; +import { formatInfo } from '../utils/logging'; -describe('verdaccioEnvLogger.info', () => { - let consoleInfoSpy; - beforeEach(() => { - consoleInfoSpy = vi.spyOn(console, 'info').mockImplementation(vi.fn()); - }); - - it('should log info', () => { - verdaccioEnvLogger.info('message'); - expect(consoleInfoSpy).toHaveBeenCalledTimes(1); - expect(consoleInfoSpy).toHaveBeenCalledWith( - `${gray('>')} ${gray(bold('Verdaccio Env: '))} ${'message'}` - ); - }); +vi.mock('child_process', async () => { + const actual = await vi.importActual( + 'child_process' + ); + return { + ...actual, + execSync: vi.fn(), + }; }); -describe('logError', () => { - let consoleErrorSpy; - beforeEach(() => { - consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(vi.fn()); - }); - - it('should log error', () => { - verdaccioEnvLogger.error('message'); - expect(consoleErrorSpy).toHaveBeenCalledTimes(1); - expect(consoleErrorSpy).toHaveBeenCalledWith( - `${red('>')} ${red(bold('Verdaccio Env: '))} ${'message'}` - ); - }); +vi.mock('@nx/devkit', async () => { + const actual = await vi.importActual('@nx/devkit'); + return { + ...actual, + logger: { + info: vi.fn(), + }, + }; }); describe('configureRegistry', () => { it('should set the npm registry and authToken', () => { - const processResult: VerdaccioProcessResult & { userconfig?: string } = { + const processResult: ConfigureRegistryOptions = { port: 4873, host: 'localhost', protocol: 'http', @@ -45,37 +38,41 @@ describe('configureRegistry', () => { userconfig: 'test-config', }; - configureRegistry(processResult, false); - - expect(objectToCliArgs).toHaveBeenCalledWith({ userconfig: 'test-config' }); + configureRegistry(processResult); + expect(execSync).toHaveBeenCalledTimes(2); expect(execSync).toHaveBeenCalledWith( - 'npm config set registry="http://localhost:4873" --userconfig=test-config' + 'npm config set registry="http://localhost:4873" --userconfig="test-config"' ); expect(execSync).toHaveBeenCalledWith( - 'npm config set //localhost:4873/:_authToken "secretVerdaccioToken" --userconfig=test-config' + 'npm config set //localhost:4873/:_authToken "secretVerdaccioToken" --userconfig="test-config"' ); }); it('should log registry and authToken commands if verbose is true', () => { - const processResult = { + const processResult: ConfigureRegistryOptions = { port: 4873, host: 'localhost', + protocol: 'http', url: 'http://localhost:4873', userconfig: 'test-config', }; configureRegistry(processResult, true); - expect(verdaccioEnvLogger.info).toHaveBeenCalledWith( - 'Set registry:\nnpm config set registry="http://localhost:4873" --userconfig=test-config' + expect(execSync).toHaveBeenCalledTimes(2); + expect(logger.info).toHaveBeenCalledWith( + formatInfo( + 'Set registry:\nnpm config set registry="http://localhost:4873" --userconfig="test-config"', + VERDACCIO_ENV_TOKEN + ) ); - - expect(verdaccioEnvLogger.info).toHaveBeenCalledWith( - 'Set authToken:\nnpm config set //localhost:4873/:_authToken "secretVerdaccioToken" --userconfig=test-config' + expect(logger.info).toHaveBeenCalledWith( + formatInfo( + 'Set authToken:\nnpm config set //localhost:4873/:_authToken "secretVerdaccioToken" --userconfig="test-config"', + VERDACCIO_ENV_TOKEN + ) ); - - expect(execSync).toHaveBeenCalledTimes(2); }); }); diff --git a/tooling/build-env/src/internal/verdaccio/verdaccio-registry.ts b/tooling/build-env/src/internal/verdaccio/verdaccio-registry.ts index b37fdabf..0f781256 100644 --- a/tooling/build-env/src/internal/verdaccio/verdaccio-registry.ts +++ b/tooling/build-env/src/internal/verdaccio/verdaccio-registry.ts @@ -1,6 +1,6 @@ import { gray, bold, red } from 'ansis'; import { join } from 'node:path'; -import { error, info } from '../utils/logging'; +import { formatError, formatInfo } from '../utils/logging'; import { logger } from '@nx/devkit'; import { objectToCliArgs } from '../utils/terminal'; import { executeProcess } from '../utils/execute-process'; @@ -8,11 +8,11 @@ import { uniquePort } from '../utils/unique-port'; import { getEnvironmentsRoot } from '../../shared/setup'; export function logInfo(msg: string) { - info(msg, 'Verdaccio: '); + formatInfo(msg, 'Verdaccio: '); } export function logError(msg: string) { - error(msg, 'Verdaccio: '); + formatError(msg, 'Verdaccio: '); } export type VerdaccioProcessResult = {