mirror of
https://github.com/advplyr/audiobookshelf.git
synced 2026-07-07 09:51:37 +00:00
259 lines
8.3 KiB
JavaScript
259 lines
8.3 KiB
JavaScript
const chai = require('chai')
|
|
const sinon = require('sinon')
|
|
|
|
const LibraryScanner = require('../../../server/scanner/LibraryScanner')
|
|
const LibraryScan = require('../../../server/scanner/LibraryScan')
|
|
const LibraryItemScanner = require('../../../server/scanner/LibraryItemScanner')
|
|
const Database = require('../../../server/Database')
|
|
const libraryFilters = require('../../../server/utils/queries/libraryFilters')
|
|
const SocketAuthority = require('../../../server/SocketAuthority')
|
|
const fs = require('../../../server/libs/fsExtra')
|
|
const { ScanResult } = require('../../../server/utils/constants')
|
|
|
|
const expect = chai.expect
|
|
|
|
describe('LibraryScanner placeholder handling', () => {
|
|
let originalSequelize
|
|
|
|
beforeEach(() => {
|
|
originalSequelize = Database.sequelize
|
|
Database.sequelize = {
|
|
models: {
|
|
libraryItem: {
|
|
findAll: () => {},
|
|
getExpandedById: () => {},
|
|
update: () => {},
|
|
findOneExpanded: () => {},
|
|
findOne: () => {}
|
|
}
|
|
}
|
|
}
|
|
})
|
|
|
|
afterEach(() => {
|
|
Database.sequelize = originalSequelize
|
|
sinon.restore()
|
|
})
|
|
|
|
it('skips missing checks for placeholder items during full scans', async () => {
|
|
const library = {
|
|
id: 'library-1',
|
|
name: 'Test Library',
|
|
mediaType: 'book',
|
|
settings: {},
|
|
libraryFolders: [
|
|
{
|
|
id: 'folder-1',
|
|
path: '/library'
|
|
}
|
|
]
|
|
}
|
|
|
|
const libraryScan = new LibraryScan()
|
|
libraryScan.setData(library)
|
|
|
|
const placeholderItem = {
|
|
id: 'item-1',
|
|
path: '/library/Series/Placeholder',
|
|
relPath: 'Series/Placeholder',
|
|
ino: 123,
|
|
isPlaceholder: true,
|
|
isMissing: false,
|
|
libraryFiles: [],
|
|
save: sinon.stub().resolves(),
|
|
changed: sinon.stub()
|
|
}
|
|
|
|
sinon.stub(libraryFilters, 'getFilterData').resolves()
|
|
sinon.stub(LibraryScanner, 'scanFolder').resolves([])
|
|
const findAllStub = sinon.stub(Database.libraryItemModel, 'findAll').resolves([placeholderItem])
|
|
const getExpandedStub = sinon.stub(Database.libraryItemModel, 'getExpandedById').resolves(null)
|
|
const updateStub = sinon.stub(Database.libraryItemModel, 'update').resolves()
|
|
const checkAuthorsStub = sinon.stub(LibraryItemScanner, 'checkAuthorsAndSeriesRemovedFromBooks').resolves()
|
|
|
|
await LibraryScanner.scanLibrary(libraryScan, false)
|
|
|
|
expect(findAllStub.calledOnce).to.be.true
|
|
expect(getExpandedStub.called).to.be.false
|
|
expect(updateStub.called).to.be.false
|
|
expect(checkAuthorsStub.calledOnce).to.be.true
|
|
expect(libraryScan.resultsMissing).to.equal(0)
|
|
})
|
|
|
|
it('promotes placeholders when audio files are detected in folder updates', async () => {
|
|
const library = {
|
|
id: 'library-1',
|
|
name: 'Test Library',
|
|
mediaType: 'book',
|
|
settings: {}
|
|
}
|
|
const folder = {
|
|
id: 'folder-1',
|
|
path: '/library',
|
|
libraryId: library.id
|
|
}
|
|
|
|
const placeholderItem = {
|
|
id: 'item-1',
|
|
path: '/library/Series/Placeholder',
|
|
relPath: 'Series/Placeholder',
|
|
isPlaceholder: true,
|
|
isMissing: true,
|
|
media: { title: 'Placeholder Book' },
|
|
save: sinon.stub().resolves(),
|
|
changed: sinon.stub()
|
|
}
|
|
|
|
sinon.stub(libraryFilters, 'getFilterData').resolves()
|
|
sinon.stub(Database.libraryItemModel, 'findOneExpanded').resolves(placeholderItem)
|
|
sinon.stub(Database.libraryItemModel, 'findOne').resolves(null)
|
|
sinon.stub(fs, 'pathExists').resolves(true)
|
|
const scanLibraryItemStub = sinon.stub(LibraryItemScanner, 'scanLibraryItem').resolves(ScanResult.UPDATED)
|
|
sinon.stub(SocketAuthority, 'libraryItemEmitter')
|
|
|
|
const fileUpdateGroup = {
|
|
'Series/Placeholder': ['track-01.mp3']
|
|
}
|
|
|
|
const results = await LibraryScanner.scanFolderUpdates(library, folder, fileUpdateGroup)
|
|
|
|
expect(placeholderItem.isPlaceholder).to.be.false
|
|
expect(placeholderItem.isMissing).to.be.false
|
|
expect(placeholderItem.save.calledOnce).to.be.true
|
|
expect(scanLibraryItemStub.calledOnce).to.be.true
|
|
expect(results['Series/Placeholder']).to.equal(ScanResult.UPDATED)
|
|
})
|
|
|
|
it('promotes placeholders during full scans when media is present', async () => {
|
|
const library = {
|
|
id: 'library-1',
|
|
name: 'Test Library',
|
|
mediaType: 'book',
|
|
settings: {},
|
|
libraryFolders: [
|
|
{
|
|
id: 'folder-1',
|
|
path: '/library'
|
|
}
|
|
]
|
|
}
|
|
|
|
const libraryScan = new LibraryScan()
|
|
libraryScan.setData(library)
|
|
|
|
const placeholderItem = {
|
|
id: 'item-1',
|
|
path: '/library/Series/Placeholder',
|
|
relPath: 'Series/Placeholder',
|
|
isPlaceholder: true,
|
|
isMissing: true,
|
|
save: sinon.stub().resolves(),
|
|
changed: sinon.stub()
|
|
}
|
|
|
|
const libraryItemData = {
|
|
path: placeholderItem.path,
|
|
audioLibraryFiles: [{ metadata: { ext: '.mp3' } }],
|
|
ebookLibraryFiles: [],
|
|
hasLibraryFileChanges: true,
|
|
hasPathChange: false,
|
|
checkLibraryItemData: sinon.stub().resolves(true)
|
|
}
|
|
|
|
sinon.stub(libraryFilters, 'getFilterData').resolves()
|
|
sinon.stub(LibraryScanner, 'scanFolder').resolves([libraryItemData])
|
|
sinon.stub(Database.libraryItemModel, 'findAll').resolves([placeholderItem])
|
|
const rescanStub = sinon.stub(LibraryItemScanner, 'rescanLibraryItemMedia').resolves({ libraryItem: placeholderItem, wasUpdated: true })
|
|
sinon.stub(LibraryItemScanner, 'checkAuthorsAndSeriesRemovedFromBooks').resolves()
|
|
sinon.stub(SocketAuthority, 'libraryItemsEmitter')
|
|
|
|
await LibraryScanner.scanLibrary(libraryScan, false)
|
|
|
|
expect(placeholderItem.isPlaceholder).to.be.false
|
|
expect(placeholderItem.isMissing).to.be.false
|
|
expect(placeholderItem.save.calledOnce).to.be.true
|
|
expect(rescanStub.calledOnce).to.be.true
|
|
})
|
|
|
|
it('skips placeholder scans on file updates without audio', async () => {
|
|
const library = {
|
|
id: 'library-1',
|
|
name: 'Test Library',
|
|
mediaType: 'book',
|
|
settings: {}
|
|
}
|
|
const folder = {
|
|
id: 'folder-1',
|
|
path: '/library',
|
|
libraryId: library.id
|
|
}
|
|
|
|
const placeholderItem = {
|
|
id: 'item-1',
|
|
path: '/library/Series/Placeholder',
|
|
relPath: 'Series/Placeholder',
|
|
isPlaceholder: true,
|
|
isMissing: false,
|
|
media: { title: 'Placeholder Book' },
|
|
save: sinon.stub().resolves(),
|
|
changed: sinon.stub()
|
|
}
|
|
|
|
sinon.stub(libraryFilters, 'getFilterData').resolves()
|
|
sinon.stub(Database.libraryItemModel, 'findOneExpanded').resolves(placeholderItem)
|
|
sinon.stub(Database.libraryItemModel, 'findOne').resolves(null)
|
|
sinon.stub(fs, 'pathExists').resolves(true)
|
|
const scanLibraryItemStub = sinon.stub(LibraryItemScanner, 'scanLibraryItem').resolves(ScanResult.UPDATED)
|
|
sinon.stub(SocketAuthority, 'libraryItemEmitter')
|
|
|
|
const fileUpdateGroup = {
|
|
'Series/Placeholder': ['cover.jpg']
|
|
}
|
|
|
|
const results = await LibraryScanner.scanFolderUpdates(library, folder, fileUpdateGroup)
|
|
|
|
expect(scanLibraryItemStub.called).to.be.false
|
|
expect(results['Series/Placeholder']).to.equal(ScanResult.NOTHING)
|
|
})
|
|
|
|
it('ignores missing checks for placeholders on file updates when path is gone', async () => {
|
|
const library = {
|
|
id: 'library-1',
|
|
name: 'Test Library',
|
|
mediaType: 'book',
|
|
settings: {}
|
|
}
|
|
const folder = {
|
|
id: 'folder-1',
|
|
path: '/library',
|
|
libraryId: library.id
|
|
}
|
|
|
|
const placeholderItem = {
|
|
id: 'item-1',
|
|
path: '/library/Series/Placeholder',
|
|
relPath: 'Series/Placeholder',
|
|
isPlaceholder: true,
|
|
isMissing: false,
|
|
media: { title: 'Placeholder Book' },
|
|
save: sinon.stub().resolves(),
|
|
changed: sinon.stub()
|
|
}
|
|
|
|
sinon.stub(libraryFilters, 'getFilterData').resolves()
|
|
sinon.stub(Database.libraryItemModel, 'findOneExpanded').resolves(placeholderItem)
|
|
sinon.stub(Database.libraryItemModel, 'findOne').resolves(null)
|
|
sinon.stub(fs, 'pathExists').resolves(false)
|
|
const scanLibraryItemStub = sinon.stub(LibraryItemScanner, 'scanLibraryItem').resolves(ScanResult.UPDATED)
|
|
sinon.stub(SocketAuthority, 'libraryItemEmitter')
|
|
|
|
const fileUpdateGroup = {
|
|
'Series/Placeholder': ['track-01.mp3']
|
|
}
|
|
|
|
const results = await LibraryScanner.scanFolderUpdates(library, folder, fileUpdateGroup)
|
|
|
|
expect(scanLibraryItemStub.called).to.be.false
|
|
expect(results['Series/Placeholder']).to.equal(ScanResult.NOTHING)
|
|
})
|
|
})
|