test: extract shared fixtures and scaffolds

Collapse duplicated setup across the suite into six shared helpers under
test/test_helpers/ and rewrite the 28 suites that were open-coding it:

  http_fixtures.dart         jsonResponse() for http.Response JSON stubs
  library_tab_scaffold.dart  pumps library tabs under their required ancestors
  multi_server_fixtures.dart MultiServerProvider wiring for widget tests
  playback_report_fakes.dart PlaybackReportCall + fake report sinks
  profile_stack.dart         production-shaped profile dependency graph
  theme.dart                 testMonoTokens for fast-settling widget tests

Net -1245 lines with no change in coverage or assertions.
This commit is contained in:
edde746
2026-07-26 06:09:47 +02:00
parent 04d8070fd4
commit 61344f7862
34 changed files with 1599 additions and 2505 deletions
+54 -143
View File
@@ -1,26 +1,19 @@
import 'dart:convert';
import 'package:drift/native.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/models/plex/plex_home_user.dart';
import 'package:plezy/profiles/active_profile_provider.dart';
import 'package:plezy/profiles/plex_home_service.dart';
import 'package:plezy/profiles/profile.dart';
import 'package:plezy/profiles/profile_connection.dart';
import 'package:plezy/profiles/profile_connection_registry.dart';
import 'package:plezy/profiles/profile_registry.dart';
import 'package:plezy/providers/user_profile_provider.dart';
import 'package:plezy/services/multi_server_manager.dart';
import 'package:plezy/services/plex_auth_service.dart';
import 'package:plezy/services/storage_service.dart';
import 'package:plezy/utils/media_server_http_client.dart';
import '../test_helpers/prefs.dart';
import '../test_helpers/profile_stack.dart';
void main() {
setUp(resetSharedPreferencesForTest);
@@ -57,30 +50,11 @@ void main() {
});
test('settings connection follows the profile default row', () async {
final db = AppDatabase.forTesting(NativeDatabase.memory());
final connections = ConnectionRegistry(db);
final profileConnections = ProfileConnectionRegistry(db);
final profiles = ProfileRegistry(db);
final storage = await StorageService.getInstance();
final plexHome = PlexHomeService(
connections: connections,
profileConnections: profileConnections,
storage: storage,
plexHomeUserFetcher: (_) async => const [],
);
final active = ActiveProfileProvider(
registry: profiles,
plexHome: plexHome,
connections: connections,
storage: storage,
);
final stack = await ProfileStack.create();
final manager = MultiServerManager();
addTearDown(() async {
manager.dispose();
await active.resetForTesting();
active.dispose();
await plexHome.dispose();
await db.close();
await stack.dispose();
});
final profile = Profile.local(id: 'local-owner', displayName: 'Owner', createdAt: DateTime(2026, 1, 1));
@@ -102,10 +76,10 @@ void main() {
deviceId: 'device-a',
createdAt: DateTime(2026, 1, 1),
);
await profiles.upsert(profile);
await connections.upsert(plex);
await connections.upsert(jellyfin);
await profileConnections.upsert(
await stack.profiles.upsert(profile);
await stack.connections.upsert(plex);
await stack.connections.upsert(jellyfin);
await stack.profileConnections.upsert(
ProfileConnection(
profileId: profile.id,
connectionId: plex.id,
@@ -115,53 +89,36 @@ void main() {
),
makeDefault: true,
);
await profileConnections.upsert(
await stack.profileConnections.upsert(
ProfileConnection(profileId: profile.id, connectionId: jellyfin.id, userIdentifier: jellyfin.userId),
);
await storage.setActiveProfileId(profile.id);
await active.initialize();
await stack.storage.setActiveProfileId(profile.id);
await stack.active.initialize();
final p = UserProfileProvider()
..attach(
connections: connections,
activeProfile: active,
profileConnections: profileConnections,
connections: stack.connections,
activeProfile: stack.active,
profileConnections: stack.profileConnections,
serverManager: manager,
);
addTearDown(p.dispose);
expect(await p.debugResolveActiveSettingsConnectionForTesting(), isA<PlexAccountConnection>());
await profileConnections.setDefault(profile.id, jellyfin.id);
await stack.profileConnections.setDefault(profile.id, jellyfin.id);
expect(await p.debugResolveActiveSettingsConnectionForTesting(), isA<JellyfinConnection>());
});
test('watches Plex Home profile connection rows', () async {
final db = AppDatabase.forTesting(NativeDatabase.memory());
final connections = ConnectionRegistry(db);
final profileConnections = ProfileConnectionRegistry(db);
final profiles = ProfileRegistry(db);
final storage = await StorageService.getInstance();
final plexHome = PlexHomeService(
connections: connections,
profileConnections: profileConnections,
storage: storage,
plexHomeUserFetcher: (_) async => [_homeUser(uuid: 'home-user-a', title: 'Home User')],
);
final active = ActiveProfileProvider(
registry: profiles,
plexHome: plexHome,
connections: connections,
storage: storage,
final stack = await ProfileStack.create(
homeUsers: [_homeUser(uuid: 'home-user-a', title: 'Home User')],
);
final manager = MultiServerManager();
addTearDown(() async {
manager.dispose();
await active.resetForTesting();
active.dispose();
await plexHome.dispose();
await db.close();
await stack.dispose();
});
final account = PlexAccountConnection(
@@ -171,21 +128,23 @@ void main() {
accountLabel: 'Plex A',
createdAt: DateTime(2026, 1, 1),
);
await connections.upsert(account);
await plexHome.refresh(account);
await storage.setActiveProfileId(plexHomeProfileId(accountConnectionId: account.id, homeUserUuid: 'home-user-a'));
await active.initialize();
await stack.connections.upsert(account);
await stack.plexHome.refresh(account);
await stack.storage.setActiveProfileId(
plexHomeProfileId(accountConnectionId: account.id, homeUserUuid: 'home-user-a'),
);
await stack.active.initialize();
final p = UserProfileProvider()
..attach(
connections: connections,
activeProfile: active,
profileConnections: profileConnections,
connections: stack.connections,
activeProfile: stack.active,
profileConnections: stack.profileConnections,
serverManager: manager,
);
addTearDown(p.dispose);
expect(p.debugWatchedProfileConnectionProfileId, active.activeId);
expect(p.debugWatchedProfileConnectionProfileId, stack.active.activeId);
});
test('Plex Home profile without a switched token makes no user request', () async {
@@ -231,30 +190,11 @@ void main() {
});
test('Plex token fallback uses the selected local profile account', () async {
final db = AppDatabase.forTesting(NativeDatabase.memory());
final connections = ConnectionRegistry(db);
final profileConnections = ProfileConnectionRegistry(db);
final profiles = ProfileRegistry(db);
final storage = await StorageService.getInstance();
final plexHome = PlexHomeService(
connections: connections,
profileConnections: profileConnections,
storage: storage,
plexHomeUserFetcher: (_) async => const [],
);
final active = ActiveProfileProvider(
registry: profiles,
plexHome: plexHome,
connections: connections,
storage: storage,
);
final stack = await ProfileStack.create();
final manager = MultiServerManager();
addTearDown(() async {
manager.dispose();
await active.resetForTesting();
active.dispose();
await plexHome.dispose();
await db.close();
await stack.dispose();
});
final profile = Profile.local(id: 'local-owner', displayName: 'Owner', createdAt: DateTime(2026, 1, 1));
@@ -272,10 +212,10 @@ void main() {
accountLabel: 'Plex B',
createdAt: DateTime(2026, 1, 1),
);
await profiles.upsert(profile);
await connections.upsert(accountA);
await connections.upsert(accountB);
await profileConnections.upsert(
await stack.profiles.upsert(profile);
await stack.connections.upsert(accountA);
await stack.connections.upsert(accountB);
await stack.profileConnections.upsert(
ProfileConnection(
profileId: profile.id,
connectionId: accountB.id,
@@ -284,8 +224,8 @@ void main() {
),
makeDefault: true,
);
await storage.setActiveProfileId(profile.id);
await active.initialize();
await stack.storage.setActiveProfileId(profile.id);
await stack.active.initialize();
final requests = <http.Request>[];
final auth = _recordingAuth(requests, audioLanguage: 'fra');
@@ -293,9 +233,9 @@ void main() {
final p = UserProfileProvider(authService: auth)
..attach(
connections: connections,
activeProfile: active,
profileConnections: profileConnections,
connections: stack.connections,
activeProfile: stack.active,
profileConnections: stack.profileConnections,
serverManager: manager,
);
addTearDown(p.dispose);
@@ -356,39 +296,16 @@ PlexAuthService _recordingAuth(List<http.Request> requests, {required String aud
}
class _HomeProfileFixture {
_HomeProfileFixture({
required this.db,
required this.active,
required this.plexHome,
required this.auth,
required this.provider,
required this.requests,
});
_HomeProfileFixture({required this.stack, required this.auth, required this.provider, required this.requests});
final AppDatabase db;
final ActiveProfileProvider active;
final PlexHomeService plexHome;
final ProfileStack stack;
final PlexAuthService auth;
final UserProfileProvider provider;
final List<http.Request> requests;
static Future<_HomeProfileFixture> create({String? switchedToken}) async {
final db = AppDatabase.forTesting(NativeDatabase.memory());
final connections = ConnectionRegistry(db);
final profileConnections = ProfileConnectionRegistry(db);
final profiles = ProfileRegistry(db);
final storage = await StorageService.getInstance();
final plexHome = PlexHomeService(
connections: connections,
profileConnections: profileConnections,
storage: storage,
plexHomeUserFetcher: (_) async => [_homeUser(uuid: 'home-user-a', title: 'Home User')],
);
final active = ActiveProfileProvider(
registry: profiles,
plexHome: plexHome,
connections: connections,
storage: storage,
final stack = await ProfileStack.create(
homeUsers: [_homeUser(uuid: 'home-user-a', title: 'Home User')],
);
final account = PlexAccountConnection(
id: 'plex-parent',
@@ -397,12 +314,12 @@ class _HomeProfileFixture {
accountLabel: 'Plex Parent',
createdAt: DateTime(2026, 1, 1),
);
await connections.upsert(account);
await plexHome.refresh(account);
await stack.connections.upsert(account);
await stack.plexHome.refresh(account);
final activeId = plexHomeProfileId(accountConnectionId: account.id, homeUserUuid: 'home-user-a');
if (switchedToken != null) {
await profileConnections.upsert(
await stack.profileConnections.upsert(
ProfileConnection(
profileId: activeId,
connectionId: account.id,
@@ -413,29 +330,23 @@ class _HomeProfileFixture {
makeDefault: true,
);
}
await storage.setActiveProfileId(activeId);
await active.initialize();
await stack.storage.setActiveProfileId(activeId);
await stack.active.initialize();
final requests = <http.Request>[];
final auth = _recordingAuth(requests, audioLanguage: 'jpn');
final provider = UserProfileProvider(authService: auth)
..attach(connections: connections, activeProfile: active, profileConnections: profileConnections);
return _HomeProfileFixture(
db: db,
active: active,
plexHome: plexHome,
auth: auth,
provider: provider,
requests: requests,
);
..attach(
connections: stack.connections,
activeProfile: stack.active,
profileConnections: stack.profileConnections,
);
return _HomeProfileFixture(stack: stack, auth: auth, provider: provider, requests: requests);
}
Future<void> dispose() async {
provider.dispose();
auth.dispose();
await active.resetForTesting();
active.dispose();
await plexHome.dispose();
await db.close();
await stack.dispose();
}
}