Files
Keysat 4be489d6d3 v1.2.0:5 — Gear (breathing, 1-5) replaces RPE as the effort field for cardio
Cardio exercises now log a breathing "Gear" (1-5, per Brian MacKenzie)
instead of RPE (6-10) as their effort field; strength keeps RPE. An exercise
counts as cardio when its equipment type is "cardio" or it carries the
"cardio" muscle group (isCardioExercise in lib/exerciseOptions), so the
Assault Bike (type "assault bike") qualifies.

New nullable SetLog.gear column added by the boot-time guarded ALTER in
docker_entrypoint.sh (additive, idempotent); plumbed through all 5 set-write
paths, the summary/edit views, and CSV/JSON import-export. Existing rpe data
is untouched and still displays. Program/AI target-RPE is unaffected.
2026-06-16 14:49:15 -05:00

29 lines
1.1 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import { isCardioExercise } from '@/lib/exerciseOptions';
describe('isCardioExercise', () => {
it('treats type "cardio" as cardio', () => {
expect(isCardioExercise({ type: 'cardio', muscleGroups: '["cardio"]' })).toBe(true);
});
it('treats the cardio muscle group as cardio even when type differs (Assault Bike)', () => {
expect(
isCardioExercise({ type: 'assault bike', muscleGroups: '["cardio","legs","back","shoulders"]' })
).toBe(true);
});
it('is case/whitespace-insensitive on the muscle group', () => {
expect(isCardioExercise({ type: 'other', muscleGroups: '[" Cardio "]' })).toBe(true);
});
it('treats strength work (no cardio signal) as non-cardio', () => {
expect(isCardioExercise({ type: 'barbell', muscleGroups: '["back","biceps"]' })).toBe(false);
});
it('handles missing/empty fields without throwing', () => {
expect(isCardioExercise({})).toBe(false);
expect(isCardioExercise({ type: null, muscleGroups: null })).toBe(false);
expect(isCardioExercise({ type: '', muscleGroups: 'not json' })).toBe(false);
});
});