feat: implement Haptika PPG and Watch V1
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
import {buildMetricInsights} from '../insights/metricInsights';
|
||||
import type {StoredMeasurement} from '../storage/storageTypes';
|
||||
import {makeProcessingResult} from './syntheticMeasurements';
|
||||
|
||||
const stored = (index: number, bpm: number, rmssd: number): StoredMeasurement => ({
|
||||
schemaVersion: 1,
|
||||
algorithmVersion: 'test',
|
||||
acquisition: {cameraPosition: 'front', torchUsed: false},
|
||||
id: `stored-${index}`,
|
||||
measuredAt: new Date(Date.UTC(2026, 6, index + 1, 8)).toISOString(),
|
||||
atRest: true,
|
||||
baselineEligible: true,
|
||||
cameraResult: makeProcessingResult({
|
||||
bpm: {...makeProcessingResult().bpm, bpm},
|
||||
prv: {...makeProcessingResult().prv, estimatedRmssdMs: rmssd},
|
||||
}),
|
||||
potentialStress: {
|
||||
index: null,
|
||||
status: 'baselineBuilding',
|
||||
confidence: 0,
|
||||
bpmContribution: null,
|
||||
prvContribution: null,
|
||||
signalQuality: 0.9,
|
||||
baselineMeasurementCount: 0,
|
||||
healthKitUsedForScore: false,
|
||||
limitations: [],
|
||||
},
|
||||
healthKitContext: null,
|
||||
selfReport: null,
|
||||
});
|
||||
|
||||
describe('buildMetricInsights', () => {
|
||||
it('uses real historical measurements and creates personal ranges after five values', () => {
|
||||
const history = [
|
||||
stored(0, 70, 40),
|
||||
stored(1, 71, 41),
|
||||
stored(2, 69, 39),
|
||||
stored(3, 72, 42),
|
||||
stored(4, 70, 40),
|
||||
];
|
||||
const insights = buildMetricInsights(history[4]!.cameraResult, history);
|
||||
const bpm = insights.find(insight => insight.key === 'bpm');
|
||||
const rmssd = insights.find(insight => insight.key === 'rmssd');
|
||||
|
||||
expect(bpm?.trend).toHaveLength(5);
|
||||
expect(bpm?.referenceRange).not.toBeNull();
|
||||
expect(bpm?.status).toBe('Dans votre repère habituel');
|
||||
expect(rmssd?.trend.map(point => point.value)).toEqual([40, 41, 39, 42, 40]);
|
||||
});
|
||||
|
||||
it('never publishes PRV insights when the current PRV is unreliable', () => {
|
||||
const current = makeProcessingResult({
|
||||
prv: {...makeProcessingResult().prv, reliable: false},
|
||||
});
|
||||
const insights = buildMetricInsights(current, []);
|
||||
|
||||
expect(insights.find(insight => insight.key === 'bpm')?.value).toBe(72);
|
||||
expect(insights.find(insight => insight.key === 'rmssd')?.value).toBeNull();
|
||||
expect(insights.find(insight => insight.key === 'rmssd')?.status).toBe(
|
||||
'Signal insuffisant',
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user