Focus chrome was implemented twice, once in the focusable wrapper and once in the focus builders; both now go through FocusChrome. TvColorPicker's channel row was a copy of TvNumberSpinner and is now that widget in compact density. Also trims unused helpers and fields and simplifies the Jellyfin browse paths.
132 lines
4.5 KiB
Dart
132 lines
4.5 KiB
Dart
import 'dart:convert';
|
|
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:http/http.dart' as http;
|
|
import 'package:http/testing.dart';
|
|
import 'package:plezy/exceptions/media_server_exceptions.dart';
|
|
import 'package:plezy/services/plex_auth_service.dart';
|
|
import 'package:plezy/utils/media_server_http_client.dart';
|
|
|
|
void main() {
|
|
group('PlexAuthService', () {
|
|
test('fetchServers retries resources through plex.tv after clients host transport failure', () async {
|
|
final hosts = <String>[];
|
|
final client = MediaServerHttpClient(
|
|
client: MockClient((request) async {
|
|
hosts.add(request.url.host);
|
|
if (request.url.host == 'clients.plex.tv') {
|
|
throw http.ClientException('DNS failed', request.url);
|
|
}
|
|
return http.Response(jsonEncode([_serverJson()]), 200, headers: {'content-type': 'application/json'});
|
|
}),
|
|
);
|
|
addTearDown(client.close);
|
|
final auth = PlexAuthService.forTesting(http: client);
|
|
|
|
final servers = await auth.fetchServers('token');
|
|
|
|
expect(hosts, ['clients.plex.tv', 'plex.tv']);
|
|
expect(servers.single.clientIdentifier, 'srv-1');
|
|
});
|
|
|
|
test('fetchServers does not retry canonical host for HTTP auth failures', () async {
|
|
final hosts = <String>[];
|
|
final client = MediaServerHttpClient(
|
|
client: MockClient((request) async {
|
|
hosts.add(request.url.host);
|
|
return http.Response('{"errors":[]}', 401, headers: {'content-type': 'application/json'});
|
|
}),
|
|
);
|
|
addTearDown(client.close);
|
|
final auth = PlexAuthService.forTesting(http: client);
|
|
|
|
await expectLater(
|
|
auth.fetchServers('bad-token'),
|
|
throwsA(isA<MediaServerHttpException>().having((e) => e.statusCode, 'statusCode', 401)),
|
|
);
|
|
expect(hosts, ['clients.plex.tv']);
|
|
});
|
|
|
|
test('switchToUser tolerates drifted field shapes on the 201 body (#1488)', () async {
|
|
final client = MediaServerHttpClient(
|
|
client: MockClient((request) async {
|
|
expect(request.method, 'POST');
|
|
expect(request.url.host, 'clients.plex.tv');
|
|
expect(request.url.path, '/api/v2/home/users/uuid-1/switch');
|
|
return http.Response(
|
|
jsonEncode({
|
|
'id': 312174832,
|
|
'uuid': 'uuid-1',
|
|
'title': 'hi_phi',
|
|
'authToken': 'minted-user-token',
|
|
'profile': {
|
|
'defaultAudioLanguages': 'en,sv',
|
|
'defaultSubtitleLanguages': 'en,sv',
|
|
'mediaPostsVisibility': true,
|
|
},
|
|
}),
|
|
201,
|
|
headers: {'content-type': 'application/json'},
|
|
);
|
|
}),
|
|
);
|
|
addTearDown(client.close);
|
|
final auth = PlexAuthService.forTesting(http: client);
|
|
|
|
final token = await auth.switchToUser('uuid-1', 'account-token');
|
|
|
|
expect(token, 'minted-user-token');
|
|
});
|
|
|
|
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);
|
|
});
|
|
});
|
|
}
|
|
|
|
Map<String, dynamic> _serverJson() => {
|
|
'name': 'Home Server',
|
|
'clientIdentifier': 'srv-1',
|
|
'accessToken': 'server-token',
|
|
'owned': true,
|
|
'provides': 'server',
|
|
'connections': [
|
|
{
|
|
'protocol': 'https',
|
|
'address': '192.168.1.3',
|
|
'port': 32400,
|
|
'uri': 'https://192-168-1-3.machine.plex.direct:32400',
|
|
'local': true,
|
|
'relay': false,
|
|
'IPv6': false,
|
|
},
|
|
],
|
|
};
|