const Database = require('../../server/Database') const { Sequelize } = require('sequelize') const LibraryFile = require('../../server/objects/files/LibraryFile') const fileUtils = require('../../server/utils/fileUtils') const sinon = require('sinon') async function loadTestDatabase(mockFileInfo) { let libraryItem1Id, libraryItem2Id let fileInfo = mockFileInfo || getMockFileInfo() let bookLibraryFiles = fileInfo.keys().reduce((acc, key) => { let bookfile = new LibraryFile() bookfile.setDataFromPath(key, key) acc.push(bookfile) return acc }, []) global.ServerSettings = {} Database.sequelize = new Sequelize({ dialect: 'sqlite', storage: ':memory:', // Choose one of the logging options logging: (...msg) => console.log(msg), logQueryParameters: true }) Database.sequelize.uppercaseFirst = (str) => (str ? `${str[0].toUpperCase()}${str.substr(1)}` : '') await Database.buildModels() const newLibrary = await Database.libraryModel.create({ name: 'Test Library', mediaType: 'book' }) const newLibraryFolder = await Database.libraryFolderModel.create({ path: '/test', libraryId: newLibrary.id }) const newLibraryFolder2 = await Database.libraryFolderModel.create({ path: '/mnt/drive', libraryId: newLibrary.id }) const newBook = await Database.bookModel.create({ title: 'Test Book', audioFiles: [], tags: [], narrators: [], genres: [], chapters: [] }) const newLibraryItem = await Database.libraryItemModel.create(buildBookLibraryItemParams(bookLibraryFiles[0], newBook.id, newLibrary.id, newLibraryFolder.id)) libraryItem1Id = newLibraryItem.id const newBook2 = await Database.bookModel.create({ title: 'Test Book 2', audioFiles: [], tags: [], narrators: [], genres: [], chapters: [] }) const newLibraryItem2 = await Database.libraryItemModel.create(buildBookLibraryItemParams(bookLibraryFiles[1], newBook2.id, newLibrary.id, newLibraryFolder2.id)) libraryItem2Id = newLibraryItem2.id return newLibrary } exports.loadTestDatabase = loadTestDatabase /** @returns {Map} */ function getMockFileInfo() { // @ts-ignore return new Map([ ['/test/file.pdf', { path: '/test/file.pdf', isDirectory: () => false, size: 1024, mtimeMs: Date.now(), ino: '1', dev: '100' }], ['/mnt/drive/file-same-ino-different-dev.pdf', { path: '/mnt/drive/file-same-ino-different-dev.pdf', isDirectory: () => false, size: 42, mtimeMs: Date.now(), ino: '1', dev: '200' }] ]) } exports.getMockFileInfo = getMockFileInfo /** @returns {Map} */ // this has the same data as above except one file has been renamed function getRenamedMockFileInfo() { // @ts-ignore return new Map([ ['/test/file-renamed.pdf', { path: '/test/file-renamed.pdf', isDirectory: () => false, size: 1024, mtimeMs: Date.now(), ino: '1', dev: '100' }], ['/mnt/drive/file-same-ino-different-dev.pdf', { path: '/mnt/drive/file-same-ino-different-dev.pdf', isDirectory: () => false, size: 42, mtimeMs: Date.now(), ino: '1', dev: '200' }] ]) } exports.getRenamedMockFileInfo = getRenamedMockFileInfo /** * @param {LibraryFile} libraryFile * @param {any} bookId * @param {string} libraryId * @param {any} libraryFolderId */ function buildBookLibraryItemParams(libraryFile, bookId, libraryId, libraryFolderId) { return { path: libraryFile.metadata?.path, isFile: true, ino: libraryFile.ino, deviceId: libraryFile.deviceId, libraryFiles: [libraryFile.toJSON()], mediaId: bookId, mediaType: 'book', libraryId: libraryId, libraryFolderId: libraryFolderId } } exports.buildBookLibraryItemParams = buildBookLibraryItemParams function stubFileUtils() { let getInoStub, getDeviceIdStub, getFileTimestampsWithInoStub getInoStub = sinon.stub(fileUtils, 'getIno') getInoStub.callsFake((path) => { const normalizedPath = fileUtils.filePathToPOSIX(path).replace(/\/$/, '') const stats = getMockFileInfo().get(normalizedPath) if (stats) { return stats.ino } else { return null } }) getDeviceIdStub = sinon.stub(fileUtils, 'getDeviceId') getDeviceIdStub.callsFake(async (path) => { const normalizedPath = fileUtils.filePathToPOSIX(path).replace(/\/$/, '') const stats = getMockFileInfo().get(normalizedPath) if (stats) { return stats.dev } else { return null } }) getFileTimestampsWithInoStub = sinon.stub(fileUtils, 'getFileTimestampsWithIno') getFileTimestampsWithInoStub.callsFake(async (path) => { const normalizedPath = fileUtils.filePathToPOSIX(path).replace(/\/$/, '') const stats = getMockFileInfo().get(normalizedPath) if (stats) { return stats } else { return null } }) } exports.stubFileUtils = stubFileUtils