@hashgraph/solo
Version:
An opinionated CLI tool to deploy and manage private Hedera Networks.
72 lines • 3.61 kB
JavaScript
// SPDX-License-Identifier: Apache-2.0
import { expect } from 'chai';
import { PathEx } from '../../../../src/business/utils/path-ex.js';
import fs from 'node:fs';
import path from 'node:path';
import sinon from 'sinon';
import { SoloError } from '../../../../src/core/errors/solo-error.js';
describe('PathEx', () => {
const baseDirectory = path.normalize(path.resolve('/base/dir'));
const validPath = PathEx.join(baseDirectory, 'file.txt');
const validPathNormalized = path.normalize(path.resolve(validPath));
const invalidPath = path.normalize(path.resolve('/outside/dir/file.txt'));
beforeEach(() => {
sinon.stub(fs, 'realpathSync').callsFake((inputPath) => {
// Always normalize the input path for consistent comparison
const normalizedInput = path.normalize(path.resolve(inputPath));
const normalizedBaseDirectory = path.normalize(path.resolve(baseDirectory));
const normalizedInvalidPath = path.normalize(path.resolve(invalidPath));
if (normalizedInput === normalizedBaseDirectory || normalizedInput.includes(normalizedBaseDirectory + path.sep)) {
return normalizedInput; // Return normalized path instead of original inputPath
}
if (normalizedInput === normalizedInvalidPath) {
return normalizedInput;
}
throw new Error('Path does not exist');
});
});
afterEach(() => {
sinon.restore();
});
describe('joinWithRealPath', () => {
it('should join paths and return the real path', () => {
const result = PathEx.joinWithRealPath(baseDirectory, 'file.txt');
expect(path.normalize(result)).to.equal(validPathNormalized);
});
it('should throw an error if the path does not exist', () => {
expect(() => PathEx.joinWithRealPath('/nonexistent', 'file.txt')).to.throw('Path does not exist');
});
});
describe('safeJoinWithBaseDirConfinement', () => {
it('should securely join paths within the base directory', () => {
const result = PathEx.safeJoinWithBaseDirConfinement(baseDirectory, 'file.txt');
expect(path.normalize(result)).to.equal(validPathNormalized);
});
it('should throw SoloError for path traversal outside the base directory', () => {
const outsideDirectoryPath = ['..', '..', 'outside', 'dir', 'file.txt'].join(path.sep);
expect(() => PathEx.safeJoinWithBaseDirConfinement(baseDirectory, outsideDirectoryPath)).to.throw(SoloError);
});
});
describe('realPathSync', () => {
it('should return the real path for an existing path', () => {
const result = PathEx.realPathSync(validPath);
expect(path.normalize(result)).to.equal(validPathNormalized);
});
it('should throw an error for a non-existent path', () => {
expect(() => PathEx.realPathSync('/nonexistent')).to.throw('Path does not exist');
});
});
describe('join', () => {
it('should join paths and normalize the result', () => {
const result = PathEx.join('/base', 'dir', 'file.txt');
expect(result).to.equal(path.normalize('/base/dir/file.txt'));
});
});
describe('resolve', () => {
it('should resolve paths to an absolute path', () => {
const result = PathEx.resolve('/base', 'dir', 'file.txt');
expect(result).to.equal(path.resolve('/base', 'dir', 'file.txt'));
});
});
});
//# sourceMappingURL=path-ex.test.js.map