Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
2846c41
Show placeholder as artist image
FranzDeschler Apr 27, 2026
4116a25
Provide setting for downloading and displaying artist images
FranzDeschler Apr 27, 2026
a05ab60
Fix displaying artist images
FranzDeschler Apr 29, 2026
b9ecf5c
Add database migration for ArtistArtwork
FranzDeschler Apr 29, 2026
c718e6b
Access ArtistArtwork via ArtistArtworkRepository
FranzDeschler Apr 29, 2026
f9c9853
Create ArrayUtils for common array functions
FranzDeschler May 1, 2026
a9b7eb8
Provide list of album and track artists via file metadata
FranzDeschler May 1, 2026
92f8e0c
Rename constants "cachedCoverArt*" to "cachedArtwork*" to have a more…
FranzDeschler May 1, 2026
ac878b8
Create CacheService to access cached artist artwork
FranzDeschler May 1, 2026
a67e5c4
Getter for downloading artist artwork
FranzDeschler May 1, 2026
bc7c9a4
Index artist artwork
FranzDeschler May 1, 2026
1225032
Generate artistKey
FranzDeschler May 1, 2026
f1eeb2b
Load artist image from cache via application paths
FranzDeschler May 1, 2026
d1d0d9a
Fix tests
FranzDeschler May 1, 2026
84cdab1
Update translations
FranzDeschler May 1, 2026
cccd1b8
Fix tests
FranzDeschler May 1, 2026
bfea628
Call ArtistArtworkIndexer in IndexingService
FranzDeschler May 1, 2026
67b36be
Update tests
FranzDeschler May 3, 2026
2910270
Update migration
FranzDeschler May 3, 2026
567f9ac
Update repositories
FranzDeschler May 3, 2026
d69e6d8
Add artworkId to ArtistModel
FranzDeschler May 3, 2026
58f53c2
Load artworkId in ArtistService
FranzDeschler May 3, 2026
093ed50
Update artwork indexing
FranzDeschler May 3, 2026
03f4a95
Update tests
FranzDeschler May 3, 2026
60a5a48
Fix application setup
FranzDeschler May 3, 2026
c19bc82
Reuse OnlineArtistImageGetter
FranzDeschler May 3, 2026
44ae880
Fix reference error
FranzDeschler May 3, 2026
8e45763
Improve logging
FranzDeschler May 3, 2026
17aa654
Fix sql queries
FranzDeschler May 3, 2026
3ee7c8f
Fix sql queries
FranzDeschler May 3, 2026
5073889
Handle multiple artists per track
FranzDeschler May 4, 2026
093634e
Generator for ArtistsKey
FranzDeschler May 6, 2026
79f27f0
Use ArtistsKey for merging ArtistsArtwork and Track
FranzDeschler May 6, 2026
f2e0b50
Disable NeedsArtistArtworkIndexing flag for unknown artists
FranzDeschler May 6, 2026
9dd6601
Get rid of NeedsArtistArtworkIndexing flag
FranzDeschler May 8, 2026
426122c
Add option to refresh artists artwork
FranzDeschler May 8, 2026
e66d37a
Fixed tests
FranzDeschler May 9, 2026
7d58324
Fix margins
FranzDeschler May 9, 2026
17fbf54
Add database tests
FranzDeschler May 13, 2026
78a0864
Create custom script for executing database tests in the electron env…
FranzDeschler May 13, 2026
8b21588
Merge branch 'master' into feature/artist-images
FranzDeschler May 13, 2026
b919ab8
Fix unit tests
FranzDeschler May 13, 2026
813b83c
Revert "Provide list of album and track artists via file metadata"
FranzDeschler May 14, 2026
1734b0f
Dynamically set item size of artist components
FranzDeschler May 14, 2026
40bb661
Remove unnecessary delimiter from ArtistArtwork table
FranzDeschler May 14, 2026
051bd83
Fix UI
FranzDeschler May 14, 2026
3d0f418
Remove unused code
FranzDeschler May 14, 2026
03186fd
Undo code changes
FranzDeschler May 14, 2026
f734f4a
Fix logging
FranzDeschler May 14, 2026
cc87d60
Use MusicBrainz API as fallback if last.fm cannot provide artist info…
FranzDeschler May 14, 2026
d3108de
Fix typographic issues
FranzDeschler May 14, 2026
867cee8
Add "Edit" option to artist context menu
FranzDeschler May 17, 2026
9b4ca9c
Provide dialog for removing/changing the artist image
FranzDeschler May 17, 2026
7fab090
Show alternative artist images
FranzDeschler May 24, 2026
4098a2c
Show loading spinner for artist images
FranzDeschler May 24, 2026
21348bc
Update artist image in database
FranzDeschler May 31, 2026
f02ea9e
Extend translations
FranzDeschler May 31, 2026
2cdc225
Rename migration due to merge conflicts
FranzDeschler May 31, 2026
64ab87b
Merge branch 'master' into feature/artist-images
FranzDeschler May 31, 2026
5c74249
Add "Edit" option to artist context menu
FranzDeschler May 17, 2026
75426d4
Provide dialog for removing/changing the artist image
FranzDeschler May 17, 2026
79db8ed
Show alternative artist images
FranzDeschler May 24, 2026
45ead7b
Show loading spinner for artist images
FranzDeschler May 24, 2026
fadff54
Update artist image in database
FranzDeschler May 31, 2026
1cdf60a
Rebase
FranzDeschler May 31, 2026
d7efb4d
Merge remote-tracking branch 'origin/feature/artist-image-editing' in…
FranzDeschler May 31, 2026
65afc86
Update translations
FranzDeschler May 31, 2026
1317f14
Update UI as soon as artist image was updated
FranzDeschler May 31, 2026
7485bff
Merge branch 'master' into feature/artist-image-editing
FranzDeschler Jul 4, 2026
511f0e5
Fix logging
FranzDeschler Jul 5, 2026
112d5c5
Show edit option only if showing artist images is enabled
FranzDeschler Jul 5, 2026
564814b
Add IsManuallySet flag to database
FranzDeschler Jul 5, 2026
dad80fa
Set IsManuallySet flag when editing artist images
FranzDeschler Jul 5, 2026
6a79079
Add translations
FranzDeschler Jul 5, 2026
ade1099
Fix unit tests
FranzDeschler Jul 5, 2026
82f055d
Add translations
FranzDeschler Jul 5, 2026
2002c0a
Fix unit tests
FranzDeschler Jul 5, 2026
1ea7163
Fix Setup
FranzDeschler Jul 5, 2026
ac1648f
Merge branch 'master' into feature/artist-image-editing
FranzDeschler Jul 19, 2026
4fb5059
Merge branch 'master' into feature/artist-image-editing
digimezzo Jul 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ import { ArtistArtworkCacheService } from './services/artist-artwork-cache/artis
import { ArtistModelFactory } from './services/artist/artist-model-factory';
import { ArtistsKeyGenerator } from './data/artists-key-generator';
import { MusicBrainzApi } from './common/api/musicbrainz/musicbrainz.api';
import { EditArtistDialogComponent } from './ui/components/dialogs/edit-artist-dialog/edit-artist-dialog.component';

