Files
HealthTracking/jest.setup.js
T
FightRate Agent 41b49ba442 feat(chart): TrainingChart dinâmico com viewport, zoom, pan e pin sobrevivente
Substitui o gráfico estático (últimos 120 samples + selectedIndex por
posição) por um modelo de viewport temporal que resolve os problemas de
qualidade em tempo real e abre zoom/pan nos 3 call sites (Captura,
Janela salva e Faixa customizada).

Adições:
- src/training/chartViewport.ts: funções puras (granularityForSpan,
  formatTickLabel, buildChartViewport, applyZoomIn/Out, applyPan,
  isLiveTailSnap, pickSampleAtTimestamp, xFromTimestampMs,
  timestampMsFromX, tipos Viewport/ChartPin/Granularity).
- __tests__/chartViewport.test.ts: 34 testes cobrindo limites,
  ordenação defensiva, snap zone, hit-test e granularidade adaptativa.
- src/components/TrainingChart.tsx: reescrito para consumir viewport.
  - Pin por timestampMs (sobrevive a novas amostras em tempo real).
  - Pinch (Gesture.Pinch) + Pan (Gesture.Pan) + Tap (Gesture.Tap) via
    react-native-gesture-handler v3.
  - Auto-follow: endMs estende com novos samples enquanto liveTail.
  - Snap zone (5% da duração visível) reanexa o live ao final do pan.
  - Eixo X com ticks adaptativos: minute/halfMinute/quarterMinute/
    tenSeconds/second/halfSecond, conforme duração visível.
  - Botões +/- (zoom 2x) e ↺ (reset) na lateral.
  - Indicador 'dados mais novos disponíveis' quando !liveTail.
  - Estado vazio preservado (samples < 2).
- jest.setup.js + jest.config.js: mocks de gesture-handler e
  reanimated para o App.test rodar em Jest (módulos nativos não
  disponíveis no host).

Modificações de setup (dependências aprovadas):
- package.json + package-lock.json: adiciona react-native-gesture-handler
  ^3.0.1, react-native-reanimated ^4.4.1, react-native-worklets ^0.9.2.
- index.js: import 'react-native-gesture-handler' no topo.
- App.tsx: <GestureHandlerRootView> envolvendo SafeAreaProvider.
- babel.config.js: plugin react-native-worklets/plugin.

Verificações:
- npm run typecheck: 0 errors.
- npm run lint: 0 errors, 0 warnings.
- npm test -- --runInBand: 55/55 passam.
- Build Android: não verificado nesta sessão (timeout); o usuário
  valida localmente antes de distribuir.

Não comitado neste commit (mudanças pré-existentes não relacionadas):
- android/* (migração fightratern → healthtracking/fightrate, mipmaps)
- README.md
- app.json
2026-06-15 00:10:55 -03:00

56 lines
1.6 KiB
JavaScript

/* eslint-env jest */
// react-native-gesture-handler and react-native-reanimated both depend on
// native modules that are not present in the Jest environment. Mock the
// TurboModuleRegistry calls so importing our screens does not throw.
jest.mock('react-native-gesture-handler', () => {
const View = require('react-native').View;
const React = require('react');
const passthrough = component =>
React.forwardRef((props, ref) => {
const Comp = component;
return React.createElement(Comp, { ...props, ref });
});
return {
__esModule: true,
GestureHandlerRootView: passthrough(View),
GestureDetector: passthrough(View),
Gesture: {
Pan: () => ({
onBegin: () => ({
onUpdate: () => ({
onEnd: () => ({
onFinalize: () => ({ minDistance: () => ({}) }),
}),
}),
}),
}),
Pinch: () => ({
onBegin: () => ({
onUpdate: () => ({
onEnd: () => ({ onFinalize: () => ({}) }),
}),
}),
}),
Tap: () => ({ maxDuration: () => ({ onEnd: () => ({}) }) }),
Race: (...args) => ({ _args: args }),
Simultaneous: (...args) => ({ _args: args }),
},
};
});
jest.mock('react-native-reanimated', () => {
const View = require('react-native').View;
return {
__esModule: true,
default: { View, createAnimatedComponent: c => c, Value: function () {} },
runOnJS: fn => fn,
useSharedValue: initial => ({ value: initial }),
useAnimatedStyle: () => ({}),
withTiming: v => v,
withSpring: v => v,
Easing: { inOut: () => ({}), linear: () => ({}) },
};
});