package psql_test import ( "context" "testing" "github.com/gabehf/koito/internal/catalog" "github.com/gabehf/koito/internal/db" "github.com/google/uuid" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func truncateTestData(t *testing.T) { err := store.Exec(context.Background(), `TRUNCATE artists, artist_aliases, tracks, artist_tracks, releases, artist_releases, release_aliases, listens RESTART IDENTITY CASCADE`) require.NoError(t, err) } func testDataForRelease(t *testing.T) { truncateTestData(t) err := store.Exec(context.Background(), `INSERT INTO artists (musicbrainz_id) VALUES ('00000000-0000-0000-0000-000000000001')`) require.NoError(t, err) err = store.Exec(context.Background(), `INSERT INTO artist_aliases (artist_id, alias, source, is_primary) VALUES (1, 'ATARASHII GAKKO!', 'MusicBrainz', true)`) require.NoError(t, err) err = store.Exec(context.Background(), `INSERT INTO artists (musicbrainz_id) VALUES ('00000000-0000-0000-0000-000000000002')`) require.NoError(t, err) err = store.Exec(context.Background(), `INSERT INTO artist_aliases (artist_id, alias, source, is_primary) VALUES (2, 'Masayuki Suzuki', 'MusicBrainz', true)`) require.NoError(t, err) } func TestGetAlbum(t *testing.T) { testDataForRelease(t) ctx := context.Background() // Insert test data rg, err := store.SaveAlbum(ctx, db.SaveAlbumOpts{ Title: "Test Release Group", ArtistIDs: []int32{1}, }) require.NoError(t, err) // Test GetAlbum by ID result, err := store.GetAlbum(ctx, db.GetAlbumOpts{ID: rg.ID}) require.NoError(t, err) assert.Equal(t, rg.ID, result.ID) assert.Equal(t, "Test Release Group", result.Title) // Test GetAlbum with insufficient information _, err = store.GetAlbum(ctx, db.GetAlbumOpts{}) assert.Error(t, err) truncateTestData(t) } func TestSaveAlbum(t *testing.T) { testDataForRelease(t) ctx := context.Background() // Save release group with artist IDs artistIDs := []int32{1, 2} rg, err := store.SaveAlbum(ctx, db.SaveAlbumOpts{ Title: "New Release Group", ArtistIDs: artistIDs, }) require.NoError(t, err) // Verify release group was saved assert.Equal(t, "New Release Group", rg.Title) // Verify release was created for release group exists, err := store.RowExists(ctx, ` SELECT EXISTS ( SELECT 1 FROM releases_with_title WHERE title = $1 AND id = $2 )`, "New Release Group", rg.ID) require.NoError(t, err) assert.True(t, exists, "expected release to exist") // Verify artist associations were created for release group for _, aid := range artistIDs { exists, err := store.RowExists(ctx, ` SELECT EXISTS ( SELECT 1 FROM artist_releases WHERE artist_id = $1 AND release_id = $2 )`, aid, rg.ID) require.NoError(t, err) assert.True(t, exists, "expected artist association to exist") } truncateTestData(t) } func TestUpdateAlbum(t *testing.T) { testDataForRelease(t) ctx := context.Background() rg, err := store.SaveAlbum(ctx, db.SaveAlbumOpts{ Title: "Old Title", ArtistIDs: []int32{1}, }) require.NoError(t, err) newMbzID := uuid.New() imgid := uuid.New() err = store.UpdateAlbum(ctx, db.UpdateAlbumOpts{ ID: rg.ID, MusicBrainzID: newMbzID, Image: imgid, ImageSrc: catalog.ImageSourceUserUpload, }) require.NoError(t, err) result, err := store.GetAlbum(ctx, db.GetAlbumOpts{ID: rg.ID}) require.NoError(t, err) assert.Equal(t, newMbzID, *result.MbzID) assert.Equal(t, imgid, *result.Image) truncateTestData(t) } func TestAddArtistsToAlbum(t *testing.T) { testDataForRelease(t) ctx := context.Background() // Insert test album rg, err := store.SaveAlbum(ctx, db.SaveAlbumOpts{ Title: "Test Album", ArtistIDs: []int32{1}, }) require.NoError(t, err) // Add additional artists to the album err = store.AddArtistsToAlbum(ctx, db.AddArtistsToAlbumOpts{ AlbumID: rg.ID, ArtistIDs: []int32{2}, }) require.NoError(t, err) // Verify artist associations were created exists, err := store.RowExists(ctx, ` SELECT EXISTS ( SELECT 1 FROM artist_releases WHERE artist_id = $1 AND release_id = $2 )`, 2, rg.ID) require.NoError(t, err) assert.True(t, exists, "expected artist association to exist") truncateTestData(t) } func TestSaveAlbumAliases(t *testing.T) { testDataForRelease(t) ctx := context.Background() // Insert test album rg, err := store.SaveAlbum(ctx, db.SaveAlbumOpts{ Title: "Test Album", ArtistIDs: []int32{1}, }) require.NoError(t, err) // Save aliases for the album aliases := []string{"Alias 1", "Alias 2"} err = store.SaveAlbumAliases(ctx, rg.ID, aliases, "TestSource") require.NoError(t, err) // Verify aliases were saved for _, alias := range aliases { exists, err := store.RowExists(ctx, ` SELECT EXISTS ( SELECT 1 FROM release_aliases WHERE release_id = $1 AND alias = $2 )`, rg.ID, alias) require.NoError(t, err) assert.True(t, exists, "expected alias to exist") } err = store.SetPrimaryAlbumAlias(ctx, 1, "Alias 1") require.NoError(t, err) album, err := store.GetAlbum(ctx, db.GetAlbumOpts{ID: rg.ID}) require.NoError(t, err) assert.Equal(t, "Alias 1", album.Title) err = store.SetPrimaryAlbumAlias(ctx, 1, "Fake Alias") require.Error(t, err) store.SetPrimaryAlbumAlias(ctx, 1, "Album One") truncateTestData(t) } func TestDeleteAlbum(t *testing.T) { testDataForRelease(t) ctx := context.Background() testDataForTopItems(t) // Delete the album err := store.DeleteAlbum(ctx, 1) require.NoError(t, err) // Verify album was deleted exists, err := store.RowExists(ctx, ` SELECT EXISTS ( SELECT 1 FROM releases WHERE id = $1 )`, 1) require.NoError(t, err) assert.False(t, exists, "expected album to be deleted") // Verify album's track was deleted exists, err = store.RowExists(ctx, ` SELECT EXISTS ( SELECT 1 FROM tracks WHERE id = $1 )`, 1) require.NoError(t, err) assert.False(t, exists, "expected album's tracks to be deleted") // Verify album's listens was deleted exists, err = store.RowExists(ctx, ` SELECT EXISTS ( SELECT 1 FROM listens WHERE track_id = $1 )`, 1) require.NoError(t, err) assert.False(t, exists, "expected album's listens to be deleted") truncateTestData(t) } func TestDeleteAlbumAlias(t *testing.T) { testDataForRelease(t) ctx := context.Background() // Insert test album rg, err := store.SaveAlbum(ctx, db.SaveAlbumOpts{ Title: "Test Album", ArtistIDs: []int32{1}, }) require.NoError(t, err) // Save aliases for the album aliases := []string{"Alias 1", "Alias 2"} err = store.SaveAlbumAliases(ctx, rg.ID, aliases, "TestSource") require.NoError(t, err) // Delete one alias err = store.DeleteAlbumAlias(ctx, rg.ID, "Alias 1") require.NoError(t, err) // Verify alias was deleted exists, err := store.RowExists(ctx, ` SELECT EXISTS ( SELECT 1 FROM release_aliases WHERE release_id = $1 AND alias = $2 )`, rg.ID, "Alias 1") require.NoError(t, err) assert.False(t, exists, "expected alias to be deleted") // Verify other alias still exists exists, err = store.RowExists(ctx, ` SELECT EXISTS ( SELECT 1 FROM release_aliases WHERE release_id = $1 AND alias = $2 )`, rg.ID, "Alias 2") require.NoError(t, err) assert.True(t, exists, "expected alias to still exist") // Ensure primary alias cannot be deleted err = store.DeleteAlbumAlias(ctx, rg.ID, "Test Album") require.NoError(t, err) // shouldn't error when nothing is deleted rg, err = store.GetAlbum(ctx, db.GetAlbumOpts{ID: rg.ID}) require.NoError(t, err) assert.Equal(t, "Test Album", rg.Title) truncateTestData(t) } func TestGetAllAlbumAliases(t *testing.T) { testDataForRelease(t) ctx := context.Background() // Insert test album rg, err := store.SaveAlbum(ctx, db.SaveAlbumOpts{ Title: "Test Album", ArtistIDs: []int32{1}, }) require.NoError(t, err) // Save aliases for the album aliases := []string{"Alias 1", "Alias 2"} err = store.SaveAlbumAliases(ctx, rg.ID, aliases, "TestSource") require.NoError(t, err) // Retrieve all aliases result, err := store.GetAllAlbumAliases(ctx, rg.ID) require.NoError(t, err) assert.Len(t, result, len(aliases)+1) // new + canonical for _, alias := range aliases { found := false for _, res := range result { if res.Alias == alias { found = true break } } assert.True(t, found, "expected alias to be retrieved") } truncateTestData(t) }