fix(plex): tolerate scalar schema drift
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:plezy/models/plex/plex_home.dart';
|
||||
|
||||
void main() {
|
||||
test('PlexHome tolerates scalar drift from the account API', () {
|
||||
final home = PlexHome.fromJson({
|
||||
'id': '7',
|
||||
'name': 42,
|
||||
'guestUserID': '9',
|
||||
'guestUserUUID': 123,
|
||||
'guestEnabled': 1,
|
||||
'subscription': 'true',
|
||||
'users': <dynamic>[],
|
||||
});
|
||||
|
||||
expect(home.id, 7);
|
||||
expect(home.name, '42');
|
||||
expect(home.guestUserID, 9);
|
||||
expect(home.guestUserUUID, '123');
|
||||
expect(home.guestEnabled, isTrue);
|
||||
expect(home.subscription, isTrue);
|
||||
});
|
||||
}
|
||||
@@ -14,14 +14,14 @@ void main() {
|
||||
test('captures the first video stream and accumulates audio + subs', () {
|
||||
final streams = [
|
||||
// streamType 1=video, 2=audio, 3=subtitle
|
||||
{'streamType': 1, 'id': 100, 'frameRate': 23.976, 'colorSpace': 'bt709'},
|
||||
{'streamType': '1', 'id': '100', 'frameRate': 23.976, 'colorSpace': 'bt709'},
|
||||
{
|
||||
'streamType': 2,
|
||||
'id': 101,
|
||||
'index': 1,
|
||||
'streamType': '2',
|
||||
'id': '101',
|
||||
'index': '1',
|
||||
'codec': 'eac3',
|
||||
'language': 'English',
|
||||
'channels': 6,
|
||||
'channels': '6',
|
||||
'selected': true,
|
||||
'displayTitle': 'English (EAC3 5.1)',
|
||||
},
|
||||
@@ -35,9 +35,9 @@ void main() {
|
||||
'selected': false,
|
||||
},
|
||||
{
|
||||
'streamType': 3,
|
||||
'id': 200,
|
||||
'index': 3,
|
||||
'streamType': '3',
|
||||
'id': '200',
|
||||
'index': '3',
|
||||
'codec': 'srt',
|
||||
'language': 'English',
|
||||
'forced': false,
|
||||
@@ -48,8 +48,8 @@ void main() {
|
||||
|
||||
final out = walkStreams(streams, reader);
|
||||
|
||||
expect(out.videoStream?['id'], 100);
|
||||
expect(out.audioStream?['id'], 101);
|
||||
expect(out.videoStream?['id'], '100');
|
||||
expect(out.audioStream?['id'], '101');
|
||||
expect(out.videoStream?['frameRate'], closeTo(23.976, 1e-6));
|
||||
expect(out.audioTracks.map((t) => t.id), [101, 102]);
|
||||
expect(out.audioTracks[0].channels, 6);
|
||||
|
||||
@@ -79,6 +79,37 @@ void main() {
|
||||
expect(response.profile.defaultAudioLanguages, ['en', 'sv']);
|
||||
expect(response.profile.defaultSubtitleLanguages, ['en', 'sv']);
|
||||
});
|
||||
|
||||
test('fetchServers tolerates scalar drift in server and connection fields', () async {
|
||||
final server = _serverJson()
|
||||
..['owned'] = '1'
|
||||
..['presence'] = 1
|
||||
..['product'] = 42
|
||||
..['lastSeenAt'] = 123;
|
||||
final connection = (server['connections'] as List).single as Map<String, dynamic>
|
||||
..['port'] = '32400'
|
||||
..['local'] = '1'
|
||||
..['relay'] = 0
|
||||
..['IPv6'] = 'false';
|
||||
final client = MediaServerHttpClient(
|
||||
client: MockClient(
|
||||
(_) async => http.Response(jsonEncode([server]), 200, headers: {'content-type': 'application/json'}),
|
||||
),
|
||||
);
|
||||
addTearDown(client.close);
|
||||
|
||||
final servers = await PlexAuthService.forTesting(http: client).fetchServers('token');
|
||||
|
||||
expect(servers.single.owned, isTrue);
|
||||
expect(servers.single.presence, isTrue);
|
||||
expect(servers.single.product, '42');
|
||||
expect(servers.single.lastSeenAt, isNull);
|
||||
expect(connection['port'], '32400');
|
||||
expect(servers.single.connections.first.port, 32400);
|
||||
expect(servers.single.connections.first.local, isTrue);
|
||||
expect(servers.single.connections.first.relay, isFalse);
|
||||
expect(servers.single.connections.first.ipv6, isFalse);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:drift/native.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
@@ -53,4 +55,34 @@ void main() {
|
||||
expect(await client.createCollectionFromUri(sectionId: '1', title: 'Collection', uri: 'server://items'), isNull);
|
||||
expect(await client.createPlayQueue(uri: 'server://items', type: 'video'), isNull);
|
||||
});
|
||||
|
||||
test('play queue accepts numeric strings from Plex', () async {
|
||||
final client = makeClient(
|
||||
(_) async => http.Response(
|
||||
jsonEncode({
|
||||
'MediaContainer': {
|
||||
'playQueueID': '42',
|
||||
'playQueueSelectedItemID': '7',
|
||||
'playQueueSelectedItemOffset': '1',
|
||||
'playQueueTotalCount': '3',
|
||||
'playQueueVersion': '5',
|
||||
'size': '3',
|
||||
'Metadata': <dynamic>[],
|
||||
},
|
||||
}),
|
||||
200,
|
||||
headers: {'content-type': 'application/json'},
|
||||
),
|
||||
);
|
||||
addTearDown(client.close);
|
||||
|
||||
final queue = await client.createPlayQueue(uri: 'server://items', type: 'video');
|
||||
|
||||
expect(queue?.playQueueID, 42);
|
||||
expect(queue?.playQueueSelectedItemID, 7);
|
||||
expect(queue?.playQueueSelectedItemOffset, 1);
|
||||
expect(queue?.playQueueTotalCount, 3);
|
||||
expect(queue?.playQueueVersion, 5);
|
||||
expect(queue?.size, 3);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -9,6 +9,19 @@ const _serverId = 'plex-machine-1';
|
||||
const _serverName = 'Home';
|
||||
|
||||
void main() {
|
||||
test('PlexMetadataDto accepts string ratings', () {
|
||||
final dto = PlexMetadataDto.fromJson({
|
||||
'ratingKey': '1',
|
||||
'rating': '8.8',
|
||||
'audienceRating': '9.1',
|
||||
'userRating': '9.5',
|
||||
});
|
||||
|
||||
expect(dto.rating, 8.8);
|
||||
expect(dto.audienceRating, 9.1);
|
||||
expect(dto.userRating, 9.5);
|
||||
});
|
||||
|
||||
group('PlexMappers.mediaItem (movie)', () {
|
||||
test('maps a Plex movie with watch state, ratings, genres, and people', () {
|
||||
final json = {
|
||||
|
||||
@@ -343,32 +343,39 @@ void main() {
|
||||
'container': 'mkv',
|
||||
'videoCodec': 'h264',
|
||||
'videoResolution': '1080',
|
||||
'width': 1920,
|
||||
'height': 1080,
|
||||
'aspectRatio': 1.78,
|
||||
'bitrate': 8000,
|
||||
'duration': 120000,
|
||||
'width': '1920',
|
||||
'height': '1080',
|
||||
'aspectRatio': '1.78',
|
||||
'bitrate': '8000',
|
||||
'duration': '120000',
|
||||
'audioCodec': 'aac',
|
||||
'audioChannels': 2,
|
||||
'audioChannels': '2',
|
||||
'optimizedForStreaming': '1',
|
||||
'has64bitOffsets': 0,
|
||||
'Part': [
|
||||
{
|
||||
'file': '/media/movie.mkv',
|
||||
'size': 123456,
|
||||
'size': '123456',
|
||||
'Stream': [
|
||||
{'streamType': 1, 'frameRate': 24, 'colorSpace': 'bt709', 'bitDepth': 8, 'bitrate': 7000},
|
||||
{'streamType': '1', 'frameRate': '24', 'colorSpace': 'bt709', 'bitDepth': '8', 'bitrate': '7000'},
|
||||
{
|
||||
'streamType': 2,
|
||||
'id': 301,
|
||||
'index': 0,
|
||||
'streamType': '2',
|
||||
'id': '301',
|
||||
'index': '0',
|
||||
'language': 'English',
|
||||
'languageCode': 'eng',
|
||||
'channels': 2,
|
||||
'channels': '2',
|
||||
'selected': true,
|
||||
'audioChannelLayout': 'stereo',
|
||||
},
|
||||
{'streamType': 3, 'id': 401, 'index': 0, 'languageCode': 'eng', 'forced': 0, 'key': '/subtitles/401'},
|
||||
{
|
||||
'streamType': '3',
|
||||
'id': '401',
|
||||
'index': '0',
|
||||
'languageCode': 'eng',
|
||||
'forced': 0,
|
||||
'key': '/subtitles/401',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user