|
...
|
...
|
@@ -391,9 +391,10 @@ void main() { |
|
|
|
expect(daily.single.uploaded, isTrue);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('startCoreCaculate skips raw reads when health auth is missing',
|
|
|
|
test(
|
|
|
|
'startCoreCaculate skips raw reads when health auth and local data are missing',
|
|
|
|
() async {
|
|
|
|
final api = _FakeHealthKitRawDataHostApi();
|
|
|
|
final api = _FakeHealthKitRawDataHostApi()..hasData = false;
|
|
|
|
final service = AppleHealthRawDataCoreService(
|
|
|
|
healthApi: _FakeHealthKitHostApi(status: 2),
|
|
|
|
rawDataApi: api,
|
|
...
|
...
|
@@ -411,6 +412,79 @@ void main() { |
|
|
|
expect(api.workoutCallCount, 0);
|
|
|
|
});
|
|
|
|
|
|
|
|
test(
|
|
|
|
'startCoreCaculate reads raw data when health auth is missing but data exists',
|
|
|
|
() async {
|
|
|
|
final now = DateTime.now().millisecondsSinceEpoch ~/ 1000;
|
|
|
|
final api = _FakeHealthKitRawDataHostApi()..hasData = true;
|
|
|
|
api.setPoints(HealthDataUploadType.hrv.type, [
|
|
|
|
_point(now - 120, 35),
|
|
|
|
]);
|
|
|
|
final service = AppleHealthRawDataCoreService(
|
|
|
|
healthApi: _FakeHealthKitHostApi(status: 2),
|
|
|
|
rawDataApi: api,
|
|
|
|
localStore: _MemoryHealthRawStressLocalStore(),
|
|
|
|
userIdProvider: () => 42,
|
|
|
|
uploadResultsAfterCalculation: false,
|
|
|
|
);
|
|
|
|
|
|
|
|
final result = await service.startCoreCaculate(
|
|
|
|
endTime: now,
|
|
|
|
readChunkDays: 1,
|
|
|
|
);
|
|
|
|
|
|
|
|
expect(result.hrvStressPoints.map((e) => e.rawEndTime), [now - 120]);
|
|
|
|
expect(api.calls, isNotEmpty);
|
|
|
|
expect(api.hasHealthDataCallCount, 1);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('startCoreCaculate skips raw reads when local data check fails',
|
|
|
|
() async {
|
|
|
|
final api = _FakeHealthKitRawDataHostApi()
|
|
|
|
..hasDataError = StateError('health data unavailable');
|
|
|
|
final service = AppleHealthRawDataCoreService(
|
|
|
|
healthApi: _FakeHealthKitHostApi(status: 2),
|
|
|
|
rawDataApi: api,
|
|
|
|
localStore: _MemoryHealthRawStressLocalStore(),
|
|
|
|
userIdProvider: () => 42,
|
|
|
|
uploadResultsAfterCalculation: false,
|
|
|
|
);
|
|
|
|
|
|
|
|
final result = await service.startCoreCaculate(readChunkDays: 1);
|
|
|
|
|
|
|
|
expect(result.hrvStressPoints, isEmpty);
|
|
|
|
expect(result.realtimeStressPoints, isEmpty);
|
|
|
|
expect(api.calls, isEmpty);
|
|
|
|
expect(api.hasHealthDataCallCount, 1);
|
|
|
|
});
|
|
|
|
|
|
|
|
test(
|
|
|
|
'startCoreCaculate does not call local data fallback when auth is granted',
|
|
|
|
() async {
|
|
|
|
final now = DateTime.now().millisecondsSinceEpoch ~/ 1000;
|
|
|
|
final api = _FakeHealthKitRawDataHostApi()
|
|
|
|
..hasData = false
|
|
|
|
..hasDataError = StateError('should not call hasHealthData');
|
|
|
|
api.setPoints(HealthDataUploadType.hrv.type, [
|
|
|
|
_point(now - 120, 35),
|
|
|
|
]);
|
|
|
|
final service = AppleHealthRawDataCoreService(
|
|
|
|
healthApi: _FakeHealthKitHostApi(status: 1),
|
|
|
|
rawDataApi: api,
|
|
|
|
localStore: _MemoryHealthRawStressLocalStore(),
|
|
|
|
userIdProvider: () => 42,
|
|
|
|
uploadResultsAfterCalculation: false,
|
|
|
|
);
|
|
|
|
|
|
|
|
final result = await service.startCoreCaculate(
|
|
|
|
endTime: now,
|
|
|
|
readChunkDays: 1,
|
|
|
|
);
|
|
|
|
|
|
|
|
expect(result.hrvStressPoints.map((e) => e.rawEndTime), [now - 120]);
|
|
|
|
expect(api.hasHealthDataCallCount, 0);
|
|
|
|
});
|
|
|
|
|
|
|
|
test('onHealthDataUpdated emits event with data types after calculation',
|
|
|
|
() async {
|
|
|
|
final now = DateTime.now().millisecondsSinceEpoch ~/ 1000;
|
|
...
|
...
|
@@ -943,6 +1017,8 @@ class _FakeHealthKitRawDataHostApi extends HealthKitRawDataHostApi { |
|
|
|
Completer<int>? hrUploadCompleter;
|
|
|
|
Completer<int>? hrvUploadCompleter;
|
|
|
|
var hasData = true;
|
|
|
|
Object? hasDataError;
|
|
|
|
var hasHealthDataCallCount = 0;
|
|
|
|
|
|
|
|
void setPoints(int dataType, List<HealthKitRawDataPoint> points) {
|
|
|
|
_pointsByType[dataType] = points;
|
|
...
|
...
|
@@ -965,7 +1041,14 @@ class _FakeHealthKitRawDataHostApi extends HealthKitRawDataHostApi { |
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Future<bool> hasHealthData() async => hasData;
|
|
|
|
Future<bool> hasHealthData() async {
|
|
|
|
hasHealthDataCallCount += 1;
|
|
|
|
final error = hasDataError;
|
|
|
|
if (error != null) {
|
|
|
|
throw error;
|
|
|
|
}
|
|
|
|
return hasData;
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Future<List<HealthKitRawDataPoint>> getHealthKitRawData(
|
...
|
...
|
|