refactor(media): migrate media item to freezed
This commit is contained in:
@@ -2,6 +2,9 @@ import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:plezy/media/media_backend.dart';
|
||||
import 'package:plezy/media/media_item.dart';
|
||||
import 'package:plezy/media/media_kind.dart';
|
||||
import 'package:plezy/media/media_part.dart';
|
||||
import 'package:plezy/media/media_role.dart';
|
||||
import 'package:plezy/media/media_version.dart';
|
||||
|
||||
/// Backend-agnostic [MediaItem] tests. Existing coverage is split between
|
||||
/// `plex_mappers_test` and `jellyfin_mappers_test` — those exercise the
|
||||
@@ -187,6 +190,137 @@ void main() {
|
||||
expect(original.copyWith(title: 'New').backend, backend, reason: 'copyWith must preserve backend');
|
||||
}
|
||||
});
|
||||
|
||||
test('preserves Plex-only fields when omitted', () {
|
||||
const original = PlexMediaItem(
|
||||
id: 'p1',
|
||||
kind: MediaKind.movie,
|
||||
title: 'Old',
|
||||
editionTitle: 'Director Cut',
|
||||
audienceRating: 8.9,
|
||||
ratingImage: 'rottentomatoes://rating',
|
||||
audienceRatingImage: 'rottentomatoes://audience',
|
||||
subtitleLanguage: 'eng',
|
||||
subtitleMode: 1,
|
||||
trailerKey: '/library/metadata/1',
|
||||
playlistItemId: 42,
|
||||
playQueueItemId: 7,
|
||||
subtype: 'trailer',
|
||||
extraType: 1,
|
||||
);
|
||||
|
||||
final copy = original.copyWith(title: 'New');
|
||||
|
||||
expect(copy.title, 'New');
|
||||
expect(copy.editionTitle, 'Director Cut');
|
||||
expect(copy.audienceRating, 8.9);
|
||||
expect(copy.ratingImage, 'rottentomatoes://rating');
|
||||
expect(copy.audienceRatingImage, 'rottentomatoes://audience');
|
||||
expect(copy.subtitleLanguage, 'eng');
|
||||
expect(copy.subtitleMode, 1);
|
||||
expect(copy.trailerKey, '/library/metadata/1');
|
||||
expect(copy.playlistItemId, 42);
|
||||
expect(copy.playQueueItemId, 7);
|
||||
expect(copy.subtype, 'trailer');
|
||||
expect(copy.extraType, 1);
|
||||
});
|
||||
|
||||
test('preserves Jellyfin playlist item id when omitted', () {
|
||||
const original = JellyfinMediaItem(
|
||||
id: 'j1',
|
||||
kind: MediaKind.movie,
|
||||
title: 'Old',
|
||||
playlistItemId: 'playlist-entry-1',
|
||||
);
|
||||
|
||||
final copy = original.copyWith(title: 'New');
|
||||
|
||||
expect(copy.title, 'New');
|
||||
expect(copy.playlistItemId, 'playlist-entry-1');
|
||||
});
|
||||
|
||||
test('can clear nullable fields explicitly', () {
|
||||
final original = _movie(title: 'Movie', viewCount: 1, durationMs: 1000, viewOffsetMs: 500);
|
||||
|
||||
final copy = original.copyWith(title: null, viewOffsetMs: null);
|
||||
|
||||
expect(copy.title, isNull);
|
||||
expect(copy.viewOffsetMs, isNull);
|
||||
expect(copy.viewCount, 1);
|
||||
});
|
||||
});
|
||||
|
||||
group('MediaItem JSON', () {
|
||||
test('round-trips Plex-only fields', () {
|
||||
const original = PlexMediaItem(
|
||||
id: 'p1',
|
||||
kind: MediaKind.movie,
|
||||
title: 'Movie',
|
||||
editionTitle: 'Theatrical',
|
||||
audienceRating: 9.1,
|
||||
ratingImage: 'rottentomatoes://rating',
|
||||
audienceRatingImage: 'rottentomatoes://audience',
|
||||
genres: ['Drama'],
|
||||
roles: [MediaRole(id: '1', tag: 'Actor', role: 'Lead', thumbPath: '/photo')],
|
||||
mediaVersions: [
|
||||
MediaVersion(
|
||||
id: 'v1',
|
||||
width: 1920,
|
||||
height: 1080,
|
||||
parts: [MediaPart(id: 'part1', streamPath: '/stream', sizeBytes: 1000)],
|
||||
),
|
||||
],
|
||||
subtitleLanguage: 'eng',
|
||||
subtitleMode: 2,
|
||||
trailerKey: '/trailer',
|
||||
playlistItemId: 4,
|
||||
playQueueItemId: 5,
|
||||
subtype: 'trailer',
|
||||
extraType: 9,
|
||||
);
|
||||
|
||||
final json = original.toJson();
|
||||
final decoded = MediaItem.fromJson(json);
|
||||
|
||||
expect(json['backend'], 'plex');
|
||||
expect(json.containsKey('summary'), isFalse);
|
||||
expect(decoded, isA<PlexMediaItem>());
|
||||
final plex = decoded as PlexMediaItem;
|
||||
expect(plex.editionTitle, 'Theatrical');
|
||||
expect(plex.audienceRating, 9.1);
|
||||
expect(plex.ratingImage, 'rottentomatoes://rating');
|
||||
expect(plex.audienceRatingImage, 'rottentomatoes://audience');
|
||||
expect(plex.genres, ['Drama']);
|
||||
expect(plex.roles?.single.tag, 'Actor');
|
||||
expect(plex.mediaVersions?.single.parts.single.streamPath, '/stream');
|
||||
expect(plex.subtitleLanguage, 'eng');
|
||||
expect(plex.subtitleMode, 2);
|
||||
expect(plex.trailerKey, '/trailer');
|
||||
expect(plex.playlistItemId, 4);
|
||||
expect(plex.playQueueItemId, 5);
|
||||
expect(plex.subtype, 'trailer');
|
||||
expect(plex.extraType, 9);
|
||||
});
|
||||
|
||||
test('round-trips Jellyfin playlist item id', () {
|
||||
const original = JellyfinMediaItem(id: 'j1', kind: MediaKind.movie, title: 'Movie', playlistItemId: 'entry-1');
|
||||
|
||||
final json = original.toJson();
|
||||
final decoded = MediaItem.fromJson(json);
|
||||
|
||||
expect(json['backend'], 'jellyfin');
|
||||
expect(decoded, isA<JellyfinMediaItem>());
|
||||
expect((decoded as JellyfinMediaItem).playlistItemId, 'entry-1');
|
||||
});
|
||||
|
||||
test('missing backend keeps legacy Plex fallback', () {
|
||||
final decoded = MediaItem.fromJson({'id': 'legacy', 'kind': 'movie'});
|
||||
|
||||
expect(decoded, isA<PlexMediaItem>());
|
||||
expect(decoded.backend, MediaBackend.plex);
|
||||
expect(decoded.id, 'legacy');
|
||||
expect(decoded.kind, MediaKind.movie);
|
||||
});
|
||||
});
|
||||
|
||||
group('MediaItem.displayTitle', () {
|
||||
|
||||
Reference in New Issue
Block a user