diff --git a/package.json b/package.json index e98717952..1294e2d71 100644 --- a/package.json +++ b/package.json @@ -39,8 +39,26 @@ "format:write": "prettier --write .", "test:integration:api-tests": "node --test integrationTests/apiTests/tests/testSuite.mjs", "test:integration": "node integrationTests/utils/scripts/run.ts", - "test:unit": "TSX_TSCONFIG_PATH=./unitTests/tsconfig.json npx mocha --config unitTests/.mocharc.json", - "test:unit:all": "npm run test:unit unitTests" + "test:unit": "mocha --config unitTests/.mocharc.json", + "test:unit:all": "npm run test:unit unitTests", + "test:unit:typestrip": "env NODE_OPTIONS='--conditions=typestrip' npm run test:unit", + "test:unit:typestrip:all": "npm run test:unit:typestrip unitTests" + }, + "imports": { + "#src/*": { + "import": "./*.ts", + "require": { + "typestrip": "./*.ts", + "default": "./dist/*.js" + } + }, + "#js/*": { + "import": "./*.js", + "require": { + "typestrip": "./*.js", + "default": "./dist/*.js" + } + } }, "engines": { "node": ">=20", diff --git a/unitTests/.mocharc.json b/unitTests/.mocharc.json index 6b7877684..cfc2b7a0a 100644 --- a/unitTests/.mocharc.json +++ b/unitTests/.mocharc.json @@ -1,9 +1,7 @@ { - "$schema": "https://json.schemastore.org/mocharc.json", - "require": "tsx", "timeout": 0, "ui": "bdd", - "extension": ["js", "mjs", "ts"], + "extension": ["js", "mjs"], "recursive": true, "exit": true } diff --git a/unitTests/components/Component.test.ts b/unitTests/components/Component.test.js similarity index 98% rename from unitTests/components/Component.test.ts rename to unitTests/components/Component.test.js index 5b306ba6f..5f1169884 100644 --- a/unitTests/components/Component.test.ts +++ b/unitTests/components/Component.test.js @@ -1,6 +1,6 @@ -import { describe, it } from 'mocha'; -import { Component, ComponentInvalidPatternError } from '@/components/Component'; -import assert from 'node:assert/strict'; +/* eslint-disable sonarjs/no-nested-functions */ +const { Component, ComponentInvalidPatternError } = require('#src/components/Component'); +const assert = require('node:assert/strict'); describe('Component', () => { const name = 'test-component'; diff --git a/unitTests/components/ComponentV1.test.ts b/unitTests/components/ComponentV1.test.js similarity index 98% rename from unitTests/components/ComponentV1.test.ts rename to unitTests/components/ComponentV1.test.js index a8f2982f4..aa0d0cd54 100644 --- a/unitTests/components/ComponentV1.test.ts +++ b/unitTests/components/ComponentV1.test.js @@ -1,8 +1,8 @@ /* eslint-disable @typescript-eslint/no-require-imports, sonarjs/void-use, sonarjs/assertions-in-tests, sonarjs/no-nested-functions */ // Not sure why sonar cannot pick up the assertions within the tests. I think its because they are `async`. -import { tmpdir } from 'node:os'; -import { +const { tmpdir } = require('node:os'); +const { processResourceExtensionComponent, ComponentV1, InvalidFilesOptionError, @@ -13,13 +13,13 @@ import { InvalidRootOptionError, InvalidPathOptionError, InvalidURLPathOptionError, -} from '@/components/ComponentV1'; -import { Resources } from '@/resources/Resources'; -import assert from 'node:assert/strict'; -import { join } from 'node:path'; -import { mkdtempSync, writeFileSync, mkdirSync, rmSync } from 'node:fs'; -import { fake, restore, replace } from 'sinon'; -import fg from 'fast-glob'; +} = require('#src/components/ComponentV1'); +const { Resources } = require('#src/resources/Resources'); +const assert = require('node:assert/strict'); +const { join } = require('node:path'); +const { mkdtempSync, writeFileSync, mkdirSync, rmSync } = require('node:fs'); +const { fake, restore, replace } = require('sinon'); +const fg = require('fast-glob'); const TEMP_DIR_PATH = join(tmpdir(), 'harper.unit-test.component-v1-'); @@ -45,7 +45,7 @@ function createTempFixture(fixture) { describe('ComponentV1', () => { const componentName = 'test-component'; - const harperLogger = require('@/utility/logging/harper_logger'); + const harperLogger = require('#js/utility/logging/harper_logger'); beforeEach(() => { replace(harperLogger, 'warn', fake()); diff --git a/unitTests/components/EntryHandler.test.ts b/unitTests/components/EntryHandler.test.js similarity index 97% rename from unitTests/components/EntryHandler.test.ts rename to unitTests/components/EntryHandler.test.js index 6f8a75d5e..09d6c90f1 100644 --- a/unitTests/components/EntryHandler.test.ts +++ b/unitTests/components/EntryHandler.test.js @@ -1,12 +1,12 @@ -import { EntryHandler } from '@/components/EntryHandler'; -import { EventEmitter, once } from 'node:events'; -import assert from 'node:assert/strict'; -import { join, basename } from 'node:path'; -import { tmpdir } from 'node:os'; -import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from 'node:fs'; -import { writeFile, mkdir } from 'node:fs/promises'; -import { spy } from 'sinon'; -import { waitFor } from './waitFor'; +const { EntryHandler } = require('#src/components/EntryHandler'); +const { EventEmitter, once } = require('node:events'); +const assert = require('node:assert/strict'); +const { join, basename } = require('node:path'); +const { tmpdir } = require('node:os'); +const { mkdtempSync, mkdirSync, writeFileSync, rmSync } = require('node:fs'); +const { writeFile, mkdir } = require('node:fs/promises'); +const { spy } = require('sinon'); +const { waitFor } = require('./waitFor.js'); function generateFixture(dirPath, fixture) { mkdirSync(dirPath, { recursive: true }); diff --git a/unitTests/components/OptionsWatcher.test.ts b/unitTests/components/OptionsWatcher.test.js similarity index 97% rename from unitTests/components/OptionsWatcher.test.ts rename to unitTests/components/OptionsWatcher.test.js index 2f4330300..3a1989900 100644 --- a/unitTests/components/OptionsWatcher.test.ts +++ b/unitTests/components/OptionsWatcher.test.js @@ -1,14 +1,14 @@ /* eslint-disable sonarjs/no-nested-functions */ -import { OptionsWatcher } from '@/components/OptionsWatcher'; -import { EventEmitter, once } from 'node:events'; -import assert from 'node:assert/strict'; -import { join } from 'node:path'; -import { tmpdir } from 'node:os'; -import { mkdtempSync, writeFileSync, rmSync } from 'node:fs'; -import { writeFile, rm } from 'node:fs/promises'; -import { stringify } from 'yaml'; -import { spy } from 'sinon'; -import { DEFAULT_CONFIG } from '@/components/DEFAULT_CONFIG'; +const { OptionsWatcher } = require('#src/components/OptionsWatcher'); +const { EventEmitter, once } = require('node:events'); +const assert = require('node:assert/strict'); +const { join } = require('node:path'); +const { tmpdir } = require('node:os'); +const { mkdtempSync, writeFileSync, rmSync } = require('node:fs'); +const { writeFile, rm } = require('node:fs/promises'); +const { stringify } = require('yaml'); +const { spy } = require('sinon'); +const { DEFAULT_CONFIG } = require('#src/components/DEFAULT_CONFIG'); /** * This function asserts that an event is emitted. diff --git a/unitTests/components/Scope.test.ts b/unitTests/components/Scope.test.js similarity index 92% rename from unitTests/components/Scope.test.ts rename to unitTests/components/Scope.test.js index 38e7dedc0..549e41ed6 100644 --- a/unitTests/components/Scope.test.ts +++ b/unitTests/components/Scope.test.js @@ -1,17 +1,17 @@ -import { Scope, MissingDefaultFilesOptionError } from '@/components/Scope'; -import { EventEmitter } from 'node:events'; -import assert from 'node:assert/strict'; -import { join, basename } from 'node:path'; -import { tmpdir } from 'node:os'; -import { mkdtempSync, writeFileSync, rmSync } from 'node:fs'; -import { stringify } from 'yaml'; -import { spy } from 'sinon'; -import { OptionsWatcher } from '@/components/OptionsWatcher'; -import { Resources } from '@/resources/Resources'; -import { EntryHandler } from '@/components/EntryHandler'; -import { restartNeeded, resetRestartNeeded } from '@/components/requestRestart'; -import { writeFile } from 'node:fs/promises'; -import { waitFor } from './waitFor'; +const { Scope, MissingDefaultFilesOptionError } = require('#src/components/Scope'); +const { EventEmitter } = require('node:events'); +const assert = require('node:assert/strict'); +const { join, basename } = require('node:path'); +const { tmpdir } = require('node:os'); +const { mkdtempSync, writeFileSync, rmSync } = require('node:fs'); +const { stringify } = require('yaml'); +const { spy } = require('sinon'); +const { OptionsWatcher } = require('#src/components/OptionsWatcher'); +const { Resources } = require('#src/resources/Resources'); +const { EntryHandler } = require('#src/components/EntryHandler'); +const { restartNeeded, resetRestartNeeded } = require('#src/components/requestRestart'); +const { writeFile } = require('node:fs/promises'); +const { waitFor } = require('./waitFor.js'); describe('Scope', () => { beforeEach(() => { diff --git a/unitTests/components/componentLoader.test.ts b/unitTests/components/componentLoader.test.js similarity index 93% rename from unitTests/components/componentLoader.test.ts rename to unitTests/components/componentLoader.test.js index 05a9551d6..c44e2321b 100644 --- a/unitTests/components/componentLoader.test.ts +++ b/unitTests/components/componentLoader.test.js @@ -1,9 +1,8 @@ -import { describe, it, before, beforeEach, after } from 'mocha'; -import assert from 'node:assert/strict'; -import sinon from 'sinon'; -import path from 'path'; -import { tmpdir } from 'os'; -import { mkdtempSync, mkdirSync, writeFileSync, rmSync, existsSync } from 'fs'; +const assert = require('node:assert/strict'); +const sinon = require('sinon'); +const path = require('path'); +const { tmpdir } = require('os'); +const { mkdtempSync, mkdirSync, writeFileSync, rmSync, existsSync } = require('fs'); describe('ComponentLoader Status Integration', function () { let componentStatusRegistry; @@ -11,12 +10,12 @@ describe('ComponentLoader Status Integration', function () { let componentLoader; let lifecycle; - before(() => { + before(function () { // Create a temporary directory for test components tempDir = mkdtempSync(path.join(tmpdir(), 'harper-test-components-')); // Mock environment to use our temp directory - const env = require('@/utility/environment/environmentManager'); + const env = require('#js/utility/environment/environmentManager'); sinon.stub(env, 'get').callsFake((key) => { if (key === 'COMPONENTSROOT') { return tempDir; @@ -30,7 +29,7 @@ describe('ComponentLoader Status Integration', function () { }); // Get both the lifecycle and internal objects - const statusModule = require('@/components/status'); + const statusModule = require('#src/components/status/index'); const { internal } = statusModule; lifecycle = statusModule.lifecycle; componentStatusRegistry = internal.componentStatusRegistry; @@ -48,14 +47,14 @@ describe('ComponentLoader Status Integration', function () { sinon.spy(componentStatusRegistry, 'getStatus'); // Mock getConfigObj to avoid loading real config for root components - const configUtils = require('@/config/configUtils'); + const configUtils = require('#js/config/configUtils'); sinon.stub(configUtils, 'getConfigObj').returns({}); // Clear the componentLoader from require cache to ensure it gets our spied lifecycle - delete require.cache[require.resolve('@/components/componentLoader')]; + delete require.cache[require.resolve('#src/components/componentLoader')]; // Load componentLoader after setting up spies - componentLoader = require('@/components/componentLoader'); + componentLoader = require('#src/components/componentLoader'); }); after(function () { @@ -215,7 +214,7 @@ describe('ComponentLoader Status Integration', function () { it('should handle component loading errors gracefully', async function () { // Stub the dataLoader module's handleApplication method to throw an error - const dataLoaderModule = require('@/resources/dataLoader'); + const dataLoaderModule = require('#src/resources/dataLoader'); const originalhandleApplication = dataLoaderModule.handleApplication; sinon.stub(dataLoaderModule, 'handleApplication').throws(new Error('DataLoader failed to initialize')); diff --git a/unitTests/components/deriveCommonPatternBase.test.ts b/unitTests/components/deriveCommonPatternBase.test.js similarity index 80% rename from unitTests/components/deriveCommonPatternBase.test.ts rename to unitTests/components/deriveCommonPatternBase.test.js index 5f2e4003f..bb80baf46 100644 --- a/unitTests/components/deriveCommonPatternBase.test.ts +++ b/unitTests/components/deriveCommonPatternBase.test.js @@ -1,5 +1,5 @@ -import { deriveCommonPatternBase } from '@/components/deriveCommonPatternBase'; -import assert from 'node:assert/strict'; +const { deriveCommonPatternBase } = require('#src/components/deriveCommonPatternBase'); +const assert = require('node:assert/strict'); describe('deriveCommonPatternBase', () => { [ diff --git a/unitTests/components/deriveGlobOption.test.ts b/unitTests/components/deriveGlobOption.test.js similarity index 94% rename from unitTests/components/deriveGlobOption.test.ts rename to unitTests/components/deriveGlobOption.test.js index 1abc9838d..97271691a 100644 --- a/unitTests/components/deriveGlobOption.test.ts +++ b/unitTests/components/deriveGlobOption.test.js @@ -1,5 +1,5 @@ -import assert from 'node:assert/strict'; -import { deriveGlobOptions } from '@/components/deriveGlobOptions'; +const assert = require('node:assert/strict'); +const { deriveGlobOptions } = require('#src/components/deriveGlobOptions'); // components/deriveGlobOptions.test.ts diff --git a/unitTests/components/requestRestart.test.ts b/unitTests/components/requestRestart.test.js similarity index 60% rename from unitTests/components/requestRestart.test.ts rename to unitTests/components/requestRestart.test.js index 64854ab0b..b384b42c4 100644 --- a/unitTests/components/requestRestart.test.ts +++ b/unitTests/components/requestRestart.test.js @@ -1,5 +1,5 @@ -import { requestRestart, restartNeeded } from '@/components/requestRestart'; -import assert from 'node:assert/strict'; +const { requestRestart, restartNeeded } = require('#src/components/requestRestart'); +const assert = require('node:assert/strict'); describe('requestRestart', () => { it('should update the shared buffer', () => { diff --git a/unitTests/components/resolveBaseURLPath.test.ts b/unitTests/components/resolveBaseURLPath.test.js similarity index 90% rename from unitTests/components/resolveBaseURLPath.test.ts rename to unitTests/components/resolveBaseURLPath.test.js index 28b8360dc..9d0dae502 100644 --- a/unitTests/components/resolveBaseURLPath.test.ts +++ b/unitTests/components/resolveBaseURLPath.test.js @@ -1,5 +1,5 @@ -import { resolveBaseURLPath, InvalidBaseURLPathError } from '@/components/resolveBaseURLPath'; -import assert from 'node:assert/strict'; +const { resolveBaseURLPath, InvalidBaseURLPathError } = require('#src/components/resolveBaseURLPath'); +const assert = require('node:assert/strict'); describe('resolveBaseURLPath', () => { const componentName = 'test-component'; diff --git a/unitTests/components/status/ComponentStatus.test.ts b/unitTests/components/status/ComponentStatus.test.js similarity index 97% rename from unitTests/components/status/ComponentStatus.test.ts rename to unitTests/components/status/ComponentStatus.test.js index a640f3ab5..19e30e287 100644 --- a/unitTests/components/status/ComponentStatus.test.ts +++ b/unitTests/components/status/ComponentStatus.test.js @@ -1,8 +1,7 @@ -import assert from 'node:assert/strict'; -import sinon from 'sinon'; -import { ComponentStatus } from '@/components/status/ComponentStatus'; -import { COMPONENT_STATUS_LEVELS } from '@/components/status/types'; -import { describe, it, beforeEach, afterEach } from 'mocha'; +const assert = require('node:assert/strict'); +const sinon = require('sinon'); +const { ComponentStatus } = require('#src/components/status/ComponentStatus'); +const { COMPONENT_STATUS_LEVELS } = require('#src/components/status/types'); describe('ComponentStatus', function () { let clock; diff --git a/unitTests/components/status/ComponentStatusRegistry.test.ts b/unitTests/components/status/ComponentStatusRegistry.test.js similarity index 98% rename from unitTests/components/status/ComponentStatusRegistry.test.ts rename to unitTests/components/status/ComponentStatusRegistry.test.js index c0c78e964..69a39b2c0 100644 --- a/unitTests/components/status/ComponentStatusRegistry.test.ts +++ b/unitTests/components/status/ComponentStatusRegistry.test.js @@ -1,9 +1,11 @@ -import assert from 'node:assert/strict'; -import sinon from 'sinon'; -import { ComponentStatusRegistry } from '@/components/status/ComponentStatusRegistry'; -import { ComponentStatus } from '@/components/status/ComponentStatus'; -import { COMPONENT_STATUS_LEVELS } from '@/components/status/types'; -import { StatusAggregator } from '@/components/status/crossThread'; +const assert = require('node:assert/strict'); +const sinon = require('sinon'); +const { ComponentStatusRegistry } = require('#src/components/status/ComponentStatusRegistry'); +const { ComponentStatus } = require('#src/components/status/ComponentStatus'); +const { COMPONENT_STATUS_LEVELS } = require('#src/components/status/types'); +const { StatusAggregator } = require('#src/components/status/crossThread'); +const itcModule = require('#js/server/threads/itc'); +const manageThreadsModule = require('#js/server/threads/manageThreads'); describe('ComponentStatusRegistry', function () { let registry; @@ -14,8 +16,6 @@ describe('ComponentStatusRegistry', function () { clock = sinon.useFakeTimers(); // Stub ITC functions - const itcModule = require('@/server/threads/itc'); - const manageThreadsModule = require('@/server/threads/manageThreads'); sinon.stub(itcModule, 'sendItcEvent').resolves(); sinon.stub(manageThreadsModule, 'onMessageByType'); sinon.stub(manageThreadsModule, 'getWorkerIndex').returns(0); @@ -504,7 +504,7 @@ describe('ComponentStatusRegistry', function () { describe('static getAggregatedFromAllThreads method', function () { it('should collect and aggregate statuses', async function () { // Mock the crossThreadCollector to avoid actual ITC communication - const { crossThreadCollector } = require('@/components/status/crossThread'); + const { crossThreadCollector } = require('#src/components/status/crossThread'); const originalCollect = crossThreadCollector.collect; // Create a fresh registry for this test diff --git a/unitTests/components/status/api.test.ts b/unitTests/components/status/api.test.js similarity index 96% rename from unitTests/components/status/api.test.ts rename to unitTests/components/status/api.test.js index 093ae229f..b3588a949 100644 --- a/unitTests/components/status/api.test.ts +++ b/unitTests/components/status/api.test.js @@ -1,6 +1,6 @@ -import assert from 'node:assert/strict'; -import { statusForComponent, lifecycle, reset, STATUS, internal } from '@/../components/status'; -import { describe, it, afterEach } from 'mocha'; +const assert = require('node:assert/strict'); +const { statusForComponent, lifecycle, reset, STATUS } = require('#src/components/status/index'); +const { internal } = require('#src/components/status/index'); describe('Component Status Public API', function () { afterEach(function () { diff --git a/unitTests/components/status/crossThread.test.ts b/unitTests/components/status/crossThread.test.js similarity index 96% rename from unitTests/components/status/crossThread.test.ts rename to unitTests/components/status/crossThread.test.js index 675aff76c..4d7876444 100644 --- a/unitTests/components/status/crossThread.test.ts +++ b/unitTests/components/status/crossThread.test.js @@ -1,19 +1,17 @@ -import assert from 'node:assert/strict'; -import sinon from 'sinon'; -import { CrossThreadStatusCollector, StatusAggregator } from '@/components/status/crossThread'; -import { ComponentStatusRegistry } from '@/components/status/ComponentStatusRegistry'; +const assert = require('node:assert/strict'); +const sinon = require('sinon'); +const { CrossThreadStatusCollector, StatusAggregator } = require('#src/components/status/crossThread'); +const { ComponentStatusRegistry } = require('#src/components/status/ComponentStatusRegistry'); +const itcModule = require('#js/server/threads/itc'); +const manageThreadsModule = require('#js/server/threads/manageThreads'); describe('CrossThread Module', function () { let sendItcEventStub; let onMessageByTypeStub; let getWorkerIndexStub; - let itcModule; - let manageThreadsModule; beforeEach(function () { // Stub ITC functions - itcModule = require('@/server/threads/itc'); - manageThreadsModule = require('@/server/threads/manageThreads'); sendItcEventStub = sinon.stub(itcModule, 'sendItcEvent').resolves(); onMessageByTypeStub = sinon.stub(manageThreadsModule, 'onMessageByType'); getWorkerIndexStub = sinon.stub(manageThreadsModule, 'getWorkerIndex').returns(0); @@ -173,7 +171,7 @@ describe('CrossThread Module', function () { getWorkerIndexStub.returns(0); // Mock getWorkerCount to return 2 (expecting 2 worker responses) - const manageThreadsModule = require('@/server/threads/manageThreads'); + const manageThreadsModule = require('#js/server/threads/manageThreads'); const getWorkerCountStub = sinon.stub(manageThreadsModule, 'getWorkerCount').returns(2); // Track when collection completes diff --git a/unitTests/components/status/errors.test.ts b/unitTests/components/status/errors.test.js similarity index 96% rename from unitTests/components/status/errors.test.ts rename to unitTests/components/status/errors.test.js index 1e2fe2491..2b0f0b518 100644 --- a/unitTests/components/status/errors.test.ts +++ b/unitTests/components/status/errors.test.js @@ -1,14 +1,13 @@ -import assert from 'node:assert/strict'; -import { +const assert = require('node:assert/strict'); +const { ComponentStatusError, CrossThreadTimeoutError, ITCError, AggregationError, ComponentStatusOperationError, CrossThreadCollectionError, -} from '@/components/status/errors'; -import { HTTP_STATUS_CODES } from '@/utility/errors/commonErrors'; -import { describe, it } from 'mocha'; +} = require('#src/components/status/errors'); +const { HTTP_STATUS_CODES } = require('#js/utility/errors/commonErrors'); describe('Component Status Errors', function () { describe('ComponentStatusError', function () { diff --git a/unitTests/components/status/index.test.ts b/unitTests/components/status/index.test.js similarity index 98% rename from unitTests/components/status/index.test.ts rename to unitTests/components/status/index.test.js index 1fdc98df9..a362efb23 100644 --- a/unitTests/components/status/index.test.ts +++ b/unitTests/components/status/index.test.js @@ -1,6 +1,5 @@ -import assert from 'node:assert/strict'; -import { statusForComponent, reset, STATUS, internal } from '@/components/status/index'; - +const assert = require('node:assert/strict'); +const { statusForComponent, reset, STATUS, internal } = require('#src/components/status/index'); const { ComponentStatus } = internal; describe('Component Status API', function () { diff --git a/unitTests/components/status/registry.test.ts b/unitTests/components/status/registry.test.js similarity index 80% rename from unitTests/components/status/registry.test.ts rename to unitTests/components/status/registry.test.js index 676c9b8f4..1d9ac940e 100644 --- a/unitTests/components/status/registry.test.ts +++ b/unitTests/components/status/registry.test.js @@ -1,16 +1,9 @@ -import assert from 'node:assert/strict'; -import { ComponentStatusRegistry } from '@/components/status/ComponentStatusRegistry'; -import { describe, it, before, after } from 'mocha'; +const assert = require('node:assert/strict'); +const { ComponentStatusRegistry } = require('#src/components/status/ComponentStatusRegistry'); +const { componentStatusRegistry } = require('#src/components/status/registry'); describe('componentStatusRegistry singleton', function () { - let componentStatusRegistry; - - before(() => { - const registry = require('@/components/status/registry'); - componentStatusRegistry = registry.componentStatusRegistry; - }); - - after(() => { + after(function () { // Clean up the global singleton after tests componentStatusRegistry.reset(); }); @@ -20,7 +13,7 @@ describe('componentStatusRegistry singleton', function () { }); it('should be a singleton instance', function () { - const { componentStatusRegistry: registry2 } = require('@/components/status/registry'); + const { componentStatusRegistry: registry2 } = require('#src/components/status/registry'); assert.strictEqual(componentStatusRegistry, registry2); }); diff --git a/unitTests/components/waitFor.js b/unitTests/components/waitFor.js new file mode 100644 index 000000000..9254b2a00 --- /dev/null +++ b/unitTests/components/waitFor.js @@ -0,0 +1,14 @@ +const assert = require('node:assert/strict'); +const { setTimeout } = require('node:timers/promises'); + +async function waitFor(condition, timeout = 1000, interval = 100) { + let time = 0; + while (!condition()) { + await setTimeout(interval); + if ((time += interval) > timeout) { + assert.fail('Timeout waiting for condition'); + } + } +} + +module.exports = { waitFor }; diff --git a/unitTests/components/waitFor.ts b/unitTests/components/waitFor.ts deleted file mode 100644 index 4eafacf2e..000000000 --- a/unitTests/components/waitFor.ts +++ /dev/null @@ -1,12 +0,0 @@ -import assert from 'node:assert/strict'; -import { setTimeout } from 'node:timers/promises'; - -export async function waitFor(condition, timeout = 1000, interval = 100) { - let time = 0; - while (!condition()) { - await setTimeout(interval); - if ((time += interval) > timeout) { - assert.fail('Timeout waiting for condition'); - } - } -} diff --git a/unitTests/testUtils.js b/unitTests/testUtils.js new file mode 100644 index 000000000..892d895b5 --- /dev/null +++ b/unitTests/testUtils.js @@ -0,0 +1,82 @@ +const path = require('node:path'); +const { isMainThread } = require('node:worker_threads'); +const env = require('#js/utility/environment/environmentManager'); +const terms = require('#src/utility/hdbTerms'); +const { resetDatabases } = require('#src/resources/databases'); +const fs = require('fs-extra'); +const { stringify } = require('yaml'); +const { setHdbBasePath } = require('#js/utility/environment/environmentManager'); + +const UNIT_TEST_DIR = __dirname; +const ENV_DIR_NAME = 'testEnv'; +const ENV_DIR_PATH = path.join(UNIT_TEST_DIR, ENV_DIR_NAME); + +async function tearDownMockDB(envs = undefined, partial_teardown = false) { + try { + if (envs !== undefined) { + await Promise.all(envs.map((table) => table.delete())).catch(); + } + + delete global.hdb_schema; + global.lmdb_map = undefined; + if (!partial_teardown) { + await fs.remove(ENV_DIR_PATH); + } + } catch (err) {} +} + +function getMockLMDBPath() { + const lmdbPath = path.join(UNIT_TEST_DIR, ENV_DIR_NAME, process.pid.toString()); + // TODO: Setting the "root" path some more; should clean this up! + env.setProperty(terms.HDB_SETTINGS_NAMES.HDB_ROOT_KEY, lmdbPath); + env.setProperty(terms.CONFIG_PARAMS.DATABASES, { data: { path: lmdbPath }, dev: { path: lmdbPath } }); + resetDatabases(); + if (isMainThread) { + process.on('exit', () => tearDownMockDB()); + } + return lmdbPath; +} + +function createTestSandbox() { + // TODO: Seems like we're setting the "root" path over and over again + // We should clean this up and make it so you only have to set it once + const lmdbPath = getMockLMDBPath(); // we set it in here + process.env.ROOTPATH = lmdbPath; // setting it again + setHdbBasePath(lmdbPath); // also setting the root path + const storagePath = path.join(lmdbPath, 'database'); + process.env.STORAGE_PATH = storagePath; // another "root-ish" path we have to set + const bootPropsPath = path.join(lmdbPath, terms.HDB_HOME_DIR_NAME); + fs.mkdirpSync(storagePath); + fs.writeFileSync( + path.join(lmdbPath, 'harperdb-config.yaml'), + stringify({ + rootPath: lmdbPath, + logging: { + path: path.join(lmdbPath, 'logs'), + file: false, + stdStreams: false, + auditLog: false, + }, + localStudio: {}, + operationsApi: {}, + http: {}, + storage: { writeAsync: false }, + }) + ); + fs.mkdirpSync(bootPropsPath); + fs.writeFileSync( + path.join(bootPropsPath, terms.BOOT_PROPS_FILE_NAME), + `settings_path = ${lmdbPath}/harperdb-config.yaml` + ); + return lmdbPath; +} + +function cleanupTestSandbox() { + return tearDownMockDB(); +} + +module.exports = { + getMockLMDBPath, + createTestSandbox, + cleanupTestSandbox, +}; diff --git a/unitTests/tsconfig.json b/unitTests/tsconfig.json deleted file mode 100644 index 52415630e..000000000 --- a/unitTests/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../tsconfig.json", - "include": ["./**/*"], - "compilerOptions": { - // Provide convenient path alias for compiled output so its relative to root - // Meaning imports like "@/components/Component" will just work! - // Change this to ../* once we're fully in TypeStrip land - "baseUrl": "..", - "paths": { - "@/*": ["./dist/*"] - } - } -} diff --git a/utility/processManagement/processManagement.js b/utility/processManagement/processManagement.js index 68ffbca00..88db3c97b 100644 --- a/utility/processManagement/processManagement.js +++ b/utility/processManagement/processManagement.js @@ -121,7 +121,7 @@ function restartHdb() { function getHdbPid() { const harperPath = envMangr.getHdbBasePath(); if (!harperPath) return; - const pidFile = path.join(harperPath, terms.HDB_PID_FILE); + const pidFile = path.join(harperPath, hdbTerms.HDB_PID_FILE); const hdbPid = readPidFile(pidFile); // If the pid file doesn't exist or the pid is the same as the current process, return. // In a Docker container, the pid is usually 1, and so if a previous process crashed, there will still