Files
plezy/test/providers/libraries_provider_test.dart
T
2026-05-01 01:20:36 +02:00

119 lines
3.7 KiB
Dart

import 'package:flutter_test/flutter_test.dart';
import 'package:plezy/media/media_backend.dart';
import 'package:plezy/media/media_kind.dart';
import 'package:plezy/media/media_library.dart';
import 'package:plezy/providers/libraries_provider.dart';
import 'package:plezy/services/storage_service.dart';
import '../test_helpers/prefs.dart';
MediaLibrary _lib(String key, {String type = 'movie', String? serverId, String title = 'L'}) => MediaLibrary(
id: key,
backend: MediaBackend.plex,
title: title,
kind: MediaKind.fromString(type),
serverId: serverId,
);
void main() {
setUp(resetSharedPreferencesForTest);
group('LibrariesProvider', () {
test('starts with initial empty state', () {
final p = LibrariesProvider();
expect(p.libraries, isEmpty);
expect(p.hasLibraries, isFalse);
expect(p.isLoading, isFalse);
expect(p.hasLoaded, isFalse);
expect(p.loadState, LibrariesLoadState.initial);
expect(p.errorMessage, isNull);
p.dispose();
});
test('loadLibraries before initialize is a no-op', () async {
final p = LibrariesProvider();
var notified = 0;
p.addListener(() => notified++);
await p.loadLibraries();
// Without a DataAggregationService the load short-circuits with no
// state transition and no listener notification.
expect(p.loadState, LibrariesLoadState.initial);
expect(p.libraries, isEmpty);
expect(notified, 0);
p.dispose();
});
test('refresh before initialize is a no-op', () async {
final p = LibrariesProvider();
var notified = 0;
p.addListener(() => notified++);
await p.refresh();
expect(p.loadState, LibrariesLoadState.initial);
expect(notified, 0);
p.dispose();
});
test('updateLibraryOrder updates list, notifies, and persists order', () async {
final p = LibrariesProvider();
var notified = 0;
p.addListener(() => notified++);
final libs = [
_lib('1', serverId: 'srv', title: 'A'),
_lib('2', serverId: 'srv', title: 'B'),
_lib('3', serverId: 'srv', title: 'C'),
];
await p.updateLibraryOrder(libs);
expect(p.libraries.length, 3);
expect(p.libraries.map((l) => l.title), ['A', 'B', 'C']);
expect(notified, 1);
// Persisted to storage as the list of globalKeys.
final storage = await StorageService.getInstance();
expect(storage.getLibraryOrder(), equals(libs.map((l) => l.globalKey).toList()));
p.dispose();
});
test('libraries getter returns an unmodifiable list', () async {
final p = LibrariesProvider();
await p.updateLibraryOrder([_lib('1', serverId: 'srv')]);
expect(() => p.libraries.add(_lib('mutated')), throwsUnsupportedError);
p.dispose();
});
test('clear resets state to initial and notifies', () async {
final p = LibrariesProvider();
await p.updateLibraryOrder([_lib('1', serverId: 'srv'), _lib('2', serverId: 'srv')]);
expect(p.libraries, hasLength(2));
var notified = 0;
p.addListener(() => notified++);
p.clear();
expect(p.libraries, isEmpty);
expect(p.hasLibraries, isFalse);
expect(p.loadState, LibrariesLoadState.initial);
expect(p.errorMessage, isNull);
expect(notified, 1);
p.dispose();
});
test('safeNotifyListeners after dispose is a no-op', () async {
final p = LibrariesProvider();
p.dispose();
// Post-dispose clear / updateLibraryOrder must not throw — the provider
// uses `safeNotifyListeners` which swallows post-dispose firings.
p.clear();
await p.updateLibraryOrder([_lib('1', serverId: 'srv')]);
});
});
}