180 lines
6.3 KiB
Dart
180 lines
6.3 KiB
Dart
import 'package:bible_tracker/data/bible.dart';
|
|
import 'package:bible_tracker/models/tracker.dart';
|
|
import 'package:bible_tracker/services/tracker_service.dart';
|
|
import 'package:bible_tracker/services/tracker_storage.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
Future<ProviderContainer> _container() async {
|
|
SharedPreferences.setMockInitialValues(<String, Object>{});
|
|
final prefs = await SharedPreferences.getInstance();
|
|
return ProviderContainer(
|
|
overrides: <Override>[sharedPreferencesProvider.overrideWithValue(prefs)],
|
|
);
|
|
}
|
|
|
|
Future<List<Tracker>> _waitForData(ProviderContainer container) async {
|
|
while (true) {
|
|
final AsyncValue<List<Tracker>> state = container.read(
|
|
trackerServiceProvider,
|
|
);
|
|
if (state.hasValue) return state.value!;
|
|
await Future<void>.delayed(const Duration(milliseconds: 5));
|
|
}
|
|
}
|
|
|
|
void main() {
|
|
TestWidgetsFlutterBinding.ensureInitialized();
|
|
|
|
test('starts empty after initial load', () async {
|
|
final container = await _container();
|
|
addTearDown(container.dispose);
|
|
final List<Tracker> data = await _waitForData(container);
|
|
expect(data, isEmpty);
|
|
});
|
|
|
|
test('create adds a tracker with the given name and color', () async {
|
|
final container = await _container();
|
|
addTearDown(container.dispose);
|
|
await _waitForData(container);
|
|
|
|
final tracker = await container
|
|
.read(trackerServiceProvider.notifier)
|
|
.create(name: 'My Plan', color: const Color(0xFF123456));
|
|
|
|
expect(tracker.name, 'My Plan');
|
|
expect(tracker.colorValue, const Color(0xFF123456).toARGB32());
|
|
expect(container.read(trackerServiceProvider).value, <Tracker>[tracker]);
|
|
});
|
|
|
|
test('toggleChapter adds and then removes chapter', () async {
|
|
final container = await _container();
|
|
addTearDown(container.dispose);
|
|
await _waitForData(container);
|
|
|
|
final service = container.read(trackerServiceProvider.notifier);
|
|
final tracker = await service.create(
|
|
name: 'Plan',
|
|
color: const Color(0xFF000000),
|
|
);
|
|
|
|
await service.toggleChapter(tracker.id, 0, 1);
|
|
Tracker current = container.read(trackerServiceProvider).value!.single;
|
|
expect(current.readChapters, <String>{Bible.chapterKey(0, 1)});
|
|
|
|
await service.toggleChapter(tracker.id, 0, 1);
|
|
current = container.read(trackerServiceProvider).value!.single;
|
|
expect(current.readChapters, isEmpty);
|
|
});
|
|
|
|
test('setBookRead marks all chapters of the book', () async {
|
|
final container = await _container();
|
|
addTearDown(container.dispose);
|
|
await _waitForData(container);
|
|
final service = container.read(trackerServiceProvider.notifier);
|
|
final tracker = await service.create(
|
|
name: 'Plan',
|
|
color: const Color(0xFF000000),
|
|
);
|
|
|
|
await service.setBookRead(tracker.id, 0, read: true);
|
|
final Tracker current = container
|
|
.read(trackerServiceProvider)
|
|
.value!
|
|
.single;
|
|
final Book genesis = Bible.books[0];
|
|
expect(current.readChapters.length, genesis.chapterCount);
|
|
for (int chapter = 1; chapter <= genesis.chapterCount; chapter++) {
|
|
expect(current.readChapters.contains(Bible.chapterKey(0, chapter)), true);
|
|
}
|
|
});
|
|
|
|
test('reset clears only the target tracker', () async {
|
|
final container = await _container();
|
|
addTearDown(container.dispose);
|
|
await _waitForData(container);
|
|
final service = container.read(trackerServiceProvider.notifier);
|
|
final a = await service.create(name: 'A', color: const Color(0xFF111111));
|
|
final b = await service.create(name: 'B', color: const Color(0xFF222222));
|
|
await service.toggleChapter(a.id, 0, 1);
|
|
await service.toggleChapter(b.id, 0, 1);
|
|
|
|
await service.reset(a.id);
|
|
|
|
final List<Tracker> current = container.read(trackerServiceProvider).value!;
|
|
expect(
|
|
current.firstWhere((Tracker t) => t.id == a.id).readChapters,
|
|
isEmpty,
|
|
);
|
|
expect(
|
|
current.firstWhere((Tracker t) => t.id == b.id).readChapters,
|
|
<String>{Bible.chapterKey(0, 1)},
|
|
);
|
|
});
|
|
|
|
test('delete removes the tracker', () async {
|
|
final container = await _container();
|
|
addTearDown(container.dispose);
|
|
await _waitForData(container);
|
|
final service = container.read(trackerServiceProvider.notifier);
|
|
final a = await service.create(name: 'A', color: const Color(0xFF111111));
|
|
await service.create(name: 'B', color: const Color(0xFF222222));
|
|
|
|
await service.delete(a.id);
|
|
final List<Tracker> current = container.read(trackerServiceProvider).value!;
|
|
expect(current.length, 1);
|
|
expect(current.single.name, 'B');
|
|
});
|
|
|
|
test('state is persisted across container instances', () async {
|
|
SharedPreferences.setMockInitialValues(<String, Object>{});
|
|
final prefs = await SharedPreferences.getInstance();
|
|
|
|
final first = ProviderContainer(
|
|
overrides: <Override>[sharedPreferencesProvider.overrideWithValue(prefs)],
|
|
);
|
|
await _waitForData(first);
|
|
final created = await first
|
|
.read(trackerServiceProvider.notifier)
|
|
.create(name: 'Persisted', color: const Color(0xFFAABBCC));
|
|
await first
|
|
.read(trackerServiceProvider.notifier)
|
|
.toggleChapter(created.id, 5, 3);
|
|
first.dispose();
|
|
|
|
final second = ProviderContainer(
|
|
overrides: <Override>[sharedPreferencesProvider.overrideWithValue(prefs)],
|
|
);
|
|
addTearDown(second.dispose);
|
|
final List<Tracker> loaded = await _waitForData(second);
|
|
|
|
expect(loaded.length, 1);
|
|
expect(loaded.single.name, 'Persisted');
|
|
expect(loaded.single.readChapters, <String>{Bible.chapterKey(5, 3)});
|
|
});
|
|
|
|
test('updateMeta changes name and color', () async {
|
|
final container = await _container();
|
|
addTearDown(container.dispose);
|
|
await _waitForData(container);
|
|
final service = container.read(trackerServiceProvider.notifier);
|
|
final tracker = await service.create(
|
|
name: 'Old',
|
|
color: const Color(0xFF111111),
|
|
);
|
|
|
|
await service.updateMeta(
|
|
tracker.id,
|
|
name: 'New',
|
|
color: const Color(0xFF222222),
|
|
);
|
|
final Tracker current = container
|
|
.read(trackerServiceProvider)
|
|
.value!
|
|
.single;
|
|
expect(current.name, 'New');
|
|
expect(current.colorValue, const Color(0xFF222222).toARGB32());
|
|
});
|
|
}
|