mirror of
https://github.com/xtrll/MusicMetaFinder.git
synced 2026-04-17 19:54:06 +02:00
test(utils): add tests for utility functions in utils folder
This commit is contained in:
32
package-lock.json
generated
32
package-lock.json
generated
@@ -14,7 +14,8 @@
|
||||
"dotenv": "^16.4.5",
|
||||
"ffmetadata": "^1.7.0",
|
||||
"fpcalc": "^1.3.0",
|
||||
"mime-types": "^2.1.35"
|
||||
"mime-types": "^2.1.35",
|
||||
"nock": "^13.5.4"
|
||||
},
|
||||
"bin": {
|
||||
"music-meta-finder": "cli.js"
|
||||
@@ -3776,6 +3777,12 @@
|
||||
"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/json-stringify-safe": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
||||
"integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/json5": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
|
||||
@@ -4091,6 +4098,20 @@
|
||||
"@sinonjs/commons": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/nock": {
|
||||
"version": "13.5.4",
|
||||
"resolved": "https://registry.npmjs.org/nock/-/nock-13.5.4.tgz",
|
||||
"integrity": "sha512-yAyTfdeNJGGBFxWdzSKCBYxs5FxLbCg5X5Q4ets974hcQzG1+qCxvIyOo4j2Ry6MUlhWVMX4OoYDefAIIwupjw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "^4.1.0",
|
||||
"json-stringify-safe": "^5.0.1",
|
||||
"propagate": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.13"
|
||||
}
|
||||
},
|
||||
"node_modules/node-int64": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
|
||||
@@ -4419,6 +4440,15 @@
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
|
||||
},
|
||||
"node_modules/propagate": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz",
|
||||
"integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
"dotenv": "^16.4.5",
|
||||
"ffmetadata": "^1.7.0",
|
||||
"fpcalc": "^1.3.0",
|
||||
"mime-types": "^2.1.35"
|
||||
"mime-types": "^2.1.35",
|
||||
"nock": "^13.5.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/eslintrc": "^3.0.2",
|
||||
|
||||
78
test/utils/deleteDirectoryRecursively.test.js
Normal file
78
test/utils/deleteDirectoryRecursively.test.js
Normal file
@@ -0,0 +1,78 @@
|
||||
import { expect } from 'chai'
|
||||
import sinon from 'sinon';
|
||||
import fs from 'fs/promises';
|
||||
import path from "path";
|
||||
import deleteDirectoryRecursively from "../../src/utils/deleteDirectoryRecursively.js";
|
||||
|
||||
describe('DeleteDirectoryRecursively', () => {
|
||||
let readdirStub, unlinkStub, rmdirStub;
|
||||
|
||||
beforeEach(() => {
|
||||
readdirStub = sinon.stub(fs, 'readdir');
|
||||
unlinkStub = sinon.stub(fs, 'unlink');
|
||||
rmdirStub = sinon.stub(fs, 'rmdir');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
readdirStub.restore();
|
||||
unlinkStub.restore();
|
||||
rmdirStub.restore();
|
||||
});
|
||||
|
||||
it('should delete an empty directory', async () => {
|
||||
const dirPath = 'testDir';
|
||||
|
||||
readdirStub.withArgs(dirPath).resolves([]);
|
||||
rmdirStub.withArgs(dirPath).resolves();
|
||||
|
||||
await deleteDirectoryRecursively(dirPath);
|
||||
|
||||
expect(readdirStub.calledOnce).to.be.true;
|
||||
expect(rmdirStub.calledOnceWith(dirPath)).to.be.true;
|
||||
});
|
||||
|
||||
it('should delete a directory with files', async () => {
|
||||
const dirPath = 'dir';
|
||||
const filePath = path.join(dirPath, 'file.txt');
|
||||
|
||||
readdirStub.withArgs(dirPath).resolves([{ name: 'file.txt', isDirectory: () => false }]);
|
||||
unlinkStub.withArgs(filePath).resolves();
|
||||
rmdirStub.withArgs(dirPath).resolves();
|
||||
|
||||
await deleteDirectoryRecursively(dirPath);
|
||||
|
||||
expect(readdirStub.calledOnce).to.be.true;
|
||||
expect(unlinkStub.calledOnceWith(filePath)).to.be.true;
|
||||
expect(rmdirStub.calledOnceWith(dirPath)).to.be.true;
|
||||
});
|
||||
|
||||
it('should delete a nested directory with files', async () => {
|
||||
const dirPath = 'dir';
|
||||
const nestedDirPath = path.join(dirPath, 'nestedDir');
|
||||
const filePath = path.join(dirPath, 'file.txt');
|
||||
const nestedFilePath = path.join(nestedDirPath, 'nestedFile.txt');
|
||||
|
||||
readdirStub.withArgs(dirPath).resolves([
|
||||
{ name: 'file.txt', isDirectory: () => false },
|
||||
{ name: 'nestedDir', isDirectory: () => true },
|
||||
]);
|
||||
|
||||
readdirStub.withArgs(nestedDirPath).resolves([
|
||||
{ name: 'nestedFile.txt', isDirectory: () => false },
|
||||
]);
|
||||
|
||||
unlinkStub.withArgs(filePath).resolves();
|
||||
unlinkStub.withArgs(nestedFilePath).resolves();
|
||||
rmdirStub.withArgs(dirPath).resolves();
|
||||
rmdirStub.withArgs(nestedDirPath).resolves();
|
||||
|
||||
await deleteDirectoryRecursively(dirPath);
|
||||
|
||||
expect(readdirStub.calledTwice).to.be.true;
|
||||
expect(unlinkStub.calledTwice).to.be.true;
|
||||
expect(unlinkStub.calledWith(filePath)).to.be.true;
|
||||
expect(unlinkStub.calledWith(nestedFilePath)).to.be.true;
|
||||
expect(rmdirStub.calledWith(nestedDirPath)).to.be.true;
|
||||
expect(rmdirStub.calledWith(dirPath)).to.be.true;
|
||||
});
|
||||
})
|
||||
0
test/utils/downloadImage.test.js
Normal file
0
test/utils/downloadImage.test.js
Normal file
54
test/utils/ensureDirectoryExists.test.js
Normal file
54
test/utils/ensureDirectoryExists.test.js
Normal file
@@ -0,0 +1,54 @@
|
||||
import { expect } from 'chai';
|
||||
import esmock from 'esmock';
|
||||
import sinon from 'sinon';
|
||||
import fs from 'fs';
|
||||
|
||||
describe('ensureDirectoryExists', () => {
|
||||
let ensureDirectoryExists;
|
||||
let fsMock;
|
||||
let sandbox;
|
||||
|
||||
beforeEach(async () => {
|
||||
sandbox = sinon.createSandbox();
|
||||
fsMock = {
|
||||
existsSync: sandbox.stub(),
|
||||
mkdirSync: sandbox.stub(),
|
||||
};
|
||||
|
||||
// Dynamically import ensureDirectoryExists and replace fs with a mock
|
||||
ensureDirectoryExists = await esmock(
|
||||
'../../src/utils/ensureDirectoryExists.js',
|
||||
{
|
||||
'fs': fsMock,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
sandbox.restore();
|
||||
esmock.purge(ensureDirectoryExists);
|
||||
});
|
||||
|
||||
it('should not create a directory if it already exists', () => {
|
||||
const dirPath = 'path/to/existing/dir';
|
||||
|
||||
fsMock.existsSync.returns(true);
|
||||
|
||||
ensureDirectoryExists(dirPath);
|
||||
|
||||
expect(fsMock.existsSync.calledOnceWith(dirPath)).to.be.true;
|
||||
expect(fsMock.mkdirSync.notCalled).to.be.true;
|
||||
});
|
||||
|
||||
it('should create a directory if it does not exist', () => {
|
||||
const dirPath = 'path/to/new/dir';
|
||||
|
||||
fsMock.existsSync.returns(false);
|
||||
|
||||
ensureDirectoryExists(dirPath);
|
||||
|
||||
expect(fsMock.existsSync.calledOnceWith(dirPath)).to.be.true;
|
||||
expect(fsMock.mkdirSync.calledOnceWith(dirPath, { recursive: true })).to.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
89
test/utils/fetchFiles.test.js
Normal file
89
test/utils/fetchFiles.test.js
Normal file
@@ -0,0 +1,89 @@
|
||||
import path from 'path';
|
||||
import { expect } from 'chai';
|
||||
import sinon from 'sinon';
|
||||
import esmock from 'esmock';
|
||||
|
||||
function normalizeToForwardSlash(p) {
|
||||
return p.split(path.sep).join('/');
|
||||
}
|
||||
|
||||
describe('fetchFiles', () => {
|
||||
let fetchFiles, fsStub;
|
||||
|
||||
beforeEach(async () => {
|
||||
fsStub = {
|
||||
promises: {
|
||||
stat: sinon.stub(),
|
||||
readdir: sinon.stub()
|
||||
}
|
||||
};
|
||||
|
||||
fetchFiles = await esmock('../../src/utils/fetchFiles.js', {
|
||||
fs: fsStub
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
esmock.purge(fetchFiles);
|
||||
sinon.restore();
|
||||
});
|
||||
|
||||
it('should return an array with a single file when given a file path', async () => {
|
||||
const filePath = '/path/to/file.txt';
|
||||
|
||||
fsStub.promises.stat.resolves({ isFile: () => true, isDirectory: () => false });
|
||||
|
||||
const result = await fetchFiles(filePath);
|
||||
expect(result).to.deep.equal([normalizeToForwardSlash(filePath)]);
|
||||
});
|
||||
|
||||
it('should return an array of files when given a directory path', async () => {
|
||||
const dirPath = '/path/to/directory';
|
||||
const subdirPath = path.join(dirPath, 'subdir'); // Use path.join for consistency
|
||||
|
||||
fsStub.promises.stat.withArgs(dirPath).resolves({ isFile: () => false, isDirectory: () => true });
|
||||
fsStub.promises.stat.withArgs(subdirPath).resolves({ isFile: () => false, isDirectory: () => true });
|
||||
fsStub.promises.stat.resolves({ isFile: () => true, isDirectory: () => false }); // Default for files
|
||||
|
||||
fsStub.promises.readdir.withArgs(dirPath, { withFileTypes: true }).resolves([
|
||||
{ name: 'file1.txt', isFile: () => true, isDirectory: () => false },
|
||||
{ name: 'file2.txt', isFile: () => true, isDirectory: () => false },
|
||||
{ name: 'subdir', isFile: () => false, isDirectory: () => true }
|
||||
]);
|
||||
fsStub.promises.readdir.withArgs(subdirPath, { withFileTypes: true }).resolves([
|
||||
{ name: 'file3.txt', isFile: () => true, isDirectory: () => false }
|
||||
]);
|
||||
|
||||
const result = await fetchFiles(dirPath);
|
||||
console.log('Test Result:', result); // Add logging to debug the result
|
||||
expect(result).to.deep.equal([
|
||||
normalizeToForwardSlash(`${dirPath}/file1.txt`),
|
||||
normalizeToForwardSlash(`${dirPath}/file2.txt`),
|
||||
normalizeToForwardSlash(`${dirPath}/subdir/file3.txt`)
|
||||
]);
|
||||
});
|
||||
|
||||
it('should throw an error if the path does not exist', async () => {
|
||||
const invalidPath = '/invalid/path';
|
||||
|
||||
fsStub.promises.stat.rejects(new Error('ENOENT: no such file or directory'));
|
||||
|
||||
try {
|
||||
await fetchFiles(invalidPath);
|
||||
} catch (error) {
|
||||
expect(error.message).to.equal('Failed to fetch files: ENOENT: no such file or directory');
|
||||
}
|
||||
});
|
||||
|
||||
it('should throw an error if the path is neither a file nor a directory', async () => {
|
||||
const weirdPath = '/weird/path';
|
||||
|
||||
fsStub.promises.stat.resolves({ isFile: () => false, isDirectory: () => false });
|
||||
|
||||
try {
|
||||
await fetchFiles(weirdPath);
|
||||
} catch (error) {
|
||||
expect(error.message).to.equal('Failed to fetch files: Input path is neither a file nor a directory: /weird/path');
|
||||
}
|
||||
});
|
||||
});
|
||||
92
test/utils/renameAudioFileTitle.test.js
Normal file
92
test/utils/renameAudioFileTitle.test.js
Normal file
@@ -0,0 +1,92 @@
|
||||
import path from 'path';
|
||||
import { expect } from 'chai';
|
||||
import sinon from 'sinon';
|
||||
import esmock from 'esmock';
|
||||
|
||||
// Utility function to normalize paths to use forward slashes
|
||||
function normalizeToForwardSlash(p) {
|
||||
return p.split(path.sep).join('/');
|
||||
}
|
||||
|
||||
describe('renameFile', () => {
|
||||
let renameFile, fsStub, generateUniqueFilenameStub;
|
||||
|
||||
beforeEach(async () => {
|
||||
fsStub = {
|
||||
rename: sinon.stub()
|
||||
};
|
||||
|
||||
generateUniqueFilenameStub = sinon.stub();
|
||||
|
||||
renameFile = await esmock('../../src/utils/renameAudioFileTitle.js', {
|
||||
'fs/promises': fsStub,
|
||||
'../../src/utils/generateUniqueFilename.js': generateUniqueFilenameStub
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
esmock.purge(renameFile);
|
||||
sinon.restore();
|
||||
});
|
||||
|
||||
it('should rename a file successfully with valid artist, title, and filePath', async () => {
|
||||
const artist = 'Artist';
|
||||
const title = 'Title';
|
||||
const filePath = normalizeToForwardSlash('/path/to/file.mp3');
|
||||
const newFilePath = normalizeToForwardSlash('/path/to/Artist - Title.mp3');
|
||||
|
||||
generateUniqueFilenameStub.resolves(newFilePath);
|
||||
fsStub.rename.resolves();
|
||||
|
||||
const result = await renameFile(artist, title, filePath);
|
||||
|
||||
console.log('Arguments passed to generateUniqueFilename:', generateUniqueFilenameStub.args);
|
||||
console.log('Arguments expected for generateUniqueFilename:', [normalizeToForwardSlash('/path/to'), normalizeToForwardSlash('Artist - Title.mp3')]);
|
||||
|
||||
expect(result).to.equal(normalizeToForwardSlash(newFilePath));
|
||||
expect(generateUniqueFilenameStub.calledWith(normalizeToForwardSlash('/path/to'), 'Artist - Title.mp3')).to.be.true;
|
||||
expect(fsStub.rename.calledWith(normalizeToForwardSlash(filePath), normalizeToForwardSlash(newFilePath))).to.be.true;
|
||||
});
|
||||
|
||||
it('should throw an error if filePath, artist, or title are not provided', async () => {
|
||||
try {
|
||||
await renameFile('', 'Title', normalizeToForwardSlash('/path/to/file.mp3'));
|
||||
throw new Error('Test failed - expected error not thrown');
|
||||
} catch (error) {
|
||||
expect(error.message).to.equal('File path, artist, and title must be provided when renaming file.');
|
||||
}
|
||||
|
||||
try {
|
||||
await renameFile('Artist', '', normalizeToForwardSlash('/path/to/file.mp3'));
|
||||
throw new Error('Test failed - expected error not thrown');
|
||||
} catch (error) {
|
||||
expect(error.message).to.equal('File path, artist, and title must be provided when renaming file.');
|
||||
}
|
||||
|
||||
try {
|
||||
await renameFile('Artist', 'Title', '');
|
||||
throw new Error('Test failed - expected error not thrown');
|
||||
} catch (error) {
|
||||
expect(error.message).to.equal('File path, artist, and title must be provided when renaming file.');
|
||||
}
|
||||
});
|
||||
|
||||
it('should throw an error if the file rename operation fails', async () => {
|
||||
const artist = 'Artist';
|
||||
const title = 'Title';
|
||||
const filePath = normalizeToForwardSlash('/path/to/file.mp3');
|
||||
const newFilePath = normalizeToForwardSlash('/path/to/Artist - Title.mp3');
|
||||
const renameError = new Error('Rename failed');
|
||||
|
||||
generateUniqueFilenameStub.resolves(newFilePath);
|
||||
fsStub.rename.rejects(renameError);
|
||||
|
||||
try {
|
||||
await renameFile(artist, title, filePath);
|
||||
throw new Error('Test failed - expected error not thrown');
|
||||
} catch (error) {
|
||||
expect(error).to.equal(renameError);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
75
test/utils/retryAxios.test.js
Normal file
75
test/utils/retryAxios.test.js
Normal file
@@ -0,0 +1,75 @@
|
||||
import { expect } from 'chai';
|
||||
import nock from 'nock';
|
||||
import sinon from 'sinon';
|
||||
import esmock from 'esmock';
|
||||
|
||||
describe('retryAxios', () => {
|
||||
let axiosInstance, axios, axiosRetry;
|
||||
|
||||
beforeEach(async () => {
|
||||
axios = {
|
||||
create: sinon.stub().returnsThis(),
|
||||
interceptors: {
|
||||
response: {
|
||||
use: sinon.stub()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
axiosRetry = sinon.stub();
|
||||
|
||||
axiosInstance = await esmock('../../src/utils/retryAxios.js', {
|
||||
'axios': axios,
|
||||
'axios-retry': axiosRetry
|
||||
});
|
||||
});
|
||||
|
||||
it('should create an axios instance and configure retry policy', async () => {
|
||||
expect(axios.create.calledOnce).to.be.true;
|
||||
expect(axiosRetry.calledOnce).to.be.true;
|
||||
|
||||
const [instance, config] = axiosRetry.firstCall.args;
|
||||
expect(instance).to.equal(axiosInstance);
|
||||
expect(config.retries).to.equal(3);
|
||||
expect(config.retryDelay(1)).to.equal(2000);
|
||||
expect(config.retryDelay(2)).to.equal(4000);
|
||||
expect(config.retryCondition({ response: { status: 429 }})).to.be.true;
|
||||
expect(config.retryCondition({ response: { status: 500 }})).to.be.true;
|
||||
expect(config.retryCondition({ response: { status: 400 }})).to.be.false;
|
||||
});
|
||||
|
||||
it('should retry 3 times before failing for 500 status code', async () => {
|
||||
nock('https://api.example.com')
|
||||
.get('/resource')
|
||||
.reply(500)
|
||||
.persist();
|
||||
|
||||
let error;
|
||||
try {
|
||||
await axiosInstance.get('https://api.example.com/resource');
|
||||
} catch (err) {
|
||||
error = err;
|
||||
}
|
||||
expect(error).to.exist;
|
||||
|
||||
nock.cleanAll();
|
||||
});
|
||||
|
||||
it('should not retry for 400 status code', async () => {
|
||||
nock('https://api.example.com')
|
||||
.get('/resource')
|
||||
.reply(400);
|
||||
|
||||
let error;
|
||||
try {
|
||||
await axiosInstance.get('https://api.example.com/resource');
|
||||
} catch (err) {
|
||||
error = err;
|
||||
}
|
||||
|
||||
expect(error).to.exist;
|
||||
|
||||
nock.cleanAll();
|
||||
});
|
||||
});
|
||||
|
||||
78
test/utils/validateAudioFiles.test.js
Normal file
78
test/utils/validateAudioFiles.test.js
Normal file
@@ -0,0 +1,78 @@
|
||||
import { expect } from 'chai';
|
||||
import sinon from 'sinon';
|
||||
import esmock from 'esmock';
|
||||
|
||||
describe('validateAudioFile', () => {
|
||||
let validateAudioFile, fsStub, mimeStub;
|
||||
|
||||
beforeEach(async () => {
|
||||
fsStub = {
|
||||
lstat: sinon.stub()
|
||||
};
|
||||
|
||||
mimeStub = {
|
||||
lookup: sinon.stub()
|
||||
};
|
||||
|
||||
validateAudioFile = await esmock('../../src/utils/validateAudioFiles.js', {
|
||||
'fs/promises': fsStub,
|
||||
'mime-types': mimeStub
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
esmock.purge(validateAudioFile);
|
||||
sinon.restore();
|
||||
});
|
||||
|
||||
it('should return null and log an error if the path is not a file', async () => {
|
||||
const filePath = '/path/to/directory';
|
||||
const consoleErrorStub = sinon.stub(console, 'error');
|
||||
|
||||
fsStub.lstat.resolves({ isFile: () => false });
|
||||
|
||||
const result = await validateAudioFile(filePath);
|
||||
expect(result).to.be.null;
|
||||
expect(consoleErrorStub.calledWith(`The path ${filePath} is not a file and is ignored.`)).to.be.true;
|
||||
|
||||
consoleErrorStub.restore();
|
||||
});
|
||||
|
||||
it('should return null and log an error if the file is not a recognized audio file type', async () => {
|
||||
const filePath = '/path/to/file.txt';
|
||||
const consoleErrorStub = sinon.stub(console, 'error');
|
||||
|
||||
fsStub.lstat.resolves({ isFile: () => true });
|
||||
mimeStub.lookup.returns('text/plain');
|
||||
|
||||
const result = await validateAudioFile(filePath);
|
||||
expect(result).to.be.null;
|
||||
expect(consoleErrorStub.calledWith(`File ${filePath} is not an audio file and is ignored.`)).to.be.true;
|
||||
|
||||
consoleErrorStub.restore();
|
||||
});
|
||||
|
||||
it('should return the file path if the file is a recognized audio file type', async () => {
|
||||
const filePath = '/path/to/file.mp3';
|
||||
|
||||
fsStub.lstat.resolves({ isFile: () => true });
|
||||
mimeStub.lookup.returns('audio/mpeg');
|
||||
|
||||
const result = await validateAudioFile(filePath);
|
||||
expect(result).to.equal(filePath);
|
||||
});
|
||||
|
||||
it('should return null and log an error if an exception occurs during validation', async () => {
|
||||
const filePath = '/path/to/file.mp3';
|
||||
const error = new Error('Test Error');
|
||||
const consoleErrorStub = sinon.stub(console, 'error');
|
||||
|
||||
fsStub.lstat.rejects(error);
|
||||
|
||||
const result = await validateAudioFile(filePath);
|
||||
expect(result).to.be.null;
|
||||
expect(consoleErrorStub.calledWith(`Error validating file ${filePath}: ${error}`)).to.be.true;
|
||||
|
||||
consoleErrorStub.restore();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user