185 lines
6.3 KiB
Dart
185 lines
6.3 KiB
Dart
import 'package:drift/native.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:http/http.dart' as http;
|
|
import 'package:http/testing.dart';
|
|
import 'package:plezy/connection/connection.dart';
|
|
import 'package:plezy/connection/connection_registry.dart';
|
|
import 'package:plezy/database/app_database.dart';
|
|
import 'package:plezy/i18n/strings.g.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/metadata_edit/metadata_edit_adapters.dart';
|
|
import 'package:plezy/models/plex/plex_home_user.dart';
|
|
import 'package:plezy/profiles/profile.dart';
|
|
import 'package:plezy/profiles/active_profile_provider.dart';
|
|
import 'package:plezy/profiles/plex_home_service.dart';
|
|
import 'package:plezy/profiles/profile_connection_registry.dart';
|
|
import 'package:plezy/profiles/profile_registry.dart';
|
|
import 'package:plezy/providers/multi_server_provider.dart';
|
|
import 'package:plezy/services/data_aggregation_service.dart';
|
|
import 'package:plezy/services/jellyfin_client.dart';
|
|
import 'package:plezy/services/multi_server_manager.dart';
|
|
import 'package:plezy/theme/mono_theme.dart';
|
|
import 'package:plezy/utils/platform_detector.dart';
|
|
import 'package:plezy/widgets/media_context_menu.dart';
|
|
import 'package:provider/provider.dart';
|
|
|
|
void main() {
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
|
|
group('isAdminActionAllowedForMediaItem', () {
|
|
test('blocks non-admin Plex Home users on Plex items', () {
|
|
final profile = Profile.virtualPlexHome(connectionId: 'plex-1', homeUser: _homeUser(admin: false));
|
|
|
|
expect(
|
|
isAdminActionAllowedForMediaItem(isOwnerOrAdmin: true, itemBackend: MediaBackend.plex, activeProfile: profile),
|
|
isFalse,
|
|
);
|
|
});
|
|
|
|
test('does not apply Plex Home role to Jellyfin items', () {
|
|
final profile = Profile.virtualPlexHome(connectionId: 'plex-1', homeUser: _homeUser(admin: false));
|
|
|
|
expect(
|
|
isAdminActionAllowedForMediaItem(
|
|
isOwnerOrAdmin: true,
|
|
itemBackend: MediaBackend.jellyfin,
|
|
activeProfile: profile,
|
|
),
|
|
isTrue,
|
|
);
|
|
});
|
|
|
|
test('allows Plex admin Home users on Plex items', () {
|
|
final profile = Profile.virtualPlexHome(connectionId: 'plex-1', homeUser: _homeUser(admin: true));
|
|
|
|
expect(
|
|
isAdminActionAllowedForMediaItem(isOwnerOrAdmin: true, itemBackend: MediaBackend.plex, activeProfile: profile),
|
|
isTrue,
|
|
);
|
|
});
|
|
});
|
|
|
|
group('supportsMetadataEdit', () {
|
|
test('allows Jellyfin video metadata edit through capability gate', () {
|
|
final client = JellyfinClient.forTesting(
|
|
connection: _jellyfinConnection(),
|
|
httpClient: MockClient((_) async => http.Response('', 204)),
|
|
);
|
|
addTearDown(client.close);
|
|
|
|
expect(supportsMetadataEdit(client, MediaKind.movie), isTrue);
|
|
expect(supportsMetadataEdit(client, MediaKind.show), isTrue);
|
|
expect(supportsMetadataEdit(client, MediaKind.track), isFalse);
|
|
});
|
|
});
|
|
|
|
group('MediaContextMenu actions', () {
|
|
testWidgets('file info client resolution failure shows an error without popping another route', (tester) async {
|
|
LocaleSettings.setLocaleSync(AppLocale.en);
|
|
TvDetectionService.debugSetAppleTVOverride(true);
|
|
addTearDown(() => TvDetectionService.debugSetAppleTVOverride(null));
|
|
|
|
final db = AppDatabase.forTesting(NativeDatabase.memory());
|
|
final manager = MultiServerManager();
|
|
final multiServerProvider = MultiServerProvider(manager, DataAggregationService(manager));
|
|
final connections = ConnectionRegistry(db);
|
|
final profileConnections = ProfileConnectionRegistry(db);
|
|
final plexHome = PlexHomeService(
|
|
connections: connections,
|
|
profileConnections: profileConnections,
|
|
plexHomeUserFetcher: (_) async => const [],
|
|
);
|
|
final activeProfileProvider = ActiveProfileProvider(
|
|
registry: ProfileRegistry(db),
|
|
plexHome: plexHome,
|
|
connections: connections,
|
|
);
|
|
addTearDown(() async {
|
|
activeProfileProvider.dispose();
|
|
await plexHome.dispose();
|
|
multiServerProvider.dispose();
|
|
manager.dispose();
|
|
await db.close();
|
|
});
|
|
|
|
final menuKey = GlobalKey<MediaContextMenuState>();
|
|
final item = MediaItem(
|
|
id: 'movie-1',
|
|
backend: MediaBackend.jellyfin,
|
|
kind: MediaKind.movie,
|
|
title: 'Movie',
|
|
serverId: 'missing-server',
|
|
);
|
|
|
|
await tester.pumpWidget(
|
|
TranslationProvider(
|
|
child: MultiProvider(
|
|
providers: [
|
|
ChangeNotifierProvider<MultiServerProvider>.value(value: multiServerProvider),
|
|
ChangeNotifierProvider<ActiveProfileProvider>.value(value: activeProfileProvider),
|
|
],
|
|
child: MaterialApp(
|
|
theme: monoTheme(dark: true),
|
|
home: Scaffold(
|
|
body: Center(
|
|
child: MediaContextMenu(
|
|
key: menuKey,
|
|
item: item,
|
|
child: const SizedBox(width: 120, height: 80, child: Text('target')),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
|
|
menuKey.currentState!.showContextMenu(tester.element(find.text('target')));
|
|
await tester.pumpAndSettle();
|
|
|
|
await tester.tap(find.text(t.mediaMenu.fileInfo));
|
|
await tester.pumpAndSettle();
|
|
|
|
expect(tester.takeException(), isNull);
|
|
expect(find.byType(SnackBar), findsOneWidget);
|
|
expect(find.text('target'), findsOneWidget);
|
|
});
|
|
});
|
|
}
|
|
|
|
PlexHomeUser _homeUser({required bool admin}) {
|
|
return PlexHomeUser(
|
|
id: 0,
|
|
uuid: 'home-user',
|
|
title: 'Home User',
|
|
username: null,
|
|
email: null,
|
|
friendlyName: null,
|
|
thumb: 'https://plex.tv/users/home-user/avatar',
|
|
hasPassword: false,
|
|
restricted: false,
|
|
updatedAt: null,
|
|
admin: admin,
|
|
guest: false,
|
|
protected: false,
|
|
);
|
|
}
|
|
|
|
JellyfinConnection _jellyfinConnection() {
|
|
return JellyfinConnection(
|
|
id: 'srv-1/user-1',
|
|
baseUrl: 'https://jf.example.com',
|
|
serverName: 'Home',
|
|
serverMachineId: 'srv-1',
|
|
userId: 'user-1',
|
|
userName: 'edde',
|
|
accessToken: 'tok',
|
|
deviceId: 'dev',
|
|
isAdministrator: true,
|
|
createdAt: DateTime.fromMillisecondsSinceEpoch(0),
|
|
);
|
|
}
|