Add tests for download path: LibraryItemController.download, fileUtils.downloadFile, zipHelpers.zipDirectoryPipe

This commit is contained in:
Trevor Renshaw 2026-05-16 10:35:09 -06:00
parent e74dbf5f40
commit def602a30a
3 changed files with 263 additions and 0 deletions

View file

@ -8,6 +8,7 @@ const LibraryItemController = require('../../../server/controllers/LibraryItemCo
const ApiCacheManager = require('../../../server/managers/ApiCacheManager')
const Auth = require('../../../server/Auth')
const Logger = require('../../../server/Logger')
const zipHelpers = require('../../../server/utils/zipHelpers')
describe('LibraryItemController', () => {
/** @type {ApiRouter} */
@ -299,4 +300,95 @@ describe('LibraryItemController', () => {
expect(fakeRes.sendStatus.calledWith(403)).to.be.true
})
})
describe('download', () => {
let req
let res
beforeEach(() => {
req = {
user: { username: 'testUser', canDownload: true },
libraryItem: {
isFile: true,
path: '/audiobooks/hitchhikers-guide.mp3',
relPath: 'hitchhikers-guide.mp3',
media: { title: "The Hitchhiker's Guide To The Galaxy" }
}
}
res = {
setHeader: sinon.spy(),
sendFile: sinon.stub(),
sendStatus: sinon.spy(),
status: sinon.stub().returnsThis(),
send: sinon.spy()
}
})
it('should return 403 when user does not have canDownload permission', async () => {
req.user.canDownload = false
await LibraryItemController.download(req, res)
expect(res.sendStatus.calledWith(403)).to.be.true
expect(res.sendFile.called).to.be.false
})
it('should call res.sendFile for single-file library items', async () => {
res.sendFile.callsFake((filePath, opts, cb) => cb(null))
await LibraryItemController.download(req, res)
expect(res.sendFile.calledOnce).to.be.true
})
it('should pass { dotfiles: "allow" } option to res.sendFile', async () => {
res.sendFile.callsFake((filePath, opts, cb) => cb(null))
await LibraryItemController.download(req, res)
const opts = res.sendFile.firstCall.args[1]
expect(opts).to.deep.equal({ dotfiles: 'allow' })
})
it('should pass the correct file path to res.sendFile', async () => {
res.sendFile.callsFake((filePath, opts, cb) => cb(null))
await LibraryItemController.download(req, res)
expect(res.sendFile.firstCall.args[0]).to.equal('/audiobooks/hitchhikers-guide.mp3')
})
it('should set Content-Disposition attachment header with the filename', async () => {
res.sendFile.callsFake((filePath, opts, cb) => cb(null))
await LibraryItemController.download(req, res)
const dispositionCall = res.setHeader.args.find(([header]) => header === 'Content-Disposition')
expect(dispositionCall).to.exist
expect(dispositionCall[1]).to.include('attachment')
expect(dispositionCall[1]).to.include('hitchhikers-guide.mp3')
})
it('should URL-encode special characters in the Content-Disposition filename', async () => {
req.libraryItem.relPath = 'Book With Spaces & Symbols!.mp3'
res.sendFile.callsFake((filePath, opts, cb) => cb(null))
await LibraryItemController.download(req, res)
const dispositionCall = res.setHeader.args.find(([header]) => header === 'Content-Disposition')
expect(dispositionCall[1]).to.include(encodeURIComponent('Book With Spaces & Symbols!.mp3'))
})
it('should return 500 when res.sendFile calls back with an error', async () => {
res.sendFile.callsFake((filePath, opts, cb) => cb(new Error('File not found')))
await LibraryItemController.download(req, res)
expect(res.status.calledWith(500)).to.be.true
expect(res.send.called).to.be.true
})
it('should call zipDirectoryPipe for multi-file directory items', async () => {
req.libraryItem.isFile = false
const zipStub = sinon.stub(zipHelpers, 'zipDirectoryPipe').resolves()
await LibraryItemController.download(req, res)
expect(zipStub.calledOnce).to.be.true
expect(zipStub.firstCall.args[0]).to.equal(req.libraryItem.path)
expect(zipStub.firstCall.args[1]).to.equal("The Hitchhiker's Guide To The Galaxy.zip")
expect(zipStub.firstCall.args[2]).to.equal(res)
})
it('should pass the response object to zipDirectoryPipe', async () => {
req.libraryItem.isFile = false
const zipStub = sinon.stub(zipHelpers, 'zipDirectoryPipe').resolves()
await LibraryItemController.download(req, res)
expect(zipStub.firstCall.args[2]).to.equal(res)
})
})
})