mirror of
https://github.com/xtrll/MusicMetaFinder.git
synced 2026-04-17 15:53:29 +02:00
test(api): add tests for API functions in api folder
This commit is contained in:
113
test/api/metadata/coverArtArchiveApi.test.js
Normal file
113
test/api/metadata/coverArtArchiveApi.test.js
Normal file
@@ -0,0 +1,113 @@
|
||||
import { expect } from 'chai';
|
||||
import sinon from 'sinon';
|
||||
import esmock from 'esmock';
|
||||
|
||||
describe('getAlbumArt', () => {
|
||||
let axiosRetryStub;
|
||||
let handleErrorStub;
|
||||
let getAlbumArt;
|
||||
|
||||
beforeEach(async () => {
|
||||
axiosRetryStub = {
|
||||
get: sinon.stub()
|
||||
};
|
||||
handleErrorStub = sinon.stub();
|
||||
|
||||
// Mocking the coverArtArchiveApi and its dependencies
|
||||
const module = await esmock('../../../src/api/metadata/coverArtArchiveApi.js', {
|
||||
'../../../src/utils/retryAxios.js': {
|
||||
default: axiosRetryStub
|
||||
},
|
||||
'../../../src/errors/generalApiErrorHandler.js': {
|
||||
default: handleErrorStub
|
||||
}
|
||||
});
|
||||
|
||||
getAlbumArt = module.default;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
sinon.restore(); // Restore the original state of sinon stubs
|
||||
esmock.purge(); // Clean up any esmocked modules
|
||||
});
|
||||
|
||||
it('should retrieve album art URL for a given album ID (success case)', async () => {
|
||||
const albumId = 'mockAlbumId';
|
||||
const responseUrl = 'http://coverartarchive.org/mockAlbumId/front.jpg';
|
||||
axiosRetryStub.get.resolves({
|
||||
status: 200,
|
||||
request: { responseURL: responseUrl }
|
||||
});
|
||||
|
||||
const result = await getAlbumArt(albumId);
|
||||
|
||||
expect(result).to.equal(responseUrl);
|
||||
expect(axiosRetryStub.get.callCount).to.equal(1);
|
||||
expect(axiosRetryStub.get.firstCall.args[0]).to.equal(`http://coverartarchive.org/release/${albumId}/front`);
|
||||
});
|
||||
|
||||
it('should retrieve album art URL from redirect', async () => {
|
||||
const albumId = 'mockAlbumId';
|
||||
const redirectUrl = 'http://someotherurl.com/front.jpg';
|
||||
axiosRetryStub.get.resolves({
|
||||
status: 307,
|
||||
headers: { location: redirectUrl }
|
||||
});
|
||||
|
||||
const result = await getAlbumArt(albumId);
|
||||
|
||||
expect(result).to.equal(redirectUrl);
|
||||
expect(axiosRetryStub.get.callCount).to.equal(1);
|
||||
expect(axiosRetryStub.get.firstCall.args[0]).to.equal(`http://coverartarchive.org/release/${albumId}/front`);
|
||||
});
|
||||
|
||||
it('should handle 307 redirect error', async () => {
|
||||
const albumId = 'mockAlbumId';
|
||||
const redirectUrl = 'http://redirecturl.com/front.jpg';
|
||||
const error = new Error('Request failed');
|
||||
error.response = {
|
||||
status: 307,
|
||||
headers: { location: redirectUrl }
|
||||
};
|
||||
axiosRetryStub.get.rejects(error);
|
||||
|
||||
const result = await getAlbumArt(albumId);
|
||||
|
||||
expect(result).to.equal(redirectUrl);
|
||||
expect(axiosRetryStub.get.callCount).to.equal(1);
|
||||
expect(axiosRetryStub.get.firstCall.args[0]).to.equal(`http://coverartarchive.org/release/${albumId}/front`);
|
||||
});
|
||||
|
||||
it('should return null for 404 error', async () => {
|
||||
const albumId = 'mockAlbumId';
|
||||
const error = new Error('Not Found');
|
||||
error.response = {
|
||||
status: 404
|
||||
};
|
||||
axiosRetryStub.get.rejects(error);
|
||||
|
||||
const result = await getAlbumArt(albumId);
|
||||
|
||||
expect(result).to.be.null;
|
||||
expect(axiosRetryStub.get.callCount).to.equal(1);
|
||||
expect(axiosRetryStub.get.firstCall.args[0]).to.equal(`http://coverartarchive.org/release/${albumId}/front`);
|
||||
});
|
||||
|
||||
it('should return null and handle general errors', async () => {
|
||||
const albumId = 'mockAlbumId';
|
||||
const errorMessage = 'API responded with an error';
|
||||
const error = new Error('Request failed');
|
||||
error.response = {}; // Ensure error.response is an object
|
||||
axiosRetryStub.get.rejects(error);
|
||||
handleErrorStub.returns(errorMessage);
|
||||
|
||||
const result = await getAlbumArt(albumId);
|
||||
|
||||
expect(result).to.be.null;
|
||||
expect(handleErrorStub.callCount).to.equal(1);
|
||||
expect(handleErrorStub.firstCall.args[0]).to.equal(error);
|
||||
expect(axiosRetryStub.get.callCount).to.equal(1);
|
||||
expect(axiosRetryStub.get.firstCall.args[0]).to.equal(`http://coverartarchive.org/release/${albumId}/front`);
|
||||
});
|
||||
});
|
||||
|
||||
82
test/api/metadata/lyricOvhApi.test.js
Normal file
82
test/api/metadata/lyricOvhApi.test.js
Normal file
@@ -0,0 +1,82 @@
|
||||
import { expect } from 'chai';
|
||||
import sinon from 'sinon';
|
||||
import esmock from 'esmock';
|
||||
|
||||
describe('getLyrics', () => {
|
||||
let axiosRetryStub;
|
||||
let handleErrorStub;
|
||||
let getLyrics;
|
||||
|
||||
beforeEach(async () => {
|
||||
axiosRetryStub = {
|
||||
get: sinon.stub(),
|
||||
};
|
||||
handleErrorStub = sinon.stub();
|
||||
|
||||
// Mocking the lyricOvhApi and its dependencies
|
||||
const module = await esmock('../../../src/api/metadata/lyricOvhApi.js', {
|
||||
'../../../src/utils/retryAxios.js': {
|
||||
default: axiosRetryStub,
|
||||
},
|
||||
'../../../src/errors/generalApiErrorHandler.js': {
|
||||
default: handleErrorStub,
|
||||
},
|
||||
});
|
||||
|
||||
getLyrics = module.default;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
sinon.restore(); // Restore the original state of sinon stubs
|
||||
esmock.purge(); // Clean up any esmocked modules
|
||||
});
|
||||
|
||||
it('should fetch lyrics for a specific song successfully', async () => {
|
||||
const artist = 'mockArtist';
|
||||
const title = 'mockTitle';
|
||||
const lyrics = 'These are the mock lyrics';
|
||||
axiosRetryStub.get.resolves({
|
||||
status: 200,
|
||||
data: { lyrics }
|
||||
});
|
||||
|
||||
const result = await getLyrics(artist, title);
|
||||
|
||||
expect(result).to.equal(lyrics);
|
||||
expect(axiosRetryStub.get.callCount).to.equal(1);
|
||||
expect(axiosRetryStub.get.firstCall.args[0]).to.equal(`https://api.lyrics.ovh/v1/${encodeURIComponent(artist)}/${encodeURIComponent(title)}`);
|
||||
});
|
||||
|
||||
it('should return null if lyrics are not found (404 error)', async () => {
|
||||
const artist = 'mockArtist';
|
||||
const title = 'mockTitle';
|
||||
const error = new Error('Not Found');
|
||||
error.response = { status: 404 };
|
||||
axiosRetryStub.get.rejects(error);
|
||||
|
||||
const result = await getLyrics(artist, title);
|
||||
|
||||
expect(result).to.be.null;
|
||||
expect(axiosRetryStub.get.callCount).to.equal(1);
|
||||
expect(axiosRetryStub.get.firstCall.args[0]).to.equal(`https://api.lyrics.ovh/v1/${encodeURIComponent(artist)}/${encodeURIComponent(title)}`);
|
||||
});
|
||||
|
||||
it('should handle general errors and return null', async () => {
|
||||
const artist = 'mockArtist';
|
||||
const title = 'mockTitle';
|
||||
const errorMessage = 'API responded with an error';
|
||||
const error = new Error('Request failed');
|
||||
error.response = {}; // Ensure error.response is an object
|
||||
axiosRetryStub.get.rejects(error);
|
||||
handleErrorStub.returns(errorMessage);
|
||||
|
||||
const result = await getLyrics(artist, title);
|
||||
|
||||
expect(result).to.be.null;
|
||||
expect(handleErrorStub.callCount).to.equal(1);
|
||||
expect(handleErrorStub.firstCall.args[0]).to.equal(error);
|
||||
expect(axiosRetryStub.get.callCount).to.equal(1);
|
||||
expect(axiosRetryStub.get.firstCall.args[0]).to.equal(`https://api.lyrics.ovh/v1/${encodeURIComponent(artist)}/${encodeURIComponent(title)}`);
|
||||
});
|
||||
});
|
||||
|
||||
84
test/api/metadata/musicBrainzApi.test.js
Normal file
84
test/api/metadata/musicBrainzApi.test.js
Normal file
@@ -0,0 +1,84 @@
|
||||
import { expect } from 'chai';
|
||||
import sinon from 'sinon';
|
||||
import esmock from 'esmock';
|
||||
|
||||
describe('getMetadata', () => {
|
||||
let axiosRetryStub;
|
||||
let handleErrorStub;
|
||||
let getMetadata;
|
||||
|
||||
beforeEach(async () => {
|
||||
axiosRetryStub = {
|
||||
get: sinon.stub()
|
||||
};
|
||||
handleErrorStub = sinon.stub();
|
||||
|
||||
// Mocking the musicBrainzApi and its dependencies
|
||||
const module = await esmock('../../../src/api/metadata/musicBrainzApi.js', {
|
||||
'../../../src/utils/retryAxios.js': {
|
||||
default: axiosRetryStub,
|
||||
},
|
||||
'../../../src/errors/generalApiErrorHandler.js': {
|
||||
default: handleErrorStub,
|
||||
},
|
||||
});
|
||||
|
||||
getMetadata = module.default;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
sinon.restore(); // Restore the original state of sinon stubs
|
||||
esmock.purge(); // Clean up any esmocked modules
|
||||
});
|
||||
|
||||
it('should fetch metadata for a given recording ID successfully', async () => {
|
||||
const recordingId = 'mockRecordingId';
|
||||
const metadata = { title: 'Mock Title', artists: [], releases: [] };
|
||||
axiosRetryStub.get.resolves({
|
||||
status: 200,
|
||||
data: metadata
|
||||
});
|
||||
|
||||
const result = await getMetadata(recordingId);
|
||||
|
||||
expect(result).to.deep.equal(metadata);
|
||||
expect(axiosRetryStub.get.callCount).to.equal(1);
|
||||
expect(axiosRetryStub.get.firstCall.args[0]).to.equal(`https://musicbrainz.org/ws/2/recording/${recordingId}?fmt=json&inc=artists+releases`);
|
||||
});
|
||||
|
||||
it('should return null if metadata is not found (404 error)', async () => {
|
||||
const recordingId = 'mockRecordingId';
|
||||
const error = new Error('Not Found');
|
||||
error.response = { status: 404 };
|
||||
axiosRetryStub.get.rejects(error);
|
||||
|
||||
const result = await getMetadata(recordingId);
|
||||
|
||||
expect(result).to.be.null;
|
||||
expect(axiosRetryStub.get.callCount).to.equal(1);
|
||||
expect(axiosRetryStub.get.firstCall.args[0]).to.equal(`https://musicbrainz.org/ws/2/recording/${recordingId}?fmt=json&inc=artists+releases`);
|
||||
});
|
||||
|
||||
it('should handle general errors and throw an error', async () => {
|
||||
const recordingId = 'mockRecordingId';
|
||||
const errorMessage = 'API responded with an error';
|
||||
const error = new Error('Request failed');
|
||||
error.response = {}; // Ensure error.response is an object
|
||||
axiosRetryStub.get.rejects(error);
|
||||
handleErrorStub.returns(errorMessage);
|
||||
|
||||
try {
|
||||
await getMetadata(recordingId);
|
||||
// We should not reach here
|
||||
expect.fail('Expected getMetadata to throw');
|
||||
} catch (err) {
|
||||
expect(err.message).to.equal(errorMessage);
|
||||
expect(handleErrorStub.callCount).to.equal(1);
|
||||
expect(handleErrorStub.firstCall.args[0]).to.equal(error);
|
||||
}
|
||||
|
||||
expect(axiosRetryStub.get.callCount).to.equal(1);
|
||||
expect(axiosRetryStub.get.firstCall.args[0]).to.equal(`https://musicbrainz.org/ws/2/recording/${recordingId}?fmt=json&inc=artists+releases`);
|
||||
});
|
||||
});
|
||||
|
||||
84
test/api/metadata/spotifyApi.test.js
Normal file
84
test/api/metadata/spotifyApi.test.js
Normal file
@@ -0,0 +1,84 @@
|
||||
import { expect } from 'chai';
|
||||
import sinon from 'sinon';
|
||||
import esmock from 'esmock';
|
||||
|
||||
describe('getMetadata', () => {
|
||||
let axiosRetryStub;
|
||||
let handleErrorStub;
|
||||
let getMetadata;
|
||||
|
||||
beforeEach(async () => {
|
||||
axiosRetryStub = {
|
||||
get: sinon.stub()
|
||||
};
|
||||
handleErrorStub = sinon.stub();
|
||||
|
||||
// Mocking the spotifyApi and its dependencies
|
||||
const module = await esmock('../../../src/api/metadata/spotifyApi.js', {
|
||||
'../../../src/utils/retryAxios.js': {
|
||||
default: axiosRetryStub,
|
||||
},
|
||||
'../../../src/errors/generalApiErrorHandler.js': {
|
||||
default: handleErrorStub,
|
||||
},
|
||||
});
|
||||
|
||||
getMetadata = module.default;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
sinon.restore(); // Restore the original state of sinon stubs
|
||||
esmock.purge(); // Clean up any esmocked modules
|
||||
});
|
||||
|
||||
it('should fetch metadata for a given track ID successfully', async () => {
|
||||
const trackId = 'mockTrackId';
|
||||
const accessToken = 'mockAccessToken';
|
||||
const metadata = { name: 'Mock Song', artists: [], album: {} };
|
||||
axiosRetryStub.get.resolves({
|
||||
status: 200,
|
||||
data: metadata
|
||||
});
|
||||
|
||||
const result = await getMetadata(trackId, accessToken);
|
||||
|
||||
expect(result).to.deep.equal(metadata);
|
||||
expect(axiosRetryStub.get.callCount).to.equal(1);
|
||||
expect(axiosRetryStub.get.firstCall.args[0]).to.equal(`https://api.spotify.com/v1/tracks/${trackId}`);
|
||||
expect(axiosRetryStub.get.firstCall.args[1]).to.deep.include({
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle errors and throw an error message', async () => {
|
||||
const trackId = 'mockTrackId';
|
||||
const accessToken = 'mockAccessToken';
|
||||
const errorMessage = 'API responded with an error';
|
||||
const error = new Error('Request failed');
|
||||
error.response = {}; // Ensure error.response is an object
|
||||
axiosRetryStub.get.rejects(error);
|
||||
handleErrorStub.returns(errorMessage);
|
||||
|
||||
try {
|
||||
await getMetadata(trackId, accessToken);
|
||||
// We should not reach here
|
||||
expect.fail('Expected getMetadata to throw');
|
||||
} catch (err) {
|
||||
expect(err.message).to.equal(errorMessage);
|
||||
expect(handleErrorStub.callCount).to.equal(1);
|
||||
expect(handleErrorStub.firstCall.args[0]).to.equal(error);
|
||||
expect(handleErrorStub.firstCall.args[1]).to.equal(trackId);
|
||||
}
|
||||
|
||||
expect(axiosRetryStub.get.callCount).to.equal(1);
|
||||
expect(axiosRetryStub.get.firstCall.args[0]).to.equal(`https://api.spotify.com/v1/tracks/${trackId}`);
|
||||
expect(axiosRetryStub.get.firstCall.args[1]).to.deep.include({
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
125
test/api/recognition/acoustidApi.test.js
Normal file
125
test/api/recognition/acoustidApi.test.js
Normal file
@@ -0,0 +1,125 @@
|
||||
import { expect } from 'chai';
|
||||
import sinon from 'sinon';
|
||||
import esmock from 'esmock';
|
||||
|
||||
describe('acoustIdAudioRecognition', () => {
|
||||
let fpcalcStub;
|
||||
let axiosRetryStub;
|
||||
let handleErrorStub;
|
||||
let acoustIdAudioRecognition;
|
||||
|
||||
beforeEach(async () => {
|
||||
fpcalcStub = sinon.stub();
|
||||
axiosRetryStub = {
|
||||
post: sinon.stub()
|
||||
};
|
||||
handleErrorStub = sinon.stub();
|
||||
|
||||
// Mocking the acoustidApi and its dependencies
|
||||
const module = await esmock('../../../src/api/recognition/acoustidApi.js', {
|
||||
'fpcalc': fpcalcStub,
|
||||
'../../../src/utils/retryAxios.js': {
|
||||
default: axiosRetryStub,
|
||||
},
|
||||
'../../../src/errors/acoustidApiErrorHandler.js': {
|
||||
default: handleErrorStub,
|
||||
},
|
||||
});
|
||||
|
||||
acoustIdAudioRecognition = module.default;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
sinon.restore(); // Restore the original state of sinon stubs
|
||||
esmock.purge(); // Clean up any esmocked modules
|
||||
});
|
||||
|
||||
it('should successfully recognize audio file', async () => {
|
||||
const filePath = 'mockFilePath.mp3';
|
||||
const mockDuration = 200;
|
||||
const mockFingerprint = 'mockFingerprint';
|
||||
const mockRecordingId = 'mockRecordingId';
|
||||
|
||||
fpcalcStub.callsFake((path, callback) => {
|
||||
expect(path).to.equal(filePath);
|
||||
callback(null, { duration: mockDuration, fingerprint: mockFingerprint });
|
||||
});
|
||||
|
||||
axiosRetryStub.post.resolves({
|
||||
status: 200,
|
||||
data: {
|
||||
status: 'ok',
|
||||
results: [{
|
||||
recordings: [{
|
||||
id: mockRecordingId
|
||||
}]
|
||||
}]
|
||||
}
|
||||
});
|
||||
|
||||
const result = await acoustIdAudioRecognition(filePath);
|
||||
|
||||
expect(result).to.equal(mockRecordingId);
|
||||
expect(fpcalcStub.callCount).to.equal(1);
|
||||
expect(axiosRetryStub.post.callCount).to.equal(1);
|
||||
expect(axiosRetryStub.post.firstCall.args[0]).to.equal('https://api.acoustid.org/v2/lookup');
|
||||
});
|
||||
|
||||
it('should return null if song could not be recognized', async () => {
|
||||
const filePath = 'mockFilePath.mp3';
|
||||
const mockDuration = 200;
|
||||
const mockFingerprint = 'mockFingerprint';
|
||||
|
||||
fpcalcStub.callsFake((path, callback) => {
|
||||
expect(path).to.equal(filePath);
|
||||
callback(null, { duration: mockDuration, fingerprint: mockFingerprint });
|
||||
});
|
||||
|
||||
axiosRetryStub.post.resolves({
|
||||
status: 200,
|
||||
data: {
|
||||
status: 'ok',
|
||||
results: []
|
||||
}
|
||||
});
|
||||
|
||||
const result = await acoustIdAudioRecognition(filePath);
|
||||
|
||||
expect(result).to.be.null;
|
||||
expect(fpcalcStub.callCount).to.equal(1);
|
||||
expect(axiosRetryStub.post.callCount).to.equal(1);
|
||||
expect(axiosRetryStub.post.firstCall.args[0]).to.equal('https://api.acoustid.org/v2/lookup');
|
||||
});
|
||||
|
||||
it('should handle errors and throw an error message', async () => {
|
||||
const filePath = 'mockFilePath.mp3';
|
||||
const mockDuration = 200;
|
||||
const mockFingerprint = 'mockFingerprint';
|
||||
const errorMessage = 'API error occurred';
|
||||
const error = new Error('Request failed');
|
||||
error.response = {}; // Ensure error.response is an object
|
||||
|
||||
fpcalcStub.callsFake((path, callback) => {
|
||||
expect(path).to.equal(filePath);
|
||||
callback(null, { duration: mockDuration, fingerprint: mockFingerprint });
|
||||
});
|
||||
|
||||
axiosRetryStub.post.rejects(error);
|
||||
handleErrorStub.returns(errorMessage);
|
||||
|
||||
try {
|
||||
await acoustIdAudioRecognition(filePath);
|
||||
// We should not reach here
|
||||
expect.fail('Expected acoustdIdAudioRecognition to throw');
|
||||
} catch (err) {
|
||||
expect(err.message).to.equal(errorMessage);
|
||||
expect(handleErrorStub.callCount).to.equal(1);
|
||||
expect(handleErrorStub.firstCall.args[0]).to.equal(error);
|
||||
expect(handleErrorStub.firstCall.args[1]).to.equal(filePath);
|
||||
}
|
||||
|
||||
expect(fpcalcStub.callCount).to.equal(1);
|
||||
expect(axiosRetryStub.post.callCount).to.equal(1);
|
||||
});
|
||||
});
|
||||
|
||||
177
test/api/recognition/auddApi.test.js
Normal file
177
test/api/recognition/auddApi.test.js
Normal file
@@ -0,0 +1,177 @@
|
||||
import { expect } from 'chai';
|
||||
import sinon from 'sinon';
|
||||
import esmock from 'esmock';
|
||||
|
||||
describe('auddAudioRecognition', function() {
|
||||
let fsStub;
|
||||
let axiosRetryStub;
|
||||
let handleErrorStub;
|
||||
let auddAudioRecognition;
|
||||
let bufferStub;
|
||||
|
||||
const filePath = 'mockFilePath.mp3';
|
||||
const mockAudioData = 'mockAudioData';
|
||||
const mockBase64Audio = 'mockBase64Audio';
|
||||
let originalBufferFrom, originalBufferToString;
|
||||
|
||||
before(function() {
|
||||
console.log("Setting process environment variables");
|
||||
process.env.AUDD_API_TOKEN = 'mockToken';
|
||||
});
|
||||
|
||||
const setupStubs = () => {
|
||||
try {
|
||||
// Stubbing fs.readFileSync
|
||||
fsStub.readFileSync.withArgs(filePath).returns(mockAudioData);
|
||||
|
||||
// Stubbing Buffer.from
|
||||
originalBufferFrom = Buffer.from;
|
||||
bufferStub = sinon.stub(Buffer, 'from').callsFake((data) => {
|
||||
const buffer = originalBufferFrom(data);
|
||||
if (data === mockAudioData) {
|
||||
if (!originalBufferToString) {
|
||||
originalBufferToString = buffer.toString;
|
||||
}
|
||||
sinon.stub(buffer, 'toString').callsFake((encoding) => {
|
||||
if (encoding === 'base64') {
|
||||
return mockBase64Audio;
|
||||
}
|
||||
return originalBufferToString.call(buffer, encoding);
|
||||
});
|
||||
}
|
||||
return buffer;
|
||||
});
|
||||
} catch (e) {
|
||||
console.error('Error during setupStubs:', e);
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
|
||||
beforeEach(async function() {
|
||||
fsStub = { readFileSync: sinon.stub() };
|
||||
axiosRetryStub = { post: sinon.stub() };
|
||||
handleErrorStub = sinon.stub();
|
||||
|
||||
// Mocking the auddApi and its dependencies
|
||||
const module = await esmock('../../../src/api/recognition/auddApi.js', {
|
||||
'fs': fsStub,
|
||||
'../../../src/utils/retryAxios.js': { default: axiosRetryStub },
|
||||
'../../../src/errors/generalApiErrorHandler.js': { default: handleErrorStub },
|
||||
});
|
||||
|
||||
auddAudioRecognition = module.default;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
sinon.restore();
|
||||
if (bufferStub && bufferStub.restore) bufferStub.restore(); // Restore the Buffer.from stub safely
|
||||
esmock.purge();
|
||||
});
|
||||
|
||||
it('should successfully recognize the audio file', async function() {
|
||||
setupStubs();
|
||||
|
||||
const mockMetadata = { result: 'mock result' };
|
||||
|
||||
axiosRetryStub.post.resolves({
|
||||
status: 200,
|
||||
data: mockMetadata,
|
||||
});
|
||||
|
||||
try {
|
||||
const result = await auddAudioRecognition(filePath);
|
||||
|
||||
expect(result.data).to.deep.equal(mockMetadata);
|
||||
expect(result.filePath).to.equal(filePath);
|
||||
expect(fsStub.readFileSync.callCount).to.equal(1);
|
||||
expect(axiosRetryStub.post.callCount).to.equal(1);
|
||||
|
||||
// Correctly compare the URL of the request
|
||||
expect(axiosRetryStub.post.firstCall.args[0]).to.equal('https://api.audd.io/');
|
||||
|
||||
// Correctly compare the body
|
||||
const body = axiosRetryStub.post.firstCall.args[1];
|
||||
expect(body).to.be.an.instanceof(URLSearchParams);
|
||||
expect(body.get('api_token')).to.equal(process.env.AUDD_API_TOKEN);
|
||||
expect(body.get('audio')).to.equal(mockBase64Audio);
|
||||
expect(body.get('return')).to.equal('spotify');
|
||||
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should handle no data received from API', async function() {
|
||||
setupStubs();
|
||||
|
||||
axiosRetryStub.post.resolves({
|
||||
status: 200,
|
||||
data: null,
|
||||
});
|
||||
|
||||
handleErrorStub.callsFake((error) => {
|
||||
if (error.message.includes('No data received from Audd API')) {
|
||||
return 'No data received from Audd API';
|
||||
}
|
||||
return error.message;
|
||||
});
|
||||
|
||||
try {
|
||||
await auddAudioRecognition(filePath);
|
||||
expect.fail('Expected auddAudioRecognition to throw "No data received from Audd API"');
|
||||
} catch (err) {
|
||||
expect(err.message).to.equal('No data received from Audd API');
|
||||
}
|
||||
|
||||
expect(fsStub.readFileSync.callCount).to.equal(1);
|
||||
expect(axiosRetryStub.post.callCount).to.equal(1);
|
||||
});
|
||||
|
||||
it('should handle API errors correctly', async function() {
|
||||
setupStubs();
|
||||
|
||||
const apiError = { message: 'Some API error' };
|
||||
axiosRetryStub.post.resolves({
|
||||
status: 200,
|
||||
data: { error: apiError },
|
||||
});
|
||||
|
||||
handleErrorStub.callsFake((error) => {
|
||||
return `Audd API Error: ${JSON.stringify(apiError)}`;
|
||||
});
|
||||
|
||||
try {
|
||||
await auddAudioRecognition(filePath);
|
||||
expect.fail('Expected auddAudioRecognition to throw "Audd API Error: Some API error"');
|
||||
} catch (err) {
|
||||
expect(err.message).to.equal(`Audd API Error: ${JSON.stringify(apiError)}`);
|
||||
}
|
||||
|
||||
expect(fsStub.readFileSync.callCount).to.equal(1);
|
||||
expect(axiosRetryStub.post.callCount).to.equal(1);
|
||||
});
|
||||
|
||||
it('should handle general errors correctly', async function() {
|
||||
setupStubs();
|
||||
|
||||
const generalError = new Error('Network error');
|
||||
axiosRetryStub.post.rejects(generalError);
|
||||
|
||||
handleErrorStub.returns('Handled network error');
|
||||
|
||||
try {
|
||||
await auddAudioRecognition(filePath);
|
||||
expect.fail('Expected auddAudioRecognition to throw "Handled network error"');
|
||||
} catch (err) {
|
||||
expect(err.message).to.equal('Handled network error');
|
||||
expect(handleErrorStub.callCount).to.equal(1);
|
||||
expect(handleErrorStub.firstCall.args[0]).to.equal(generalError);
|
||||
expect(handleErrorStub.firstCall.args[1]).to.equal(filePath);
|
||||
}
|
||||
|
||||
expect(fsStub.readFileSync.callCount).to.equal(1);
|
||||
expect(axiosRetryStub.post.callCount).to.equal(1);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
73
test/api/spotifyAuthApi.test.js
Normal file
73
test/api/spotifyAuthApi.test.js
Normal file
@@ -0,0 +1,73 @@
|
||||
import { expect } from 'chai';
|
||||
import sinon from 'sinon';
|
||||
import esmock from 'esmock';
|
||||
|
||||
describe('getSpotifyAccessToken', () => {
|
||||
let axiosRetryStub;
|
||||
let handleErrorStub;
|
||||
let getSpotifyAccessToken;
|
||||
|
||||
beforeEach(async () => {
|
||||
axiosRetryStub = sinon.stub();
|
||||
handleErrorStub = sinon.stub();
|
||||
|
||||
// Mocking the spotifyAuthApi and its dependencies
|
||||
const module = await esmock('../../src/api/spotifyAuthApi.js', {
|
||||
'../../src/utils/retryAxios.js': axiosRetryStub,
|
||||
'../../src/errors/generalApiErrorHandler.js': {
|
||||
default: handleErrorStub,
|
||||
},
|
||||
'querystring': {
|
||||
stringify: sinon.stub().returns('grant_type=client_credentials'),
|
||||
},
|
||||
});
|
||||
|
||||
getSpotifyAccessToken = module.default;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
sinon.restore(); // Restore the original state of sinon stubs
|
||||
esmock.purge(); // Clean up any esmocked modules
|
||||
});
|
||||
|
||||
it('should retrieve the Spotify access token', async () => {
|
||||
process.env.client_id = 'mockClientId';
|
||||
process.env.client_secret = 'mockClientSecret';
|
||||
|
||||
const token = 'mocked_access_token';
|
||||
const response = { status: 200, data: { access_token: token } };
|
||||
axiosRetryStub.resolves(response);
|
||||
|
||||
const result = await getSpotifyAccessToken();
|
||||
|
||||
expect(result).to.equal(token);
|
||||
expect(axiosRetryStub.callCount).to.equal(1);
|
||||
expect(axiosRetryStub.firstCall.args[0]).to.include({
|
||||
url: 'https://accounts.spotify.com/api/token',
|
||||
});
|
||||
expect(axiosRetryStub.firstCall.args[0].headers.Authorization).to.include('Basic');
|
||||
});
|
||||
|
||||
it('should throw an error if the request fails after retries', async () => {
|
||||
process.env.client_id = 'mockClientId';
|
||||
process.env.client_secret = 'mockClientSecret';
|
||||
|
||||
const errorMessage = 'Handled error message';
|
||||
const error = new Error('Request failed');
|
||||
axiosRetryStub.rejects(error);
|
||||
handleErrorStub.returns(errorMessage);
|
||||
|
||||
try {
|
||||
await getSpotifyAccessToken();
|
||||
// We should not reach here
|
||||
expect.fail('Expected getSpotifyAccessToken to throw');
|
||||
} catch (err) {
|
||||
expect(err.message).to.equal(errorMessage);
|
||||
expect(handleErrorStub.callCount).to.equal(1);
|
||||
expect(handleErrorStub.firstCall.args[0]).to.equal(error);
|
||||
}
|
||||
|
||||
expect(axiosRetryStub.callCount).to.equal(1); // Only one stub call since retry logic is inside `retryAxios.js`
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user