feat: Implement husband features and fix iOS Safari web startup
Implement initial features for husband's companion app, including mock data service and husband notes screen. Refactor scripture and cycle services for improved stability and testability. Address iOS Safari web app startup issue by removing deprecated initialization. - Implemented MockDataService and HusbandNotesScreen. - Converted _DashboardTab and DevotionalScreen to StatefulWidgets for robust scripture provider initialization. - Refactored CycleService to use immutable CycleInfo class, reducing UI rebuilds. - Removed deprecated window.flutterConfiguration from index.html, resolving Flutter web app startup failure on iOS Safari. - Updated and fixed related tests.
This commit is contained in:
40
test/cycle_entry_test.dart
Normal file
40
test/cycle_entry_test.dart
Normal file
@@ -0,0 +1,40 @@
|
||||
import 'package:christian_period_tracker/models/cycle_entry.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
group('CycleEntry', () {
|
||||
test('hasSymptoms returns true when there are symptoms', () {
|
||||
final entry = CycleEntry(
|
||||
id: '1',
|
||||
date: DateTime.now(),
|
||||
createdAt: DateTime.now(),
|
||||
updatedAt: DateTime.now(),
|
||||
hasHeadache: true,
|
||||
);
|
||||
expect(entry.hasSymptoms, isTrue);
|
||||
});
|
||||
|
||||
test('hasSymptoms returns false when there are no symptoms', () {
|
||||
final entry = CycleEntry(
|
||||
id: '1',
|
||||
date: DateTime.now(),
|
||||
createdAt: DateTime.now(),
|
||||
updatedAt: DateTime.now(),
|
||||
);
|
||||
expect(entry.hasSymptoms, isFalse);
|
||||
});
|
||||
|
||||
test('symptomCount returns the correct number of symptoms', () {
|
||||
final entry = CycleEntry(
|
||||
id: '1',
|
||||
date: DateTime.now(),
|
||||
createdAt: DateTime.now(),
|
||||
updatedAt: DateTime.now(),
|
||||
hasHeadache: true,
|
||||
hasBloating: true,
|
||||
crampIntensity: 2,
|
||||
);
|
||||
expect(entry.symptomCount, 3);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -7,8 +7,8 @@ void main() {
|
||||
group('CycleService Tests', () {
|
||||
test('calculateCycleInfo returns follicular phase for null profile', () {
|
||||
final info = CycleService.calculateCycleInfo(null);
|
||||
expect(info['phase'], CyclePhase.follicular);
|
||||
expect(info['dayOfCycle'], 1);
|
||||
expect(info.phase, CyclePhase.follicular);
|
||||
expect(info.dayOfCycle, 1);
|
||||
});
|
||||
|
||||
test('calculateCycleInfo calculates follicular phase correctly (Day 7)', () {
|
||||
@@ -26,8 +26,8 @@ void main() {
|
||||
);
|
||||
|
||||
final info = CycleService.calculateCycleInfo(user);
|
||||
expect(info['dayOfCycle'], 7);
|
||||
expect(info['phase'], CyclePhase.follicular);
|
||||
expect(info.dayOfCycle, 7);
|
||||
expect(info.phase, CyclePhase.follicular);
|
||||
});
|
||||
|
||||
test('calculateCycleInfo calculates menstrual phase correctly (Day 2)', () {
|
||||
@@ -45,8 +45,8 @@ void main() {
|
||||
);
|
||||
|
||||
final info = CycleService.calculateCycleInfo(user);
|
||||
expect(info['dayOfCycle'], 2);
|
||||
expect(info['phase'], CyclePhase.menstrual);
|
||||
expect(info.dayOfCycle, 2);
|
||||
expect(info.phase, CyclePhase.menstrual);
|
||||
});
|
||||
|
||||
test('calculateCycleInfo handles cycle length wrapping', () {
|
||||
@@ -65,8 +65,8 @@ void main() {
|
||||
);
|
||||
|
||||
final info = CycleService.calculateCycleInfo(user);
|
||||
expect(info['dayOfCycle'], 3);
|
||||
expect(info['phase'], CyclePhase.menstrual);
|
||||
expect(info.dayOfCycle, 3);
|
||||
expect(info.phase, CyclePhase.menstrual);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
5
test/mocks.dart
Normal file
5
test/mocks.dart
Normal file
@@ -0,0 +1,5 @@
|
||||
import 'package:mockito/annotations.dart';
|
||||
import 'package:christian_period_tracker/services/bible_xml_parser.dart';
|
||||
|
||||
@GenerateMocks([BibleXmlParser])
|
||||
void main() {} // Dummy main function to satisfy Dart
|
||||
91
test/mocks.mocks.dart
Normal file
91
test/mocks.mocks.dart
Normal file
@@ -0,0 +1,91 @@
|
||||
// Mocks generated by Mockito 5.4.4 from annotations
|
||||
// in christian_period_tracker/test/mocks.dart.
|
||||
// Do not manually edit this file.
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'dart:async' as _i4;
|
||||
|
||||
import 'package:christian_period_tracker/services/bible_xml_parser.dart' as _i3;
|
||||
import 'package:mockito/mockito.dart' as _i1;
|
||||
import 'package:xml/xml.dart' as _i2;
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: avoid_redundant_argument_values
|
||||
// ignore_for_file: avoid_setters_without_getters
|
||||
// ignore_for_file: comment_references
|
||||
// ignore_for_file: deprecated_member_use
|
||||
// ignore_for_file: deprecated_member_use_from_same_package
|
||||
// ignore_for_file: implementation_imports
|
||||
// ignore_for_file: invalid_use_of_visible_for_testing_member
|
||||
// ignore_for_file: prefer_const_constructors
|
||||
// ignore_for_file: unnecessary_parenthesis
|
||||
// ignore_for_file: camel_case_types
|
||||
// ignore_for_file: subtype_of_sealed_class
|
||||
|
||||
class _FakeXmlDocument_0 extends _i1.SmartFake implements _i2.XmlDocument {
|
||||
_FakeXmlDocument_0(
|
||||
Object parent,
|
||||
Invocation parentInvocation,
|
||||
) : super(
|
||||
parent,
|
||||
parentInvocation,
|
||||
);
|
||||
}
|
||||
|
||||
/// A class which mocks [BibleXmlParser].
|
||||
///
|
||||
/// See the documentation for Mockito's code generation for more information.
|
||||
class MockBibleXmlParser extends _i1.Mock implements _i3.BibleXmlParser {
|
||||
MockBibleXmlParser() {
|
||||
_i1.throwOnMissingStub(this);
|
||||
}
|
||||
|
||||
@override
|
||||
_i4.Future<_i2.XmlDocument> loadXmlAsset(String? assetPath) =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#loadXmlAsset,
|
||||
[assetPath],
|
||||
),
|
||||
returnValue: _i4.Future<_i2.XmlDocument>.value(_FakeXmlDocument_0(
|
||||
this,
|
||||
Invocation.method(
|
||||
#loadXmlAsset,
|
||||
[assetPath],
|
||||
),
|
||||
)),
|
||||
) as _i4.Future<_i2.XmlDocument>);
|
||||
|
||||
@override
|
||||
String? getVerseFromXml(
|
||||
_i2.XmlDocument? document,
|
||||
String? bookName,
|
||||
int? chapterNum,
|
||||
int? verseNum,
|
||||
) =>
|
||||
(super.noSuchMethod(Invocation.method(
|
||||
#getVerseFromXml,
|
||||
[
|
||||
document,
|
||||
bookName,
|
||||
chapterNum,
|
||||
verseNum,
|
||||
],
|
||||
)) as String?);
|
||||
|
||||
@override
|
||||
_i4.Future<String?> getVerseFromAsset(
|
||||
String? assetPath,
|
||||
String? reference,
|
||||
) =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#getVerseFromAsset,
|
||||
[
|
||||
assetPath,
|
||||
reference,
|
||||
],
|
||||
),
|
||||
returnValue: _i4.Future<String?>.value(),
|
||||
) as _i4.Future<String?>);
|
||||
}
|
||||
262
test/scripture_provider_test.dart
Normal file
262
test/scripture_provider_test.dart
Normal file
@@ -0,0 +1,262 @@
|
||||
import 'dart:io';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:christian_period_tracker/models/scripture.dart';
|
||||
import 'package:christian_period_tracker/models/cycle_entry.dart';
|
||||
import 'package:christian_period_tracker/models/user_profile.dart';
|
||||
import 'package:christian_period_tracker/providers/scripture_provider.dart';
|
||||
import 'package:christian_period_tracker/providers/user_provider.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
|
||||
// Fake ScriptureDatabase implementation for testing
|
||||
class FakeScriptureDatabase implements ScriptureDatabase {
|
||||
final int Function(String phase) getScriptureCountForPhaseFn;
|
||||
final Scripture? Function(String phase, int index) getScriptureForPhaseByIndexFn;
|
||||
final Scripture? Function(String phase)? getRandomScriptureForPhaseFn;
|
||||
|
||||
FakeScriptureDatabase({
|
||||
required this.getScriptureCountForPhaseFn,
|
||||
required this.getScriptureForPhaseByIndexFn,
|
||||
this.getRandomScriptureForPhaseFn,
|
||||
});
|
||||
|
||||
@override
|
||||
int getScriptureCountForPhase(String phase) => getScriptureCountForPhaseFn(phase);
|
||||
|
||||
@override
|
||||
Scripture? getScriptureForPhaseByIndex(String phase, int index) =>
|
||||
getScriptureForPhaseByIndexFn(phase, index);
|
||||
|
||||
@override
|
||||
Scripture? getRandomScriptureForPhase(String phase) =>
|
||||
getRandomScriptureForPhaseFn != null ? getRandomScriptureForPhaseFn!(phase) : null;
|
||||
|
||||
// Unimplemented methods (not used by ScriptureNotifier)
|
||||
@override
|
||||
List<Scripture> getAllScriptures() => throw UnimplementedError();
|
||||
|
||||
@override
|
||||
Scripture getHusbandScripture() => throw UnimplementedError();
|
||||
|
||||
@override
|
||||
Future<void> loadScriptures() => Future.value(); // Can be mocked to do nothing
|
||||
|
||||
@override
|
||||
Scripture? getRecommendedScripture(CycleEntry entry) => throw UnimplementedError();
|
||||
|
||||
@override
|
||||
Scripture getScriptureForPhase(String phase) => throw UnimplementedError();
|
||||
}
|
||||
|
||||
void main() {
|
||||
group('ScriptureNotifier', () {
|
||||
late ProviderContainer container;
|
||||
late String testPath;
|
||||
|
||||
setUpAll(() async {
|
||||
testPath = Directory.current.path + '/test_hive_temp_scripture_provider';
|
||||
final Directory tempDir = Directory(testPath);
|
||||
if (!await tempDir.exists()) {
|
||||
await tempDir.create(recursive: true);
|
||||
}
|
||||
Hive.init(testPath);
|
||||
Hive.registerAdapter(UserProfileAdapter());
|
||||
Hive.registerAdapter(RelationshipStatusAdapter());
|
||||
Hive.registerAdapter(FertilityGoalAdapter());
|
||||
Hive.registerAdapter(BibleTranslationAdapter());
|
||||
Hive.registerAdapter(UserRoleAdapter());
|
||||
await Hive.openBox<UserProfile>('user_profile');
|
||||
});
|
||||
|
||||
tearDownAll(() async {
|
||||
await Hive.close();
|
||||
await Directory(testPath).delete(recursive: true);
|
||||
});
|
||||
|
||||
final testScripture1 = Scripture(
|
||||
verses: {BibleTranslation.esv: "Verse 1"},
|
||||
reference: "Ref 1",
|
||||
applicablePhases: ['menstrual'],
|
||||
);
|
||||
final testScripture2 = Scripture(
|
||||
verses: {BibleTranslation.esv: "Verse 2"},
|
||||
reference: "Ref 2",
|
||||
applicablePhases: ['menstrual'],
|
||||
);
|
||||
final testScripture3 = Scripture(
|
||||
verses: {BibleTranslation.esv: "Verse 3"},
|
||||
reference: "Ref 3",
|
||||
applicablePhases: ['menstrual'],
|
||||
);
|
||||
|
||||
tearDown(() {
|
||||
container.dispose();
|
||||
});
|
||||
|
||||
test('initializes with correct scripture for phase', () async {
|
||||
final fakeDb = FakeScriptureDatabase(
|
||||
getScriptureCountForPhaseFn: (phase) => 3,
|
||||
getScriptureForPhaseByIndexFn: (phase, index) => testScripture1,
|
||||
);
|
||||
|
||||
container = ProviderContainer(
|
||||
overrides: [
|
||||
scriptureDatabaseProvider.overrideWithValue(fakeDb),
|
||||
userProfileProvider.overrideWith(
|
||||
(ref) => UserProfileNotifier(),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final notifier = container.read(scriptureProvider.notifier);
|
||||
notifier.initializeScripture(CyclePhase.menstrual);
|
||||
|
||||
final state = container.read(scriptureProvider);
|
||||
expect(state.currentScripture, testScripture1);
|
||||
expect(state.currentPhase, CyclePhase.menstrual);
|
||||
expect(state.maxIndex, 3);
|
||||
// currentIndex will depend on dayOfYear % 3, which is hard to predict
|
||||
// So we'll just check it's within bounds.
|
||||
expect(state.currentIndex, isNonNegative);
|
||||
expect(state.currentIndex, lessThan(3));
|
||||
});
|
||||
|
||||
test('getNextScripture cycles correctly', () async {
|
||||
final scriptures = [testScripture1, testScripture2, testScripture3];
|
||||
final fakeDb = FakeScriptureDatabase(
|
||||
getScriptureCountForPhaseFn: (phase) => scriptures.length,
|
||||
getScriptureForPhaseByIndexFn: (phase, index) => scriptures[index],
|
||||
);
|
||||
|
||||
container = ProviderContainer(
|
||||
overrides: [
|
||||
scriptureDatabaseProvider.overrideWithValue(fakeDb),
|
||||
userProfileProvider.overrideWith(
|
||||
(ref) => UserProfileNotifier(),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final notifier = container.read(scriptureProvider.notifier);
|
||||
// Force initial state to 0 for predictable cycling
|
||||
notifier.initializeScripture(CyclePhase.menstrual);
|
||||
// Override currentIndex to 0 for predictable test
|
||||
container.read(scriptureProvider.notifier).state = container.read(scriptureProvider).copyWith(currentIndex: 0);
|
||||
|
||||
|
||||
// First next
|
||||
notifier.getNextScripture();
|
||||
expect(container.read(scriptureProvider).currentScripture, testScripture2);
|
||||
expect(container.read(scriptureProvider).currentIndex, 1);
|
||||
|
||||
// Second next
|
||||
notifier.getNextScripture();
|
||||
expect(container.read(scriptureProvider).currentScripture, testScripture3);
|
||||
expect(container.read(scriptureProvider).currentIndex, 2);
|
||||
|
||||
// Wrap around
|
||||
notifier.getNextScripture();
|
||||
expect(container.read(scriptureProvider).currentScripture, testScripture1);
|
||||
expect(container.read(scriptureProvider).currentIndex, 0);
|
||||
});
|
||||
|
||||
test('getPreviousScripture cycles correctly', () async {
|
||||
final scriptures = [testScripture1, testScripture2, testScripture3];
|
||||
final fakeDb = FakeScriptureDatabase(
|
||||
getScriptureCountForPhaseFn: (phase) => scriptures.length,
|
||||
getScriptureForPhaseByIndexFn: (phase, index) => scriptures[index],
|
||||
);
|
||||
|
||||
container = ProviderContainer(
|
||||
overrides: [
|
||||
scriptureDatabaseProvider.overrideWithValue(fakeDb),
|
||||
userProfileProvider.overrideWith(
|
||||
(ref) => UserProfileNotifier(),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final notifier = container.read(scriptureProvider.notifier);
|
||||
// Force initial state to 0 for predictable cycling
|
||||
notifier.initializeScripture(CyclePhase.menstrual);
|
||||
// Override currentIndex to 0 for predictable test
|
||||
container.read(scriptureProvider.notifier).state = container.read(scriptureProvider).copyWith(currentIndex: 0);
|
||||
|
||||
|
||||
// First previous (wraps around)
|
||||
notifier.getPreviousScripture();
|
||||
expect(container.read(scriptureProvider).currentScripture, testScripture3);
|
||||
expect(container.read(scriptureProvider).currentIndex, 2);
|
||||
|
||||
// Second previous
|
||||
notifier.getPreviousScripture();
|
||||
expect(container.read(scriptureProvider).currentScripture, testScripture2);
|
||||
expect(container.read(scriptureProvider).currentIndex, 1);
|
||||
|
||||
// Third previous
|
||||
notifier.getPreviousScripture();
|
||||
expect(container.read(scriptureProvider).currentScripture, testScripture1);
|
||||
expect(container.read(scriptureProvider).currentIndex, 0);
|
||||
});
|
||||
|
||||
test('getRandomScripture updates to a valid scripture', () async {
|
||||
final scriptures = [testScripture1, testScripture2, testScripture3];
|
||||
final fakeDb = FakeScriptureDatabase(
|
||||
getScriptureCountForPhaseFn: (phase) => scriptures.length,
|
||||
getScriptureForPhaseByIndexFn: (phase, index) => scriptures[index % scriptures.length], // Ensure it always returns a valid one
|
||||
);
|
||||
|
||||
container = ProviderContainer(
|
||||
overrides: [
|
||||
scriptureDatabaseProvider.overrideWithValue(fakeDb),
|
||||
userProfileProvider.overrideWith(
|
||||
(ref) => UserProfileNotifier(),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final notifier = container.read(scriptureProvider.notifier);
|
||||
notifier.initializeScripture(CyclePhase.menstrual);
|
||||
|
||||
// Perform a random selection
|
||||
notifier.getRandomScripture();
|
||||
final state = container.read(scriptureProvider);
|
||||
|
||||
expect(state.currentScripture, isNotNull);
|
||||
expect(state.currentScripture, isIn(scriptures)); // Ensure it's one of the valid scriptures
|
||||
expect(state.currentIndex, isNonNegative);
|
||||
expect(state.currentIndex, lessThan(scriptures.length));
|
||||
});
|
||||
|
||||
test('does not change state if maxIndex is 0', () async {
|
||||
final fakeDb = FakeScriptureDatabase(
|
||||
getScriptureCountForPhaseFn: (phase) => 0,
|
||||
getScriptureForPhaseByIndexFn: (phase, index) => null,
|
||||
);
|
||||
|
||||
container = ProviderContainer(
|
||||
overrides: [
|
||||
scriptureDatabaseProvider.overrideWithValue(fakeDb),
|
||||
userProfileProvider.overrideWith(
|
||||
(ref) => UserProfileNotifier(),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final notifier = container.read(scriptureProvider.notifier);
|
||||
notifier.initializeScripture(CyclePhase.menstrual);
|
||||
|
||||
final initialState = container.read(scriptureProvider);
|
||||
expect(initialState.currentScripture, isNull);
|
||||
expect(initialState.maxIndex, 0);
|
||||
|
||||
notifier.getNextScripture();
|
||||
notifier.getPreviousScripture();
|
||||
notifier.getRandomScripture();
|
||||
|
||||
// State should remain unchanged
|
||||
expect(container.read(scriptureProvider), initialState);
|
||||
});
|
||||
});
|
||||
}
|
||||
155
test/scripture_test.dart
Normal file
155
test/scripture_test.dart
Normal file
@@ -0,0 +1,155 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:christian_period_tracker/models/scripture.dart';
|
||||
import 'package:christian_period_tracker/models/user_profile.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'package:path_provider_platform_interface/path_provider_platform_interface.dart';
|
||||
import 'package:path_provider_linux/path_provider_linux.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'mocks.mocks.dart'; // Generated mock file
|
||||
|
||||
void main() {
|
||||
TestWidgetsFlutterBinding.ensureInitialized();
|
||||
|
||||
group('Scripture', () {
|
||||
test('fromJson creates a valid Scripture object', () {
|
||||
final json = {
|
||||
"verses": {
|
||||
"esv": "Test verse",
|
||||
},
|
||||
"reference": "Test 1:1",
|
||||
};
|
||||
final scripture = Scripture.fromJson(json);
|
||||
expect(scripture.reference, "Test 1:1");
|
||||
expect(scripture.getVerse(BibleTranslation.esv), "Test verse");
|
||||
});
|
||||
});
|
||||
|
||||
group('ScriptureDatabase', () {
|
||||
late ScriptureDatabase database;
|
||||
late String testPath;
|
||||
|
||||
setUpAll(() async {
|
||||
// Initialize path_provider_platform_interface for testing
|
||||
// This is a common pattern for mocking platform-specific plugins in tests.
|
||||
PathProviderPlatform.instance = _MockPathProviderPlatform();
|
||||
testPath = Directory.current.path + '/test_hive_temp';
|
||||
|
||||
// Ensure the directory exists
|
||||
final Directory tempDir = Directory(testPath);
|
||||
if (!await tempDir.exists()) {
|
||||
await tempDir.create(recursive: true);
|
||||
}
|
||||
|
||||
// Create and configure the mock BibleXmlParser
|
||||
final mockBibleXmlParser = MockBibleXmlParser();
|
||||
when(mockBibleXmlParser.getVerseFromAsset(any, any)).thenAnswer((invocation) async {
|
||||
final String reference = invocation.positionalArguments[1];
|
||||
// Return a mock verse based on the reference for testing purposes
|
||||
return 'Mock Verse for $reference';
|
||||
});
|
||||
|
||||
// Mock the rootBundle for JSON assets (XML assets are now handled by mockBibleXmlParser)
|
||||
TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger
|
||||
.setMockMessageHandler(
|
||||
'flutter/assets',
|
||||
(ByteData? message) async {
|
||||
final String key = utf8.decode(message!.buffer.asUint8List());
|
||||
if (key == 'assets/scriptures.json' || key == 'assets/scriptures_optimized.json') {
|
||||
final json = {
|
||||
"menstrual": [
|
||||
{
|
||||
"verses": {"esv": "Menstrual verse"},
|
||||
"reference": "Menstrual 1:1",
|
||||
"applicablePhases": ["menstrual"]
|
||||
}
|
||||
],
|
||||
"follicular": [
|
||||
{
|
||||
"verses": {"esv": "Follicular verse"},
|
||||
"reference": "Follicular 1:1",
|
||||
"applicablePhases": ["follicular"]
|
||||
}
|
||||
],
|
||||
"ovulation": [
|
||||
{
|
||||
"verses": {"esv": "Ovulation verse"},
|
||||
"reference": "Ovulation 1:1",
|
||||
"applicablePhases": ["ovulation"]
|
||||
}
|
||||
],
|
||||
"luteal": [
|
||||
{
|
||||
"verses": {"esv": "Luteal verse"},
|
||||
"reference": "Luteal 1:1",
|
||||
"applicablePhases": ["luteal"]
|
||||
}
|
||||
],
|
||||
"husband": [
|
||||
{
|
||||
"verses": {"esv": "Husband verse"},
|
||||
"reference": "Husband 1:1",
|
||||
"applicablePhases": ["husband"]
|
||||
}
|
||||
],
|
||||
"womanhood": [
|
||||
{
|
||||
"verses": {"esv": "Womanhood verse"},
|
||||
"reference": "Womanhood 1:1",
|
||||
"applicableContexts": ["womanhood"]
|
||||
}
|
||||
],
|
||||
"contextual": {
|
||||
"pain": [
|
||||
{
|
||||
"verses": {"esv": "Pain verse"},
|
||||
"reference": "Pain 1:1",
|
||||
"applicableContexts": ["pain"]
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
return utf8.encode(jsonEncode(json)).buffer.asByteData();
|
||||
}
|
||||
return null; // Return null for other asset requests not explicitly mocked
|
||||
},
|
||||
);
|
||||
|
||||
Hive.init(testPath);
|
||||
Hive.registerAdapter(ScriptureAdapter()); // Register your adapter
|
||||
Hive.registerAdapter(BibleTranslationAdapter()); // Register BibleTranslationAdapter
|
||||
database = ScriptureDatabase(bibleXmlParser: mockBibleXmlParser); // Instantiate with mock
|
||||
await database.loadScriptures();
|
||||
});
|
||||
|
||||
tearDownAll(() async {
|
||||
await Hive.close();
|
||||
await Directory(testPath).delete(recursive: true);
|
||||
});
|
||||
|
||||
test('getScriptureForPhase returns the correct scripture', () {
|
||||
final scripture = database.getScriptureForPhase('menstrual');
|
||||
expect(scripture.reference, "Menstrual 1:1");
|
||||
});
|
||||
|
||||
test('getHusbandScripture returns a husband scripture', () {
|
||||
final scripture = database.getHusbandScripture();
|
||||
expect(scripture.applicablePhases, contains('husband'));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
class _MockPathProviderPlatform extends PathProviderPlatform {
|
||||
@override
|
||||
Future<String?> getApplicationSupportPath() async {
|
||||
return Directory.current.path + '/test_hive_temp';
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String?> getApplicationDocumentsPath() async {
|
||||
return Directory.current.path + '/test_hive_temp';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user