Merge master

This commit is contained in:
advplyr 2024-12-01 13:27:20 -06:00
commit 33aa4f1952
21 changed files with 984 additions and 105 deletions

View file

@ -0,0 +1,202 @@
const { expect } = require('chai')
const { Sequelize } = require('sequelize')
const sinon = require('sinon')
const Database = require('../../../server/Database')
const ApiRouter = require('../../../server/routers/ApiRouter')
const LibraryItemController = require('../../../server/controllers/LibraryItemController')
const ApiCacheManager = require('../../../server/managers/ApiCacheManager')
const RssFeedManager = require('../../../server/managers/RssFeedManager')
const Logger = require('../../../server/Logger')
describe('LibraryItemController', () => {
/** @type {ApiRouter} */
let apiRouter
beforeEach(async () => {
global.ServerSettings = {}
Database.sequelize = new Sequelize({ dialect: 'sqlite', storage: ':memory:', logging: false })
Database.sequelize.uppercaseFirst = (str) => (str ? `${str[0].toUpperCase()}${str.substr(1)}` : '')
await Database.buildModels()
apiRouter = new ApiRouter({
apiCacheManager: new ApiCacheManager(),
rssFeedManager: new RssFeedManager()
})
sinon.stub(Logger, 'info')
})
afterEach(async () => {
sinon.restore()
// Clear all tables
await Database.sequelize.sync({ force: true })
})
describe('checkRemoveAuthorsAndSeries', () => {
let libraryItem1Id
let libraryItem2Id
let author1Id
let author2Id
let author3Id
let series1Id
let series2Id
beforeEach(async () => {
const newLibrary = await Database.libraryModel.create({ name: 'Test Library', mediaType: 'book' })
const newLibraryFolder = await Database.libraryFolderModel.create({ path: '/test', libraryId: newLibrary.id })
const newBook = await Database.bookModel.create({ title: 'Test Book', audioFiles: [], tags: [], narrators: [], genres: [], chapters: [] })
const newLibraryItem = await Database.libraryItemModel.create({ libraryFiles: [], mediaId: newBook.id, mediaType: 'book', libraryId: newLibrary.id, libraryFolderId: 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({ libraryFiles: [], mediaId: newBook2.id, mediaType: 'book', libraryId: newLibrary.id, libraryFolderId: newLibraryFolder.id })
libraryItem2Id = newLibraryItem2.id
const newAuthor = await Database.authorModel.create({ name: 'Test Author', libraryId: newLibrary.id })
author1Id = newAuthor.id
const newAuthor2 = await Database.authorModel.create({ name: 'Test Author 2', libraryId: newLibrary.id })
author2Id = newAuthor2.id
const newAuthor3 = await Database.authorModel.create({ name: 'Test Author 3', imagePath: '/fake/path/author.png', libraryId: newLibrary.id })
author3Id = newAuthor3.id
// Book 1 has Author 1, Author 2 and Author 3
await Database.bookAuthorModel.create({ bookId: newBook.id, authorId: newAuthor.id })
await Database.bookAuthorModel.create({ bookId: newBook.id, authorId: newAuthor2.id })
await Database.bookAuthorModel.create({ bookId: newBook.id, authorId: newAuthor3.id })
// Book 2 has Author 2
await Database.bookAuthorModel.create({ bookId: newBook2.id, authorId: newAuthor2.id })
const newSeries = await Database.seriesModel.create({ name: 'Test Series', libraryId: newLibrary.id })
series1Id = newSeries.id
const newSeries2 = await Database.seriesModel.create({ name: 'Test Series 2', libraryId: newLibrary.id })
series2Id = newSeries2.id
// Book 1 is in Series 1 and Series 2
await Database.bookSeriesModel.create({ bookId: newBook.id, seriesId: newSeries.id })
await Database.bookSeriesModel.create({ bookId: newBook.id, seriesId: newSeries2.id })
// Book 2 is in Series 2
await Database.bookSeriesModel.create({ bookId: newBook2.id, seriesId: newSeries2.id })
})
it('should remove authors and series with no books on library item delete', async () => {
const oldLibraryItem = await Database.libraryItemModel.getOldById(libraryItem1Id)
const fakeReq = {
query: {},
libraryItem: oldLibraryItem
}
const fakeRes = {
sendStatus: sinon.spy()
}
await LibraryItemController.delete.bind(apiRouter)(fakeReq, fakeRes)
expect(fakeRes.sendStatus.calledWith(200)).to.be.true
// Author 1 should be removed because it has no books
const author1Exists = await Database.authorModel.checkExistsById(author1Id)
expect(author1Exists).to.be.false
// Author 2 should not be removed because it still has Book 2
const author2Exists = await Database.authorModel.checkExistsById(author2Id)
expect(author2Exists).to.be.true
// Author 3 should not be removed because it has an image
const author3Exists = await Database.authorModel.checkExistsById(author3Id)
expect(author3Exists).to.be.true
// Series 1 should be removed because it has no books
const series1Exists = await Database.seriesModel.checkExistsById(series1Id)
expect(series1Exists).to.be.false
// Series 2 should not be removed because it still has Book 2
const series2Exists = await Database.seriesModel.checkExistsById(series2Id)
expect(series2Exists).to.be.true
})
it('should remove authors and series with no books on library item batch delete', async () => {
// Batch delete library item 1
const fakeReq = {
query: {},
user: {
canDelete: true
},
body: {
libraryItemIds: [libraryItem1Id]
}
}
const fakeRes = {
sendStatus: sinon.spy()
}
await LibraryItemController.batchDelete.bind(apiRouter)(fakeReq, fakeRes)
expect(fakeRes.sendStatus.calledWith(200)).to.be.true
// Author 1 should be removed because it has no books
const author1Exists = await Database.authorModel.checkExistsById(author1Id)
expect(author1Exists).to.be.false
// Author 2 should not be removed because it still has Book 2
const author2Exists = await Database.authorModel.checkExistsById(author2Id)
expect(author2Exists).to.be.true
// Author 3 should not be removed because it has an image
const author3Exists = await Database.authorModel.checkExistsById(author3Id)
expect(author3Exists).to.be.true
// Series 1 should be removed because it has no books
const series1Exists = await Database.seriesModel.checkExistsById(series1Id)
expect(series1Exists).to.be.false
// Series 2 should not be removed because it still has Book 2
const series2Exists = await Database.seriesModel.checkExistsById(series2Id)
expect(series2Exists).to.be.true
})
it('should remove authors and series with no books on library item update media', async () => {
const oldLibraryItem = await Database.libraryItemModel.getOldById(libraryItem1Id)
// Update library item 1 remove all authors and series
const fakeReq = {
query: {},
body: {
metadata: {
authors: [],
series: []
}
},
libraryItem: oldLibraryItem
}
const fakeRes = {
json: sinon.spy()
}
await LibraryItemController.updateMedia.bind(apiRouter)(fakeReq, fakeRes)
expect(fakeRes.json.calledOnce).to.be.true
// Author 1 should be removed because it has no books
const author1Exists = await Database.authorModel.checkExistsById(author1Id)
expect(author1Exists).to.be.false
// Author 2 should not be removed because it still has Book 2
const author2Exists = await Database.authorModel.checkExistsById(author2Id)
expect(author2Exists).to.be.true
// Author 3 should not be removed because it has an image
const author3Exists = await Database.authorModel.checkExistsById(author3Id)
expect(author3Exists).to.be.true
// Series 1 should be removed because it has no books
const series1Exists = await Database.seriesModel.checkExistsById(series1Id)
expect(series1Exists).to.be.false
// Series 2 should not be removed because it still has Book 2
const series2Exists = await Database.seriesModel.checkExistsById(series2Id)
expect(series2Exists).to.be.true
})
})
})

View file

@ -0,0 +1,230 @@
const { expect } = require('chai')
const sinon = require('sinon')
const { up } = require('../../../server/migrations/v2.17.3-fk-constraints')
const { Sequelize, QueryInterface } = require('sequelize')
const Logger = require('../../../server/Logger')
describe('migration-v2.17.3-fk-constraints', () => {
let sequelize
/** @type {QueryInterface} */
let queryInterface
let loggerInfoStub
beforeEach(() => {
sequelize = new Sequelize({ dialect: 'sqlite', storage: ':memory:', logging: false })
queryInterface = sequelize.getQueryInterface()
loggerInfoStub = sinon.stub(Logger, 'info')
})
afterEach(() => {
sinon.restore()
})
describe('up', () => {
beforeEach(async () => {
// Create associated tables: Users, libraries, libraryFolders, playlists, devices
await queryInterface.sequelize.query('CREATE TABLE `users` (`id` UUID PRIMARY KEY);')
await queryInterface.sequelize.query('CREATE TABLE `libraries` (`id` UUID PRIMARY KEY);')
await queryInterface.sequelize.query('CREATE TABLE `libraryFolders` (`id` UUID PRIMARY KEY);')
await queryInterface.sequelize.query('CREATE TABLE `playlists` (`id` UUID PRIMARY KEY);')
await queryInterface.sequelize.query('CREATE TABLE `devices` (`id` UUID PRIMARY KEY);')
})
afterEach(async () => {
await queryInterface.dropAllTables()
})
it('should fix table foreign key constraints', async () => {
// Create tables with missing foreign key constraints: libraryItems, feeds, mediaItemShares, playbackSessions, playlistMediaItems, mediaProgresses
await queryInterface.sequelize.query('CREATE TABLE `libraryItems` (`id` UUID UNIQUE PRIMARY KEY, `libraryId` UUID REFERENCES `libraries` (`id`), `libraryFolderId` UUID REFERENCES `libraryFolders` (`id`));')
await queryInterface.sequelize.query('CREATE TABLE `feeds` (`id` UUID UNIQUE PRIMARY KEY, `userId` UUID REFERENCES `users` (`id`));')
await queryInterface.sequelize.query('CREATE TABLE `mediaItemShares` (`id` UUID UNIQUE PRIMARY KEY, `userId` UUID REFERENCES `users` (`id`));')
await queryInterface.sequelize.query('CREATE TABLE `playbackSessions` (`id` UUID UNIQUE PRIMARY KEY, `userId` UUID REFERENCES `users` (`id`), `deviceId` UUID REFERENCES `devices` (`id`), `libraryId` UUID REFERENCES `libraries` (`id`));')
await queryInterface.sequelize.query('CREATE TABLE `playlistMediaItems` (`id` UUID UNIQUE PRIMARY KEY, `playlistId` UUID REFERENCES `playlists` (`id`));')
await queryInterface.sequelize.query('CREATE TABLE `mediaProgresses` (`id` UUID UNIQUE PRIMARY KEY, `userId` UUID REFERENCES `users` (`id`));')
//
// Validate that foreign key constraints are missing
//
let libraryItemsForeignKeys = await queryInterface.sequelize.query(`PRAGMA foreign_key_list(libraryItems);`)
expect(libraryItemsForeignKeys).to.have.deep.members([
{ id: 0, seq: 0, table: 'libraryFolders', from: 'libraryFolderId', to: 'id', on_update: 'NO ACTION', on_delete: 'NO ACTION', match: 'NONE' },
{ id: 1, seq: 0, table: 'libraries', from: 'libraryId', to: 'id', on_update: 'NO ACTION', on_delete: 'NO ACTION', match: 'NONE' }
])
let feedsForeignKeys = await queryInterface.sequelize.query(`PRAGMA foreign_key_list(feeds);`)
expect(feedsForeignKeys).to.deep.equal([{ id: 0, seq: 0, table: 'users', from: 'userId', to: 'id', on_update: 'NO ACTION', on_delete: 'NO ACTION', match: 'NONE' }])
let mediaItemSharesForeignKeys = await queryInterface.sequelize.query(`PRAGMA foreign_key_list(mediaItemShares);`)
expect(mediaItemSharesForeignKeys).to.deep.equal([{ id: 0, seq: 0, table: 'users', from: 'userId', to: 'id', on_update: 'NO ACTION', on_delete: 'NO ACTION', match: 'NONE' }])
let playbackSessionForeignKeys = await queryInterface.sequelize.query(`PRAGMA foreign_key_list(playbackSessions);`)
expect(playbackSessionForeignKeys).to.deep.equal([
{ id: 0, seq: 0, table: 'libraries', from: 'libraryId', to: 'id', on_update: 'NO ACTION', on_delete: 'NO ACTION', match: 'NONE' },
{ id: 1, seq: 0, table: 'devices', from: 'deviceId', to: 'id', on_update: 'NO ACTION', on_delete: 'NO ACTION', match: 'NONE' },
{ id: 2, seq: 0, table: 'users', from: 'userId', to: 'id', on_update: 'NO ACTION', on_delete: 'NO ACTION', match: 'NONE' }
])
let playlistMediaItemsForeignKeys = await queryInterface.sequelize.query(`PRAGMA foreign_key_list(playlistMediaItems);`)
expect(playlistMediaItemsForeignKeys).to.deep.equal([{ id: 0, seq: 0, table: 'playlists', from: 'playlistId', to: 'id', on_update: 'NO ACTION', on_delete: 'NO ACTION', match: 'NONE' }])
let mediaProgressesForeignKeys = await queryInterface.sequelize.query(`PRAGMA foreign_key_list(mediaProgresses);`)
expect(mediaProgressesForeignKeys).to.deep.equal([{ id: 0, seq: 0, table: 'users', from: 'userId', to: 'id', on_update: 'NO ACTION', on_delete: 'NO ACTION', match: 'NONE' }])
//
// Insert test data into tables
//
await queryInterface.bulkInsert('users', [{ id: 'e1a96857-48a8-43b6-8966-abc909c55b0f' }])
await queryInterface.bulkInsert('libraries', [{ id: 'a41a40e3-f516-40f5-810d-757ab668ebba' }])
await queryInterface.bulkInsert('libraryFolders', [{ id: 'b41a40e3-f516-40f5-810d-757ab668ebba' }])
await queryInterface.bulkInsert('playlists', [{ id: 'f41a40e3-f516-40f5-810d-757ab668ebba' }])
await queryInterface.bulkInsert('devices', [{ id: 'g41a40e3-f516-40f5-810d-757ab668ebba' }])
await queryInterface.bulkInsert('libraryItems', [{ id: 'c1a96857-48a8-43b6-8966-abc909c55b0f', libraryId: 'a41a40e3-f516-40f5-810d-757ab668ebba', libraryFolderId: 'b41a40e3-f516-40f5-810d-757ab668ebba' }])
await queryInterface.bulkInsert('feeds', [{ id: 'd1a96857-48a8-43b6-8966-abc909c55b0f', userId: 'e1a96857-48a8-43b6-8966-abc909c55b0f' }])
await queryInterface.bulkInsert('mediaItemShares', [{ id: 'h1a96857-48a8-43b6-8966-abc909c55b0f', userId: 'e1a96857-48a8-43b6-8966-abc909c55b0f' }])
await queryInterface.bulkInsert('playbackSessions', [{ id: 'f1a96857-48a8-43b6-8966-abc909c55b0x', userId: 'e1a96857-48a8-43b6-8966-abc909c55b0f', deviceId: 'g41a40e3-f516-40f5-810d-757ab668ebba', libraryId: 'a41a40e3-f516-40f5-810d-757ab668ebba' }])
await queryInterface.bulkInsert('playlistMediaItems', [{ id: 'i1a96857-48a8-43b6-8966-abc909c55b0f', playlistId: 'f41a40e3-f516-40f5-810d-757ab668ebba' }])
await queryInterface.bulkInsert('mediaProgresses', [{ id: 'j1a96857-48a8-43b6-8966-abc909c55b0f', userId: 'e1a96857-48a8-43b6-8966-abc909c55b0f' }])
//
// Query data before migration
//
const libraryItems = await queryInterface.sequelize.query('SELECT * FROM libraryItems;')
const feeds = await queryInterface.sequelize.query('SELECT * FROM feeds;')
const mediaItemShares = await queryInterface.sequelize.query('SELECT * FROM mediaItemShares;')
const playbackSessions = await queryInterface.sequelize.query('SELECT * FROM playbackSessions;')
const playlistMediaItems = await queryInterface.sequelize.query('SELECT * FROM playlistMediaItems;')
const mediaProgresses = await queryInterface.sequelize.query('SELECT * FROM mediaProgresses;')
//
// Run migration
//
await up({ context: { queryInterface, logger: Logger } })
//
// Validate that foreign key constraints are updated
//
libraryItemsForeignKeys = await queryInterface.sequelize.query(`PRAGMA foreign_key_list(libraryItems);`)
expect(libraryItemsForeignKeys).to.have.deep.members([
{ id: 0, seq: 0, table: 'libraryFolders', from: 'libraryFolderId', to: 'id', on_update: 'CASCADE', on_delete: 'SET NULL', match: 'NONE' },
{ id: 1, seq: 0, table: 'libraries', from: 'libraryId', to: 'id', on_update: 'CASCADE', on_delete: 'SET NULL', match: 'NONE' }
])
feedsForeignKeys = await queryInterface.sequelize.query(`PRAGMA foreign_key_list(feeds);`)
expect(feedsForeignKeys).to.deep.equal([{ id: 0, seq: 0, table: 'users', from: 'userId', to: 'id', on_update: 'CASCADE', on_delete: 'SET NULL', match: 'NONE' }])
mediaItemSharesForeignKeys = await queryInterface.sequelize.query(`PRAGMA foreign_key_list(mediaItemShares);`)
expect(mediaItemSharesForeignKeys).to.deep.equal([{ id: 0, seq: 0, table: 'users', from: 'userId', to: 'id', on_update: 'CASCADE', on_delete: 'SET NULL', match: 'NONE' }])
playbackSessionForeignKeys = await queryInterface.sequelize.query(`PRAGMA foreign_key_list(playbackSessions);`)
expect(playbackSessionForeignKeys).to.deep.equal([
{ id: 0, seq: 0, table: 'libraries', from: 'libraryId', to: 'id', on_update: 'CASCADE', on_delete: 'SET NULL', match: 'NONE' },
{ id: 1, seq: 0, table: 'devices', from: 'deviceId', to: 'id', on_update: 'CASCADE', on_delete: 'SET NULL', match: 'NONE' },
{ id: 2, seq: 0, table: 'users', from: 'userId', to: 'id', on_update: 'CASCADE', on_delete: 'SET NULL', match: 'NONE' }
])
playlistMediaItemsForeignKeys = await queryInterface.sequelize.query(`PRAGMA foreign_key_list(playlistMediaItems);`)
expect(playlistMediaItemsForeignKeys).to.deep.equal([{ id: 0, seq: 0, table: 'playlists', from: 'playlistId', to: 'id', on_update: 'CASCADE', on_delete: 'CASCADE', match: 'NONE' }])
mediaProgressesForeignKeys = await queryInterface.sequelize.query(`PRAGMA foreign_key_list(mediaProgresses);`)
expect(mediaProgressesForeignKeys).to.deep.equal([{ id: 0, seq: 0, table: 'users', from: 'userId', to: 'id', on_update: 'CASCADE', on_delete: 'CASCADE', match: 'NONE' }])
//
// Validate that data is not changed
//
const libraryItemsAfter = await queryInterface.sequelize.query('SELECT * FROM libraryItems;')
expect(libraryItemsAfter).to.deep.equal(libraryItems)
const feedsAfter = await queryInterface.sequelize.query('SELECT * FROM feeds;')
expect(feedsAfter).to.deep.equal(feeds)
const mediaItemSharesAfter = await queryInterface.sequelize.query('SELECT * FROM mediaItemShares;')
expect(mediaItemSharesAfter).to.deep.equal(mediaItemShares)
const playbackSessionsAfter = await queryInterface.sequelize.query('SELECT * FROM playbackSessions;')
expect(playbackSessionsAfter).to.deep.equal(playbackSessions)
const playlistMediaItemsAfter = await queryInterface.sequelize.query('SELECT * FROM playlistMediaItems;')
expect(playlistMediaItemsAfter).to.deep.equal(playlistMediaItems)
const mediaProgressesAfter = await queryInterface.sequelize.query('SELECT * FROM mediaProgresses;')
expect(mediaProgressesAfter).to.deep.equal(mediaProgresses)
})
it('should keep correct table foreign key constraints', async () => {
// Create tables with correct foreign key constraints: libraryItems, feeds, mediaItemShares, playbackSessions, playlistMediaItems, mediaProgresses
await queryInterface.sequelize.query('CREATE TABLE `libraryItems` (`id` UUID PRIMARY KEY, `libraryId` UUID REFERENCES `libraries` (`id`) ON DELETE SET NULL ON UPDATE CASCADE, `libraryFolderId` UUID REFERENCES `libraryFolders` (`id`) ON DELETE SET NULL ON UPDATE CASCADE);')
await queryInterface.sequelize.query('CREATE TABLE `feeds` (`id` UUID PRIMARY KEY, `userId` UUID REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE);')
await queryInterface.sequelize.query('CREATE TABLE `mediaItemShares` (`id` UUID PRIMARY KEY, `userId` UUID REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE);')
await queryInterface.sequelize.query('CREATE TABLE `playbackSessions` (`id` UUID PRIMARY KEY, `userId` UUID REFERENCES `users` (`id`) ON DELETE SET NULL ON UPDATE CASCADE, `deviceId` UUID REFERENCES `devices` (`id`) ON DELETE SET NULL ON UPDATE CASCADE, `libraryId` UUID REFERENCES `libraries` (`id`) ON DELETE SET NULL ON UPDATE CASCADE);')
await queryInterface.sequelize.query('CREATE TABLE `playlistMediaItems` (`id` UUID PRIMARY KEY, `playlistId` UUID REFERENCES `playlists` (`id`) ON DELETE CASCADE ON UPDATE CASCADE);')
await queryInterface.sequelize.query('CREATE TABLE `mediaProgresses` (`id` UUID PRIMARY KEY, `userId` UUID REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE);')
//
// Insert test data into tables
//
await queryInterface.bulkInsert('users', [{ id: 'e1a96857-48a8-43b6-8966-abc909c55b0f' }])
await queryInterface.bulkInsert('libraries', [{ id: 'a41a40e3-f516-40f5-810d-757ab668ebba' }])
await queryInterface.bulkInsert('libraryFolders', [{ id: 'b41a40e3-f516-40f5-810d-757ab668ebba' }])
await queryInterface.bulkInsert('playlists', [{ id: 'f41a40e3-f516-40f5-810d-757ab668ebba' }])
await queryInterface.bulkInsert('devices', [{ id: 'g41a40e3-f516-40f5-810d-757ab668ebba' }])
await queryInterface.bulkInsert('libraryItems', [{ id: 'c1a96857-48a8-43b6-8966-abc909c55b0f', libraryId: 'a41a40e3-f516-40f5-810d-757ab668ebba', libraryFolderId: 'b41a40e3-f516-40f5-810d-757ab668ebba' }])
await queryInterface.bulkInsert('feeds', [{ id: 'd1a96857-48a8-43b6-8966-abc909c55b0f', userId: 'e1a96857-48a8-43b6-8966-abc909c55b0f' }])
await queryInterface.bulkInsert('mediaItemShares', [{ id: 'h1a96857-48a8-43b6-8966-abc909c55b0f', userId: 'e1a96857-48a8-43b6-8966-abc909c55b0f' }])
await queryInterface.bulkInsert('playbackSessions', [{ id: 'f1a96857-48a8-43b6-8966-abc909c55b0x', userId: 'e1a96857-48a8-43b6-8966-abc909c55b0f', deviceId: 'g41a40e3-f516-40f5-810d-757ab668ebba', libraryId: 'a41a40e3-f516-40f5-810d-757ab668ebba' }])
await queryInterface.bulkInsert('playlistMediaItems', [{ id: 'i1a96857-48a8-43b6-8966-abc909c55b0f', playlistId: 'f41a40e3-f516-40f5-810d-757ab668ebba' }])
await queryInterface.bulkInsert('mediaProgresses', [{ id: 'j1a96857-48a8-43b6-8966-abc909c55b0f', userId: 'e1a96857-48a8-43b6-8966-abc909c55b0f' }])
//
// Query data before migration
//
const libraryItems = await queryInterface.sequelize.query('SELECT * FROM libraryItems;')
const feeds = await queryInterface.sequelize.query('SELECT * FROM feeds;')
const mediaItemShares = await queryInterface.sequelize.query('SELECT * FROM mediaItemShares;')
const playbackSessions = await queryInterface.sequelize.query('SELECT * FROM playbackSessions;')
const playlistMediaItems = await queryInterface.sequelize.query('SELECT * FROM playlistMediaItems;')
const mediaProgresses = await queryInterface.sequelize.query('SELECT * FROM mediaProgresses;')
await up({ context: { queryInterface, logger: Logger } })
expect(loggerInfoStub.callCount).to.equal(14)
expect(loggerInfoStub.getCall(0).calledWith(sinon.match('[2.17.3 migration] UPGRADE BEGIN: 2.17.3-fk-constraints'))).to.be.true
expect(loggerInfoStub.getCall(1).calledWith(sinon.match('[2.17.3 migration] Updating libraryItems constraints'))).to.be.true
expect(loggerInfoStub.getCall(2).calledWith(sinon.match('[2.17.3 migration] No changes needed for libraryItems constraints'))).to.be.true
expect(loggerInfoStub.getCall(3).calledWith(sinon.match('[2.17.3 migration] Updating feeds constraints'))).to.be.true
expect(loggerInfoStub.getCall(4).calledWith(sinon.match('[2.17.3 migration] No changes needed for feeds constraints'))).to.be.true
expect(loggerInfoStub.getCall(5).calledWith(sinon.match('[2.17.3 migration] Updating mediaItemShares constraints'))).to.be.true
expect(loggerInfoStub.getCall(6).calledWith(sinon.match('[2.17.3 migration] No changes needed for mediaItemShares constraints'))).to.be.true
expect(loggerInfoStub.getCall(7).calledWith(sinon.match('[2.17.3 migration] Updating playbackSessions constraints'))).to.be.true
expect(loggerInfoStub.getCall(8).calledWith(sinon.match('[2.17.3 migration] No changes needed for playbackSessions constraints'))).to.be.true
expect(loggerInfoStub.getCall(9).calledWith(sinon.match('[2.17.3 migration] Updating playlistMediaItems constraints'))).to.be.true
expect(loggerInfoStub.getCall(10).calledWith(sinon.match('[2.17.3 migration] No changes needed for playlistMediaItems constraints'))).to.be.true
expect(loggerInfoStub.getCall(11).calledWith(sinon.match('[2.17.3 migration] Updating mediaProgresses constraints'))).to.be.true
expect(loggerInfoStub.getCall(12).calledWith(sinon.match('[2.17.3 migration] No changes needed for mediaProgresses constraints'))).to.be.true
expect(loggerInfoStub.getCall(13).calledWith(sinon.match('[2.17.3 migration] UPGRADE END: 2.17.3-fk-constraints'))).to.be.true
//
// Validate that data is not changed
//
const libraryItemsAfter = await queryInterface.sequelize.query('SELECT * FROM libraryItems;')
expect(libraryItemsAfter).to.deep.equal(libraryItems)
const feedsAfter = await queryInterface.sequelize.query('SELECT * FROM feeds;')
expect(feedsAfter).to.deep.equal(feeds)
const mediaItemSharesAfter = await queryInterface.sequelize.query('SELECT * FROM mediaItemShares;')
expect(mediaItemSharesAfter).to.deep.equal(mediaItemShares)
const playbackSessionsAfter = await queryInterface.sequelize.query('SELECT * FROM playbackSessions;')
expect(playbackSessionsAfter).to.deep.equal(playbackSessions)
const playlistMediaItemsAfter = await queryInterface.sequelize.query('SELECT * FROM playlistMediaItems;')
expect(playlistMediaItemsAfter).to.deep.equal(playlistMediaItems)
const mediaProgressesAfter = await queryInterface.sequelize.query('SELECT * FROM mediaProgresses;')
expect(mediaProgressesAfter).to.deep.equal(mediaProgresses)
})
})
})