export function HttpLoaderFactory(http: HttpClient): TranslateHttpLoader {
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
Expand Down Expand Up @@ -483,6 +484,7 @@ export function settingsInitializerFactory(settings: SettingsBase) {
EditTracksDialogComponent,
EditAlbumDialogComponent,
IterableMenuComponent,
EditArtistDialogComponent,
],
imports: [
BrowserAnimationsModule,
Expand Down
17 changes: 15 additions & 2 deletions src/app/common/api/fanart/fanart.api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,26 @@ import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { SensitiveInformation } from '../../application/sensitive-information';

interface FanartResponse {
artistthumb: [
{
url: string;
},
];
}

@Injectable()
export class FanartApi {
public constructor(private httpClient: HttpClient) {}

public async getArtistThumbnailAsync(musicBrainzId: string): Promise<string> {
const thumbnailUrls: string[] = await this.getAllArtistThumbnailsAsync(musicBrainzId);
return thumbnailUrls[0];
}

public async getAllArtistThumbnailsAsync(musicBrainzId: string): Promise<string[]> {
const url: string = `http://webservice.fanart.tv/v3/music/${musicBrainzId}?api_key=${SensitiveInformation.fanartApiKey}`;
const response: any = await this.httpClient.get<any>(url).toPromise();
return response.artistthumb?.[0]?.url;
const response: FanartResponse = await this.httpClient.get<any>(url).toPromise();
return response.artistthumb?.map((value): string => value.url) ?? [];
}
}
4 changes: 4 additions & 0 deletions src/app/common/application/i18n.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ describe('validate i18n', () => {
'edit-playlist',
'edit-track',
'edit-tracks',
'edit-artist',
'search-online-images',
'embedded-lyrics',
'enable-discord-rich-presence',
'enable-gapless-playback',
Expand Down Expand Up @@ -197,6 +199,7 @@ describe('validate i18n', () => {
'no-biography-found',
'no-folders-in-collection',
'no-image-found-online',
'no-images-found-online',
'no-lyrics',
'no-lyrics-found',
'no-playlists',
Expand Down Expand Up @@ -398,6 +401,7 @@ describe('validate i18n', () => {
'large-size',
'xl-size',
'overwrite-manually-edited-covers',
'overwrite-manually-edited-artist-images',
'restore-ratings-from-backup',
'restore-ratings-from-backup-description',
'ratings-backup',
Expand Down
2 changes: 2 additions & 0 deletions src/app/data/database-migrator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { Migration9 } from './migrations/migration9';
import { Migration10 } from './migrations/migration10';
import { Migration11 } from "./migrations/migration11";
import { Migration12 } from "./migrations/migration12";
import { Migration13 } from "./migrations/migration13";

@Injectable()
export class DatabaseMigrator implements DatabaseMigratorBase {
Expand All @@ -36,6 +37,7 @@ export class DatabaseMigrator implements DatabaseMigratorBase {
new Migration10(),
new Migration11(),
new Migration12(),
new Migration13(),
];

public constructor(
Expand Down
6 changes: 5 additions & 1 deletion src/app/data/entities/artist-artwork.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
export class ArtistArtwork {
public constructor(public artist: string, public artworkId: string) {}
public constructor(
public artist: string,
public artworkId: string,
public isManuallySet: number = 0,
) {}

public artistArtworkId: string;
}
10 changes: 10 additions & 0 deletions src/app/data/migrations/migration13.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Migration } from '../migration';

export class Migration13 extends Migration {
public id: number = 13;
public name: string = 'Migration13';

public up(): void {
this.sql('ALTER TABLE ArtistArtwork ADD COLUMN IsManuallySet INTEGER DEFAULT 0;');
}
}
4 changes: 3 additions & 1 deletion src/app/data/repositories/artist-artwork-repository.base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ export abstract class ArtistArtworkRepositoryBase {
public abstract getNumberOfArtistArtworkThatHasNoTrack(): number;
public abstract deleteArtistArtworkThatHasNoTrack(): number;
public abstract addArtistArtwork(artistArtwork: ArtistArtwork): void;
public abstract updateArtistArtwork(artistArtwork: ArtistArtwork): void;
public abstract getAllArtistArtwork(): ArtistArtwork[] | undefined;
public abstract getArtistArtworkForArtists(artists: string[]): ArtistArtwork[];
public abstract deleteArtistArtworkWithDefaultId(): number;
public abstract deleteAllArtistArtwork(): number
public abstract deleteAllArtistArtwork(): number;
public abstract clearManuallySetFlag(): void;
}
39 changes: 33 additions & 6 deletions src/app/data/repositories/artist-artwork-repository.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ describe('ArtistArtworkRepository', () => {
ArtistArtworkID INTEGER,
Artist TEXT,
ArtworkID TEXT,
IsManuallySet INTEGER,
PRIMARY KEY(ArtistArtworkID)
);`,
);
Expand All @@ -32,10 +33,10 @@ describe('ArtistArtworkRepository', () => {
}

function fillTestData(): void {
const statement = database.prepare('INSERT INTO ArtistArtwork (Artist, ArtworkID) VALUES (?, ?);');
statement.run('metallica', 'artist-1');
statement.run('aerosmith', 'artist-2');
statement.run('alanis morissette', 'artist-3');
const statement = database.prepare('INSERT INTO ArtistArtwork (Artist, ArtworkID, IsManuallySet) VALUES (?, ?, ?);');
statement.run('metallica', 'artist-1', 0);
statement.run('aerosmith', 'artist-2', 0);
statement.run('alanis morissette', 'artist-3', 1);
}

beforeEach(() => {
Expand Down Expand Up @@ -73,6 +74,20 @@ describe('ArtistArtworkRepository', () => {
});
});

describe('updateArtistArtwork', () => {
it('should update the artworkId of an existing artist in the database', () => {
// Arrange, Act
const artistArtwork: ArtistArtwork = new ArtistArtwork('metallica', 'artist-99');
repository.updateArtistArtwork(artistArtwork);

// Assert
const artworkInDatabase: ArtistArtwork[] = repository.getArtistArtworkForArtists(['metallica']);
expect(artworkInDatabase).not.toBeUndefined();
expect(artworkInDatabase.length).toEqual(1);
expect(artworkInDatabase[0].artworkId).toEqual('artist-99');
});
});

describe('getAllArtistArtwork', () => {
it('should return all entries in the table', () => {
// Arrange, Act
Expand Down Expand Up @@ -180,14 +195,26 @@ describe('ArtistArtworkRepository', () => {
});

describe('deleteAllArtistArtwork', () => {
it('should delete all artist artwork', () => {
// Arrange, Act
it('should delete all artist artwork including manually set images', () => {
// Arrange
repository.clearManuallySetFlag();

// Act
const deletedRows: number = repository.deleteAllArtistArtwork();

// Assert
expect(deletedRows).toEqual(3);
expect(repository.getNumberOfArtistArtwork()).toEqual(0);
});

it('should delete all artist artwork except manually set images', () => {
// Arrange, Act
const deletedRows: number = repository.deleteAllArtistArtwork();

// Assert
expect(deletedRows).toEqual(2);
expect(repository.getNumberOfArtistArtwork()).toEqual(1);
});
});

describe('deleteArtistArtworkWithDefaultId', () => {
Expand Down
16 changes: 13 additions & 3 deletions src/app/data/repositories/artist-artwork-repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,13 @@ export class ArtistArtworkRepository implements ArtistArtworkRepositoryBase {
public constructor(private databaseFactory: DatabaseFactory) {}

public addArtistArtwork(artistArtwork: ArtistArtwork): void {
const statement = this.database.prepare('INSERT INTO ArtistArtwork (Artist, ArtworkID) VALUES (?, ?);');
statement.run(artistArtwork.artist.toLowerCase(), artistArtwork.artworkId);
const statement = this.database.prepare('INSERT INTO ArtistArtwork (Artist, ArtworkID, isManuallySet) VALUES (?, ?, ?);');
statement.run(artistArtwork.artist.toLowerCase(), artistArtwork.artworkId, artistArtwork.isManuallySet);
}

public updateArtistArtwork(artistArtwork: ArtistArtwork): void {
const statement = this.database.prepare('UPDATE ArtistArtwork SET ArtworkID = ?, isManuallySet = ? WHERE Artist = ?;');
statement.run(artistArtwork.artworkId, artistArtwork.isManuallySet, artistArtwork.artist.toLowerCase());
}

public getAllArtistArtwork(): ArtistArtwork[] | undefined {
Expand Down Expand Up @@ -79,7 +84,7 @@ export class ArtistArtworkRepository implements ArtistArtworkRepositoryBase {
}

public deleteAllArtistArtwork(): number {
const statement = this.database.prepare(`DELETE FROM ArtistArtwork WHERE 1=1;`);
const statement = this.database.prepare(`DELETE FROM ArtistArtwork WHERE IsManuallySet = 0;`);
const info = statement.run();
return info.changes;
}
Expand All @@ -90,6 +95,11 @@ export class ArtistArtworkRepository implements ArtistArtworkRepositoryBase {
return info.changes;
}

public clearManuallySetFlag(): void {
const statement = this.database.prepare(`UPDATE ArtistArtwork SET IsManuallySet = 0 WHERE IsManuallySet = 1;`);
statement.run();
}

private get database(): any {
return this.databaseFactory.create();
}
Expand Down
2 changes: 2 additions & 0 deletions src/app/services/dialog/dialog.service.base.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { PlaylistModel } from '../playlist/playlist-model';
import { TrackModel } from '../track/track-model';
import { AlbumModel } from '../album/album-model';
import { ArtistModel } from '../artist/artist-model';

export abstract class DialogServiceBase {
public abstract showConfirmationDialogAsync(dialogTitle: string, dialogText: string): Promise<boolean>;
Expand All @@ -19,6 +20,7 @@ export abstract class DialogServiceBase {
public abstract showEditColumnsDialogAsync(): Promise<void>;
public abstract showEditTracksAsync(tracks: TrackModel[]): Promise<boolean>;
public abstract showEditAlbumsAsync(albums: AlbumModel[]): Promise<void>;
public abstract showEditArtistAsync(artist: ArtistModel): Promise<void>;
public abstract cannotPlayM4aFileAsync(): Promise<void>;
public abstract cannotPlayAudioFileAsync(): Promise<void>;
}
12 changes: 12 additions & 0 deletions src/app/services/dialog/dialog.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import { EditSmartPlaylistDialogComponent } from '../../ui/components/dialogs/ed
import { FileFormats } from '../../common/application/file-formats';
import { AlbumModel } from '../album/album-model';
import { EditAlbumDialogComponent } from '../../ui/components/dialogs/edit-album-dialog/edit-album-dialog.component';
import { ArtistModel } from '../artist/artist-model';
import { EditArtistDialogComponent } from '../../ui/components/dialogs/edit-artist-dialog/edit-artist-dialog.component';

@Injectable()
export class DialogService implements DialogServiceBase {
Expand Down Expand Up @@ -153,10 +155,20 @@ export class DialogService implements DialogServiceBase {
await dialogRef.afterClosed().toPromise();
}

public async showEditArtistAsync(artist: ArtistModel): Promise<void> {
const dialogRef: MatDialogRef<EditArtistDialogComponent> = this.dialog.open(EditArtistDialogComponent, {
data: artist,
maxWidth: '750px',
});

await dialogRef.afterClosed().toPromise();
}

public async cannotPlayM4aFileAsync(): Promise<void> {
const message: string = await this.translatorService.getAsync('cannot-play-m4a-file');
this.showErrorDialog(message);
}

public async cannotPlayAudioFileAsync(): Promise<void> {
const message: string = await this.translatorService.getAsync('cannot-play-audio-file');
this.showErrorDialog(message);
Expand Down
18 changes: 17 additions & 1 deletion src/app/services/indexing/artist-artwork-adder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@ import { ArtistArtworkRepositoryBase } from '../../data/repositories/artist-artw
import { TrackRepositoryBase } from '../../data/repositories/track-repository.base';
import { NotificationServiceBase } from '../notification/notification.service.base';
import { ArrayUtils } from '../../common/utils/array-utils';
import { Observable, Subject } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class ArtistArtworkAdder {
private artistArtworkChanged: Subject<void> = new Subject();
public readonly artistArtworkChanged$: Observable<void> = this.artistArtworkChanged.asObservable();

public constructor(
private artistArtworkCacheService: ArtistArtworkCacheServiceBase,
private artistArtworkRepository: ArtistArtworkRepositoryBase,
Expand Down Expand Up @@ -69,8 +73,20 @@ export class ArtistArtworkAdder {
}
}
} catch (e: unknown) {
this.logger.error(e, `Could not add artist artwork for '${artist}'`, 'ArtistArtworkAdder', 'addMissingArtistArtworkAsync');
this.logger.error(e, `Could not add artist artwork for '${artist}'`, 'ArtistArtworkAdder', 'addArtistArtworkAsync');
}
}
}

public async updateArtistArtworkAsync(artist: string, artistArtwork: Buffer, isManuallySet: boolean): Promise<void> {
const artistArtworkCacheId: ArtistArtworkCacheId | undefined =
await this.artistArtworkCacheService.addArtworkDataToCacheAsync(artistArtwork);
if (artistArtworkCacheId != undefined) {
const newArtistArtwork: ArtistArtwork = new ArtistArtwork(artist, artistArtworkCacheId.id, isManuallySet ? 1 : 0);
this.artistArtworkRepository.updateArtistArtwork(newArtistArtwork);
this.artistArtworkChanged.next();
} else {
throw new Error(`Could not update artist artwork for '${artist}'`);
}
}
}
2 changes: 1 addition & 1 deletion src/app/services/indexing/artist-artwork-indexer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ describe('ArtistArtworkIndexer', () => {
notificationServiceMock.verify((x) => x.updatingArtistArtworkAsync(), Times.once());
});

it('should delete all artist artwork from cache', async () => {
it('should delete all artist artwork from database', async () => {
// Arrange, Act
await artistArtworkIndexer.refreshAllArtistsArtworkAsync();

Expand Down
19 changes: 18 additions & 1 deletion src/app/services/indexing/indexing.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { TrackFiller } from './track-filler';
import { SchedulerBase } from '../../common/scheduling/scheduler.base';
import { ArtistArtworkIndexer } from './artist-artwork-indexer';
import { Track } from '../../data/entities/track';
import { ArtistArtworkRepositoryBase } from '../../data/repositories/artist-artwork-repository.base';

describe('IndexingService', () => {
let notificationServiceMock: IMock<NotificationServiceBase>;
Expand All @@ -31,6 +32,7 @@ describe('IndexingService', () => {
let loggerMock: IMock<Logger>;
let trackRepositoryMock: IMock<TrackRepositoryBase>;
let albumArtworkRepositoryMock: IMock<AlbumArtworkRepositoryBase>;
let artistArtworkRepositoryMock: IMock<ArtistArtworkRepositoryBase>;

let folderService_foldersChanged: Subject<void>;

Expand All @@ -51,6 +53,7 @@ describe('IndexingService', () => {
loggerMock = Mock.ofType<Logger>();
trackRepositoryMock = Mock.ofType<TrackRepositoryBase>();
albumArtworkRepositoryMock = Mock.ofType<AlbumArtworkRepositoryBase>();
artistArtworkRepositoryMock = Mock.ofType<ArtistArtworkRepositoryBase>();

folderService_foldersChanged = new Subject();
const folderService_foldersChanged$: Observable<void> = folderService_foldersChanged.asObservable();
Expand All @@ -73,6 +76,7 @@ describe('IndexingService', () => {
albumArtworkIndexerMock.object,
artistArtworkIndexerMock.object,
albumArtworkRepositoryMock.object,
artistArtworkRepositoryMock.object,
trackRepositoryMock.object,
trackFillerMock.object,
desktopMock.object,
Expand Down Expand Up @@ -105,14 +109,27 @@ describe('IndexingService', () => {
artistArtworkIndexerMock.verify((x) => x.refreshMissingArtistsArtworkAsync(), Times.once());
});

it('should refresh all artists artwork', async () => {
it('should refresh all artists artwork including manually set images', async () => {
// Arrange
const sut: IndexingService = createSut();

// Act
await sut.indexArtistArtworkOnlyAsync(false);

// Assert
artistArtworkRepositoryMock.verify((x) => x.clearManuallySetFlag(), Times.never());
artistArtworkIndexerMock.verify((x) => x.refreshAllArtistsArtworkAsync(), Times.once());
});

it('should refresh all artists artwork except manually set images', async () => {
// Arrange
const sut: IndexingService = createSut();

// Act
await sut.indexArtistArtworkOnlyAsync(false, true);

// Assert
artistArtworkRepositoryMock.verify((x) => x.clearManuallySetFlag(), Times.once());
artistArtworkIndexerMock.verify((x) => x.refreshAllArtistsArtworkAsync(), Times.once());
});
});
Expand Down
Loading
Loading