diff --git a/jest.preset.js b/jest.preset.js index 28490c0c213ff3..28be337c9faf31 100644 --- a/jest.preset.js +++ b/jest.preset.js @@ -12,4 +12,5 @@ module.exports = { coverageReporters: ['html'], maxWorkers: 1, testEnvironment: 'node', + setupFiles: ['../../scripts/unit-test-setup.js'], }; diff --git a/packages/cypress/src/plugins/plugin.ts b/packages/cypress/src/plugins/plugin.ts index 5313637d35abcd..7634b7f7695f03 100644 --- a/packages/cypress/src/plugins/plugin.ts +++ b/packages/cypress/src/plugins/plugin.ts @@ -210,6 +210,7 @@ async function buildCypressTargets( ? cypressConfig.e2e.excludeSpecPattern.map((p) => join(projectRoot, p)) : [join(projectRoot, cypressConfig.e2e.excludeSpecPattern)]; const specFiles = await globWithWorkspaceContext( + context.workspaceRoot, specPatterns, excludeSpecPatterns ); diff --git a/packages/eslint-plugin/src/migrations/update-17-2-6-rename-workspace-rules/rename-workspace-rules.spec.ts b/packages/eslint-plugin/src/migrations/update-17-2-6-rename-workspace-rules/rename-workspace-rules.spec.ts index c00e45fe28f70e..57d2ba436d87b9 100644 --- a/packages/eslint-plugin/src/migrations/update-17-2-6-rename-workspace-rules/rename-workspace-rules.spec.ts +++ b/packages/eslint-plugin/src/migrations/update-17-2-6-rename-workspace-rules/rename-workspace-rules.spec.ts @@ -3,6 +3,8 @@ import { createTreeWithEmptyWorkspace } from 'nx/src/devkit-testing-exports'; import { WORKSPACE_PLUGIN_DIR } from '../../constants'; import update from './rename-workspace-rules'; +import 'nx/src/internal-testing-utils/mock-project-graph'; + const rule1Name = 'test-rule'; const rule2Name = 'my-rule'; diff --git a/packages/eslint/src/generators/init/init.spec.ts b/packages/eslint/src/generators/init/init.spec.ts index bcf161b287aefb..140bb2aeb7b309 100644 --- a/packages/eslint/src/generators/init/init.spec.ts +++ b/packages/eslint/src/generators/init/init.spec.ts @@ -3,6 +3,7 @@ import 'nx/src/internal-testing-utils/mock-project-graph'; import { NxJsonConfiguration, readJson, Tree, updateJson } from '@nx/devkit'; import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; import { LinterInitOptions, lintInitGenerator } from './init'; +import { setWorkspaceRoot } from 'nx/src/utils/workspace-root'; describe('@nx/eslint:init', () => { let tree: Tree; @@ -10,6 +11,7 @@ describe('@nx/eslint:init', () => { beforeEach(() => { tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); + setWorkspaceRoot(tree.root); options = { addPlugin: true, }; diff --git a/packages/gradle/src/plugin/nodes.ts b/packages/gradle/src/plugin/nodes.ts index 69ffc11cf9eb77..953eabcf8cd61d 100644 --- a/packages/gradle/src/plugin/nodes.ts +++ b/packages/gradle/src/plugin/nodes.ts @@ -72,7 +72,7 @@ export const createNodesV2: CreateNodesV2 = [ ); const targetsCache = readTargetsCache(cachePath); - populateGradleReport(context.workspaceRoot); + await populateGradleReport(context.workspaceRoot); const gradleReport = getCurrentGradleReport(); try { @@ -131,7 +131,7 @@ export const createNodes: CreateNodes = [ logger.warn( '`createNodes` is deprecated. Update your plugin to utilize createNodesV2 instead. In Nx 20, this will error.' ); - populateGradleReport(context.workspaceRoot); + await populateGradleReport(context.workspaceRoot); const gradleReport = getCurrentGradleReport(); const internalCreateNodes = makeCreateNodes(gradleReport, {}); return await internalCreateNodes(configFile, options, context); diff --git a/packages/gradle/src/utils/get-gradle-report.ts b/packages/gradle/src/utils/get-gradle-report.ts index 38c00fb9d8487a..76919c29e264c2 100644 --- a/packages/gradle/src/utils/get-gradle-report.ts +++ b/packages/gradle/src/utils/get-gradle-report.ts @@ -36,8 +36,10 @@ export function getCurrentGradleReport() { return gradleReportCache; } -export function populateGradleReport(workspaceRoot: string): void { - const gradleConfigHash = hashWithWorkspaceContext(workspaceRoot, [ +export async function populateGradleReport( + workspaceRoot: string +): Promise { + const gradleConfigHash = await hashWithWorkspaceContext(workspaceRoot, [ gradleConfigGlob, ]); if (gradleReportCache && gradleConfigHash === gradleCurrentConfigHash) { diff --git a/packages/jest/src/plugins/plugin.spec.ts b/packages/jest/src/plugins/plugin.spec.ts index f2e4a177a1cc3a..deb05e3817085c 100644 --- a/packages/jest/src/plugins/plugin.spec.ts +++ b/packages/jest/src/plugins/plugin.spec.ts @@ -3,6 +3,7 @@ import { join } from 'path'; import { createNodes } from './plugin'; import { TempFs } from 'nx/src/internal-testing-utils/temp-fs'; +import { setWorkspaceRoot } from 'nx/src/utils/workspace-root'; describe('@nx/jest/plugin', () => { let createNodesFunction = createNodes[1]; @@ -25,6 +26,8 @@ describe('@nx/jest/plugin', () => { configFiles: [], }; + setWorkspaceRoot(tempFs.tempDir); + await tempFs.createFiles({ 'proj/jest.config.js': `module.exports = {}`, 'proj/src/unit.spec.ts': '', diff --git a/packages/nx/src/adapter/ngcli-adapter.spec.ts b/packages/nx/src/adapter/ngcli-adapter.spec.ts index cb055967a3ead7..2e1946031d09f7 100644 --- a/packages/nx/src/adapter/ngcli-adapter.spec.ts +++ b/packages/nx/src/adapter/ngcli-adapter.spec.ts @@ -5,6 +5,14 @@ import { import { createTreeWithEmptyWorkspace } from '../generators/testing-utils/create-tree-with-empty-workspace'; import { addProjectConfiguration } from '../generators/utils/project-configuration'; +jest.mock('../project-graph/project-graph', () => ({ + ...jest.requireActual('../project-graph/project-graph'), + createProjectGraphAsync: () => ({ + nodes: {}, + externalNodes: {}, + }), +})); + describe('ngcli-adapter', () => { it('arrayBufferToString should support large buffers', () => { const largeString = 'a'.repeat(1000000); diff --git a/packages/nx/src/daemon/client/client.ts b/packages/nx/src/daemon/client/client.ts index 0fb3fa08804af3..29f6524592002f 100644 --- a/packages/nx/src/daemon/client/client.ts +++ b/packages/nx/src/daemon/client/client.ts @@ -4,7 +4,7 @@ import { readFileSync, statSync } from 'fs'; import { FileHandle, open } from 'fs/promises'; import { ensureDirSync, ensureFileSync } from 'fs-extra'; import { connect } from 'net'; -import { join } from 'path'; +import { extname, join } from 'path'; import { performance } from 'perf_hooks'; import { output } from '../../utils/output'; import { getFullOsSocketPath, killSocketOrPath } from '../socket-utils'; @@ -49,9 +49,6 @@ import { NxWorkspaceFiles } from '../../native'; const DAEMON_ENV_SETTINGS = { NX_PROJECT_GLOB_CACHE: 'false', NX_CACHE_PROJECTS_CONFIG: 'false', - - // Used to identify that the code is running in the daemon process. - NX_ON_DAEMON_PROCESS: 'true', }; export type UnregisterCallback = () => void; @@ -283,14 +280,9 @@ export class DaemonClient { return this.sendToDaemonViaQueue(message); } - getWorkspaceContextFileData( - globs: string[], - exclude?: string[] - ): Promise { + getWorkspaceContextFileData(): Promise { const message: HandleContextFileDataMessage = { type: GET_CONTEXT_FILE_DATA, - globs, - exclude, }; return this.sendToDaemonViaQueue(message); } @@ -480,14 +472,17 @@ export class DaemonClient { const backgroundProcess = spawn( process.execPath, - [join(__dirname, '../server/start.js')], + [join(__dirname, `../server/start.js`)], { cwd: workspaceRoot, stdio: ['ignore', this._out.fd, this._err.fd], detached: true, windowsHide: true, shell: false, - env: { ...process.env, ...DAEMON_ENV_SETTINGS }, + env: { + ...process.env, + ...DAEMON_ENV_SETTINGS, + }, } ); backgroundProcess.unref(); diff --git a/packages/nx/src/daemon/message-types/get-context-file-data.ts b/packages/nx/src/daemon/message-types/get-context-file-data.ts index c804b93eaf340a..935f1cbb876091 100644 --- a/packages/nx/src/daemon/message-types/get-context-file-data.ts +++ b/packages/nx/src/daemon/message-types/get-context-file-data.ts @@ -2,8 +2,6 @@ export const GET_CONTEXT_FILE_DATA = 'GET_CONTEXT_FILE_DATA' as const; export type HandleContextFileDataMessage = { type: typeof GET_CONTEXT_FILE_DATA; - globs: string[]; - exclude?: string[]; }; export function isHandleContextFileDataMessage( diff --git a/packages/nx/src/daemon/server/handle-context-file-data.ts b/packages/nx/src/daemon/server/handle-context-file-data.ts index 24d9243d45c2a5..52468d72033d86 100644 --- a/packages/nx/src/daemon/server/handle-context-file-data.ts +++ b/packages/nx/src/daemon/server/handle-context-file-data.ts @@ -3,7 +3,7 @@ import { workspaceRoot } from '../../utils/workspace-root'; import { HandlerResult } from './server'; export async function handleContextFileData(): Promise { - const files = getAllFileDataInContext(workspaceRoot); + const files = await getAllFileDataInContext(workspaceRoot); return { response: JSON.stringify(files), description: 'handleContextFileData', diff --git a/packages/nx/src/daemon/server/handle-get-files-in-directory.ts b/packages/nx/src/daemon/server/handle-get-files-in-directory.ts index aa781ab77980b8..adcfe93f82c4e5 100644 --- a/packages/nx/src/daemon/server/handle-get-files-in-directory.ts +++ b/packages/nx/src/daemon/server/handle-get-files-in-directory.ts @@ -5,7 +5,7 @@ import { HandlerResult } from './server'; export async function handleGetFilesInDirectory( dir: string ): Promise { - const files = getFilesInDirectoryUsingContext(workspaceRoot, dir); + const files = await getFilesInDirectoryUsingContext(workspaceRoot, dir); return { response: JSON.stringify(files), description: 'handleNxWorkspaceFiles', diff --git a/packages/nx/src/daemon/server/handle-request-file-data.ts b/packages/nx/src/daemon/server/handle-request-file-data.ts deleted file mode 100644 index 2bfd24e7e16967..00000000000000 --- a/packages/nx/src/daemon/server/handle-request-file-data.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { getAllFileDataInContext } from '../../utils/workspace-context'; -import { workspaceRoot } from '../../utils/workspace-root'; - -export async function handleRequestFileData() { - const response = JSON.stringify(getAllFileDataInContext(workspaceRoot)); - return { - response, - description: 'handleRequestFileData', - }; -} diff --git a/packages/nx/src/daemon/server/server.ts b/packages/nx/src/daemon/server/server.ts index 6310c497c372d1..dcd51bc464aa24 100644 --- a/packages/nx/src/daemon/server/server.ts +++ b/packages/nx/src/daemon/server/server.ts @@ -26,7 +26,6 @@ import { handleRecordOutputsHash, } from './handle-outputs-tracking'; import { handleProcessInBackground } from './handle-process-in-background'; -import { handleRequestFileData } from './handle-request-file-data'; import { handleRequestProjectGraph } from './handle-request-project-graph'; import { handleRequestShutdown } from './handle-request-shutdown'; import { serverLogger } from './logger'; @@ -132,11 +131,12 @@ async function handleMessage(socket, data: string) { ); } - if (daemonIsOutdated()) { + const outdated = daemonIsOutdated(); + if (outdated) { await respondWithErrorAndExit( socket, - `Lock files changed`, - new Error('LOCK-FILES-CHANGED') + `Daemon outdated`, + new Error(outdated) ); } @@ -164,10 +164,6 @@ async function handleMessage(socket, data: string) { ); } else if (payload.type === 'HASH_TASKS') { await handleResult(socket, 'HASH_TASKS', () => handleHashTasks(payload)); - } else if (payload.type === 'REQUEST_FILE_DATA') { - await handleResult(socket, 'REQUEST_FILE_DATA', () => - handleRequestFileData() - ); } else if (payload.type === 'PROCESS_IN_BACKGROUND') { await handleResult(socket, 'PROCESS_IN_BACKGROUND', () => handleProcessInBackground(payload) @@ -274,8 +270,13 @@ function registerProcessTerminationListeners() { let existingLockHash: string | undefined; -function daemonIsOutdated(): boolean { - return nxVersionChanged() || lockFileHashChanged(); +function daemonIsOutdated(): string | null { + if (nxVersionChanged()) { + return 'NX_VERSION_CHANGED'; + } else if (lockFileHashChanged()) { + return 'LOCK_FILES_CHANGED'; + } + return null; } function nxVersionChanged(): boolean { @@ -332,10 +333,11 @@ const handleWorkspaceChanges: FileWatcherCallback = async ( try { resetInactivityTimeout(handleInactivityTimeout); - if (daemonIsOutdated()) { + const outdatedReason = daemonIsOutdated(); + if (outdatedReason) { await handleServerProcessTermination({ server, - reason: 'Lock file changed', + reason: outdatedReason, }); return; } diff --git a/packages/nx/src/plugins/js/project-graph/build-dependencies/explicit-package-json-dependencies.spec.ts b/packages/nx/src/plugins/js/project-graph/build-dependencies/explicit-package-json-dependencies.spec.ts index 3849124542e8e9..529caa2b39ce51 100644 --- a/packages/nx/src/plugins/js/project-graph/build-dependencies/explicit-package-json-dependencies.spec.ts +++ b/packages/nx/src/plugins/js/project-graph/build-dependencies/explicit-package-json-dependencies.spec.ts @@ -89,7 +89,7 @@ describe('explicit package json dependencies', () => { const fileMap = createFileMap( projectsConfigurations as any, - getAllFileDataInContext(tempFs.tempDir) + await getAllFileDataInContext(tempFs.tempDir) ).fileMap; const builder = new ProjectGraphBuilder(undefined, fileMap.projectFileMap); diff --git a/packages/nx/src/project-graph/plugins/isolation/plugin-pool.ts b/packages/nx/src/project-graph/plugins/isolation/plugin-pool.ts index 64a86e394bbdae..ec404a4a6321d1 100644 --- a/packages/nx/src/project-graph/plugins/isolation/plugin-pool.ts +++ b/packages/nx/src/project-graph/plugins/isolation/plugin-pool.ts @@ -39,8 +39,6 @@ export function loadRemoteNxPlugin( : {}), }; - delete env.NX_ON_DAEMON_PROCESS; - const worker = fork(workerPath, [], { stdio: ['ignore', 'inherit', 'inherit', 'ipc'], env, diff --git a/packages/nx/src/project-graph/utils/retrieve-workspace-files.spec.ts b/packages/nx/src/project-graph/utils/retrieve-workspace-files.spec.ts index 3d23230b11e692..4499637562e47b 100644 --- a/packages/nx/src/project-graph/utils/retrieve-workspace-files.spec.ts +++ b/packages/nx/src/project-graph/utils/retrieve-workspace-files.spec.ts @@ -25,7 +25,7 @@ describe('retrieveProjectConfigurationPaths', () => { }) ); - const configPaths = retrieveProjectConfigurationPaths(fs.tempDir, [ + const configPaths = await retrieveProjectConfigurationPaths(fs.tempDir, [ { createNodes: [ '{project.json,**/project.json}', diff --git a/packages/nx/src/utils/all-file-data.ts b/packages/nx/src/utils/all-file-data.ts index 4a6a36271b7c7a..7ce3da07886b33 100644 --- a/packages/nx/src/utils/all-file-data.ts +++ b/packages/nx/src/utils/all-file-data.ts @@ -1,12 +1,7 @@ import { FileData } from '../config/project-graph'; -import { daemonClient } from '../daemon/client/client'; import { getAllFileDataInContext } from './workspace-context'; import { workspaceRoot } from './workspace-root'; export function allFileData(): Promise { - if (daemonClient.enabled()) { - return daemonClient.getAllFileData(); - } else { - return Promise.resolve(getAllFileDataInContext(workspaceRoot)); - } + return getAllFileDataInContext(workspaceRoot); } diff --git a/packages/nx/src/utils/workspace-context.ts b/packages/nx/src/utils/workspace-context.ts index 9640965e758f31..68ee35ee3633a7 100644 --- a/packages/nx/src/utils/workspace-context.ts +++ b/packages/nx/src/utils/workspace-context.ts @@ -81,7 +81,7 @@ export function updateFilesInContext( return workspaceContext?.incrementalUpdate(updatedFiles, deletedFiles); } -export function getAllFileDataInContext(workspaceRoot: string) { +export async function getAllFileDataInContext(workspaceRoot: string) { if (isOnDaemon() || !daemonClient.enabled()) { ensureContextAvailable(workspaceRoot); return workspaceContext.allFileData(); @@ -89,7 +89,7 @@ export function getAllFileDataInContext(workspaceRoot: string) { return daemonClient.getAllFileData(); } -export function getFilesInDirectoryUsingContext( +export async function getFilesInDirectoryUsingContext( workspaceRoot: string, dir: string ) { diff --git a/packages/playwright/src/plugins/plugin.ts b/packages/playwright/src/plugins/plugin.ts index 69d143a3560e56..7cc373d1747840 100644 --- a/packages/playwright/src/plugins/plugin.ts +++ b/packages/playwright/src/plugins/plugin.ts @@ -163,7 +163,7 @@ async function buildPlaywrightTargets( playwrightConfig.testMatch ??= '**/*.@(spec|test).?(c|m)[jt]s?(x)'; const dependsOn: TargetConfiguration['dependsOn'] = []; - forEachTestFile( + await forEachTestFile( (testFile) => { const relativeSpecFilePath = normalizePath( relative(projectRoot, testFile) @@ -210,7 +210,7 @@ async function buildPlaywrightTargets( return { targets, metadata }; } -function forEachTestFile( +async function forEachTestFile( cb: (path: string) => void, opts: { context: CreateNodesContext; @@ -218,7 +218,7 @@ function forEachTestFile( config: PlaywrightTestConfig; } ) { - const files = getFilesInDirectoryUsingContext( + const files = await getFilesInDirectoryUsingContext( opts.context.workspaceRoot, opts.path ); diff --git a/scripts/unit-test-setup.js b/scripts/unit-test-setup.js new file mode 100644 index 00000000000000..b3837d5a994897 --- /dev/null +++ b/scripts/unit-test-setup.js @@ -0,0 +1,13 @@ +module.exports = () => { + process.env.NX_DAEMON = 'false'; + + jest.doMock('@nx/devkit', () => ({ + ...jest.requireActual('@nx/devkit'), + createProjectGraphAsync: jest.fn().mockImplementation(async () => { + return { + nodes: {}, + dependencies: {}, + }; + }), + })); +}; diff --git a/typedoc-theme/jest.config.ts b/typedoc-theme/jest.config.ts index 69cf4a39427b9c..a39ec5d9696170 100644 --- a/typedoc-theme/jest.config.ts +++ b/typedoc-theme/jest.config.ts @@ -1,5 +1,22 @@ +const nxPreset = require('@nx/jest/preset').default; + +const preset = { + ...nxPreset, + testTimeout: 35000, + testMatch: ['**/+(*.)+(spec|test).+(ts|js)?(x)'], + transform: { + '^.+\\.(ts|js|html)$': 'ts-jest', + }, + resolver: '../scripts/patched-jest-resolver.js', + moduleFileExtensions: ['ts', 'js', 'html'], + coverageReporters: ['html'], + maxWorkers: 1, + testEnvironment: 'node', +}; + /* eslint-disable */ export default { + ...preset, displayName: 'typedoc-theme', globals: {}, @@ -14,5 +31,5 @@ export default { resolver: '../scripts/patched-jest-resolver.js', moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], coverageDirectory: '../coverage/typedoc-theme', - preset: '../jest.preset.js', + setupFiles: [], };