UNPKG

@hashgraph/solo

Version:

An opinionated CLI tool to deploy and manage private Hedera Networks.

151 lines 8.63 kB
// SPDX-License-Identifier: Apache-2.0 import { expect } from 'chai'; import { after, before, describe, it } from 'mocha'; import each from 'mocha-each'; import fs from 'node:fs'; import path from 'node:path'; import { KindDependencyManager } from '../../../../../src/core/dependency-managers/index.js'; import { getTestCacheDirectory, getTemporaryDirectory } from '../../../../test-utility.js'; import * as version from '../../../../../version.js'; import { PathEx } from '../../../../../src/business/utils/path-ex.js'; import sinon from 'sinon'; import { OperatingSystem } from '../../../../../src/business/utils/operating-system.js'; import { InjectTokens } from '../../../../../src/core/dependency-injection/inject-tokens.js'; import { container } from 'tsyringe-neo'; import { platform } from 'node:process'; import * as constants from '../../../../../src/core/constants.js'; describe('KindDependencyManager', () => { const installationDirectory = PathEx.join(getTemporaryDirectory(), 'bin'); const originalPlatform = platform; const originalInstallationDirectory = container.resolve(InjectTokens.KindInstallationDirectory); let sandbox; before(() => { fs.mkdirSync(installationDirectory); sandbox = sinon.createSandbox(); }); after(() => { if (fs.existsSync(installationDirectory)) { fs.rmSync(installationDirectory, { recursive: true }); } }); afterEach(() => { container.register(InjectTokens.OsPlatform, { useValue: originalPlatform }); container.register(InjectTokens.KindInstallationDirectory, { useValue: originalInstallationDirectory }); sandbox.restore(); }); it('should return kind version', () => { const kindDependencyManager = new KindDependencyManager(undefined, installationDirectory, undefined, undefined); expect(kindDependencyManager.getRequiredVersion()).to.equal(version.KIND_VERSION); }); it('should be able to check when kind not installed', () => { const kindDependencyManager = new KindDependencyManager(undefined, installationDirectory, undefined, undefined); expect(kindDependencyManager.isInstalledLocally()).not.to.be.ok; }); it('should be able to check when kind is installed', async () => { const kindDependencyManager = new KindDependencyManager(undefined, installationDirectory, undefined, undefined); // Create the local executable file for testing const localPath = PathEx.join(installationDirectory, constants.KIND); fs.writeFileSync(localPath, ''); expect(kindDependencyManager.isInstalledLocally()).to.be.ok; }); describe('when kind is installed globally', () => { let kindDependencyManager; let runStub; let existsSyncStub; beforeEach(() => { kindDependencyManager = new KindDependencyManager(undefined, installationDirectory, process.arch, undefined); kindDependencyManager.uninstallLocal(); }); afterEach(() => { sandbox.restore(); container.register(InjectTokens.OsPlatform, { useValue: originalPlatform }); container.register(InjectTokens.KindInstallationDirectory, { useValue: originalInstallationDirectory }); }); it('should prefer the global installation if it meets the requirements', async () => { const fakeGlobalBinDirectory = '/test-solo-global-bin'; const fakeGlobalKindPath = `${fakeGlobalBinDirectory}/kind`; const originalPath = process.env.PATH ?? ''; process.env.PATH = `${fakeGlobalBinDirectory}${path.delimiter}${originalPath}`; sandbox.stub(fs, 'accessSync').callsFake((filePath) => { if (String(filePath) === fakeGlobalKindPath) { return; } throw Object.assign(new Error('ENOENT'), { code: 'ENOENT' }); }); runStub = sandbox.stub(kindDependencyManager, 'run'); runStub.withArgs(`"${fakeGlobalKindPath}" --version`).resolves([`kind version ${version.KIND_VERSION}`]); existsSyncStub = sandbox.stub(fs, 'existsSync').returns(true); existsSyncStub.withArgs(`${installationDirectory}/kind`).returns(false); try { // @ts-expect-error TS2341: Property isInstalledGloballyAndMeetsRequirements is private const result = await kindDependencyManager.isInstalledGloballyAndMeetsRequirements(); expect(result).to.be.true; expect(await kindDependencyManager.install(getTestCacheDirectory())).to.be.true; // Should return global path since it meets requirements expect(await kindDependencyManager.getExecutable()).to.equal(constants.KIND); } finally { process.env.PATH = originalPath; } }); it('should install kind locally if the global installation does not meet the requirements', async () => { const temporaryDirectory = getTemporaryDirectory(); container.register(InjectTokens.KindInstallationDirectory, { useValue: temporaryDirectory }); // Stub accessSync so the native PATH scan finds no global kind installation. sandbox.stub(fs, 'accessSync').throws(Object.assign(new Error('ENOENT'), { code: 'ENOENT' })); expect(await kindDependencyManager.install(temporaryDirectory)).to.be.true; expect(fs.existsSync(PathEx.join(temporaryDirectory, constants.KIND))).to.be.ok; expect(await kindDependencyManager.getExecutable()).to.equal(constants.KIND); }); }); describe('Kind Installation Tests', () => { afterEach(() => { container.register(InjectTokens.OsPlatform, { useValue: originalPlatform }); container.register(InjectTokens.KindInstallationDirectory, { useValue: originalInstallationDirectory }); sandbox.restore(); }); each([ [OperatingSystem.OS_LINUX, 'x64'], [OperatingSystem.OS_LINUX, 'amd64'], [OperatingSystem.OS_WIN32, 'amd64'], ]).it('should be able to install kind base on %s and %s', async (osPlatform, osArch) => { container.register(InjectTokens.OsPlatform, { useValue: osPlatform }); container.register(InjectTokens.KindInstallationDirectory, { useValue: installationDirectory }); const kindDependencyManager = new KindDependencyManager(undefined, installationDirectory, osArch, undefined); kindDependencyManager.uninstallLocal(); expect(kindDependencyManager.isInstalledLocally()).not.to.be.ok; // Stub accessSync so the native PATH scan finds no global kind installation. sandbox.stub(fs, 'accessSync').throws(Object.assign(new Error('ENOENT'), { code: 'ENOENT' })); expect(await kindDependencyManager.install(getTestCacheDirectory())).to.be.true; expect(kindDependencyManager.isInstalledLocally()).to.be.ok; fs.rmSync(installationDirectory, { recursive: true }); }); }); describe('KindDependencyManager system methods', () => { let kindDependencyManager; let runStub; beforeEach(() => { kindDependencyManager = new KindDependencyManager(undefined, installationDirectory, process.arch, undefined); runStub = sandbox.stub(kindDependencyManager, 'run'); }); afterEach(() => { sandbox.restore(); }); it('installationMeetsRequirements returns false on error', async () => { runStub.rejects(new Error('fail')); const path = await kindDependencyManager.getExecutable(); await expect(kindDependencyManager.installationMeetsRequirements(path)).to.eventually.be.false; }); it('installationMeetsRequirements returns false on invalid version', async () => { runStub.resolves(['not a version']); const path = await kindDependencyManager.getExecutable(); await expect(kindDependencyManager.installationMeetsRequirements(path)).to.eventually.be.false; }); it('installationMeetsRequirements returns false on lower than required version', async () => { runStub.resolves(['v0.0.5']); const path = await kindDependencyManager.getExecutable(); expect(await kindDependencyManager.installationMeetsRequirements(path)).to.be.false; }); }); }); //# sourceMappingURL=kind-dependency-manager.test.js.map