UNPKG

powerhouse-rp-toolkit

Version:

Renaissance Periodization Training Toolkit for PowerHouseATX

348 lines (303 loc) 12.7 kB
/** * @jest-environment jsdom */ import * as ts from "../js/core/trainingState.js"; import { mockTrainingState } from "../__tests__/helpers/mockState.js"; import { resetMockTrainingState } from "../__tests__/helpers/mockState.js"; import { initIntelligence, optimizeVolumeLandmarks, adaptiveRIRRecommendations, } from "../js/algorithms/intelligence.js"; // ----- isolate global singleton so later test-suites aren't polluted ----- const snapshot = ts.trainingState ? Object.assign({}, ts.trainingState) : {}; beforeEach(resetMockTrainingState); afterAll(() => { // restore original once the whole file is done if (ts.trainingState) { Object.assign(ts.trainingState, snapshot); } }); describe("Intelligence Algorithm Tests", () => { describe("initIntelligence", () => { const localMockState = { ...mockTrainingState, currentMesocycle: { currentWeek: 3, length: 6, }, weeklyProgram: { actualVolume: { chest: [12, 14, 16], back: [10, 12, 14], shoulders: [8, 10, 12], }, }, volumeLandmarks: { chest: { mv: 8, mev: 10, mav: 16, mrv: 20 }, back: { mv: 6, mev: 8, mav: 14, mrv: 18 }, shoulders: { mv: 4, mev: 6, mav: 12, mrv: 16 }, }, intelligence: {}, }; test("should initialize intelligence system successfully", () => { const result = initIntelligence(localMockState); expect(result).toHaveProperty("success", true); expect(result).toHaveProperty("intelligenceConfig"); expect(result).toHaveProperty("capabilities"); expect(result).toHaveProperty("status"); expect(result.status).toBe("initialized"); expect(Array.isArray(result.capabilities)).toBe(true); expect(result.capabilities.length).toBeGreaterThan(0); }); test("should configure intelligence parameters", () => { const result = initIntelligence(localMockState); expect(result.intelligenceConfig).toHaveProperty("adaptiveThresholds"); expect(result.intelligenceConfig).toHaveProperty("learningRate"); expect(result.intelligenceConfig).toHaveProperty("optimizationFrequency"); expect(typeof result.intelligenceConfig.learningRate).toBe("number"); expect(result.intelligenceConfig.learningRate).toBeGreaterThan(0); expect(result.intelligenceConfig.learningRate).toBeLessThanOrEqual(1); }); test("should handle missing training data gracefully", () => { const emptyState = { currentMesocycle: { currentWeek: 1, length: 4 }, weeklyProgram: { actualVolume: {} }, volumeLandmarks: {}, intelligence: {}, }; const result = initIntelligence(emptyState); expect(result).toHaveProperty("success", true); expect(result).toHaveProperty("warnings"); expect(Array.isArray(result.warnings)).toBe(true); }); test("should provide initialization recommendations", () => { const result = initIntelligence(localMockState); expect(result).toHaveProperty("recommendations"); expect(Array.isArray(result.recommendations)).toBe(true); expect(result.recommendations.length).toBeGreaterThan(0); }); }); describe("optimizeVolumeLandmarks", () => { const localMockState = { ...mockTrainingState, currentMesocycle: { currentWeek: 4, length: 6, }, weeklyProgram: { actualVolume: { chest: [10, 12, 14, 16], back: [8, 10, 12, 14], shoulders: [6, 8, 10, 12], }, }, volumeLandmarks: { chest: { mv: 8, mev: 10, mav: 16, mrv: 20 }, back: { mv: 6, mev: 8, mav: 14, mrv: 18 }, shoulders: { mv: 4, mev: 6, mav: 12, mrv: 16 }, }, intelligence: { isInitialized: true, adaptiveThresholds: true, }, }; test("should optimize volume landmarks based on performance data", () => { const result = optimizeVolumeLandmarks(localMockState); expect(result).toHaveProperty("success", true); expect(result).toHaveProperty("optimizedLandmarks"); expect(result).toHaveProperty("changes"); expect(result).toHaveProperty("confidence"); expect(typeof result.confidence).toBe("number"); expect(result.confidence).toBeGreaterThanOrEqual(0); expect(result.confidence).toBeLessThanOrEqual(100); }); test("should provide detailed optimization changes", () => { const result = optimizeVolumeLandmarks(localMockState); expect(result.changes).toHaveProperty("adjustments"); expect(result.changes).toHaveProperty("reasoning"); expect(Array.isArray(result.changes.adjustments)).toBe(true); expect(Array.isArray(result.changes.reasoning)).toBe(true); }); test("should maintain landmark relationships", () => { const result = optimizeVolumeLandmarks(localMockState); Object.keys(result.optimizedLandmarks).forEach((muscle) => { const landmarks = result.optimizedLandmarks[muscle]; // Ensure proper ordering: MV <= MEV <= MAV <= MRV expect(landmarks.mv).toBeLessThanOrEqual(landmarks.mev); expect(landmarks.mev).toBeLessThanOrEqual(landmarks.mav); expect(landmarks.mav).toBeLessThanOrEqual(landmarks.mrv); }); }); test("should require initialized intelligence system", () => { const uninitializedState = { ...localMockState, intelligence: { isInitialized: false }, }; const result = optimizeVolumeLandmarks(uninitializedState); expect(result.success).toBe(false); expect(result).toHaveProperty("error"); expect(result.error).toContain("intelligence"); }); test("should provide optimization metrics", () => { const result = optimizeVolumeLandmarks(localMockState); expect(result).toHaveProperty("metrics"); expect(result.metrics).toHaveProperty("totalAdjustments"); expect(result.metrics).toHaveProperty("avgConfidence"); expect(result.metrics).toHaveProperty("musclesOptimized"); expect(typeof result.metrics.totalAdjustments).toBe("number"); expect(typeof result.metrics.avgConfidence).toBe("number"); expect(Array.isArray(result.metrics.musclesOptimized)).toBe(true); }); }); describe("adaptiveRIRRecommendations", () => { const localMockState = { ...mockTrainingState, currentMesocycle: { currentWeek: 3, length: 6, phase: "accumulation", }, weeklyProgram: { actualVolume: { chest: [12, 14, 16], back: [10, 12, 14], }, }, volumeLandmarks: { chest: { mv: 8, mev: 10, mav: 16, mrv: 20 }, back: { mv: 6, mev: 8, mav: 14, mrv: 18 }, }, intelligence: { isInitialized: true, performanceMetrics: { rirAccuracy: 0.85, volumeResponse: 0.75, }, }, }; test("should provide adaptive RIR recommendations", () => { const result = adaptiveRIRRecommendations(localMockState); expect(result).toHaveProperty("success", true); expect(result).toHaveProperty("recommendations"); expect(result).toHaveProperty("rationale"); expect(result).toHaveProperty("adjustments"); expect(typeof result.recommendations).toBe("object"); expect(Object.keys(result.recommendations).length).toBeGreaterThan(0); }); test("should adjust RIR based on mesocycle phase", () => { const accumulationResult = adaptiveRIRRecommendations(localMockState); const intensificationState = { ...localMockState, currentMesocycle: { ...localMockState.currentMesocycle, phase: "intensification", }, }; const intensificationResult = adaptiveRIRRecommendations(intensificationState); expect(accumulationResult.success).toBe(true); expect(intensificationResult.success).toBe(true); // Intensification phase should generally have lower RIR recommendations const accRIR = Object.values(accumulationResult.recommendations)[0]; const intRIR = Object.values(intensificationResult.recommendations)[0]; expect(typeof accRIR).toBe("number"); expect(typeof intRIR).toBe("number"); }); test("should consider muscle-specific adaptations", () => { const result = adaptiveRIRRecommendations(localMockState); expect(result.recommendations).toHaveProperty("chest"); expect(result.recommendations).toHaveProperty("back"); Object.values(result.recommendations).forEach((rir) => { expect(typeof rir).toBe("number"); expect(rir).toBeGreaterThanOrEqual(0); expect(rir).toBeLessThanOrEqual(5); }); }); test("should provide detailed rationale", () => { const result = adaptiveRIRRecommendations(localMockState); expect(result.rationale).toHaveProperty("factorsConsidered"); expect(result.rationale).toHaveProperty("adaptationLevel"); expect(result.rationale).toHaveProperty("riskAssessment"); expect(Array.isArray(result.rationale.factorsConsidered)).toBe(true); expect(typeof result.rationale.adaptationLevel).toBe("string"); }); test("should handle missing performance metrics", () => { const stateWithoutMetrics = { ...localMockState, intelligence: { isInitialized: true }, }; const result = adaptiveRIRRecommendations(stateWithoutMetrics); expect(result).toHaveProperty("success", true); expect(result).toHaveProperty("warnings"); expect(Array.isArray(result.warnings)).toBe(true); }); test("should provide confidence scores", () => { const result = adaptiveRIRRecommendations(localMockState); expect(result).toHaveProperty("confidence"); expect(typeof result.confidence).toBe("number"); expect(result.confidence).toBeGreaterThanOrEqual(0); expect(result.confidence).toBeLessThanOrEqual(100); }); }); describe("Integration Tests", () => { test("should work together for complete intelligence workflow", () => { const trainingState = { ...mockTrainingState, currentMesocycle: { currentWeek: 3, length: 6, phase: "accumulation" }, weeklyProgram: { actualVolume: { chest: [10, 12, 14], back: [8, 10, 12], }, }, weeklyProgressionHistory: [ { week: 1, muscle: "chest", volume: 10, rpe: 7 }, { week: 2, muscle: "chest", volume: 12, rpe: 7.5 }, { week: 3, muscle: "chest", volume: 14, rpe: 8 }, { week: 1, muscle: "back", volume: 8, rpe: 7 }, { week: 2, muscle: "back", volume: 10, rpe: 7.5 }, { week: 3, muscle: "back", volume: 12, rpe: 8 }, ], volumeLandmarks: { chest: { mv: 8, mev: 10, mav: 16, mrv: 20 }, back: { mv: 6, mev: 8, mav: 14, mrv: 18 }, }, intelligence: {}, }; // 1. Initialize intelligence const initResult = initIntelligence(trainingState); expect(initResult.success).toBe(true); // Update state with initialization results and ensure volume landmarks are preserved const updatedState = { ...trainingState, intelligence: { isInitialized: true, ...initResult.intelligenceConfig, }, // Explicitly preserve volumeLandmarks volumeLandmarks: { chest: { mv: 8, mev: 10, mav: 16, mrv: 20 }, back: { mv: 6, mev: 8, mav: 14, mrv: 18 }, }, getWeeklySets: (muscle) => { const volumeData = trainingState.weeklyProgram?.actualVolume[muscle]; return volumeData ? volumeData[volumeData.length - 1] : 0; }, }; // 2. Optimize volume landmarks const optimizeResult = optimizeVolumeLandmarks(updatedState); expect(optimizeResult.success).toBe(true); // 3. Get adaptive RIR recommendations const rirResult = adaptiveRIRRecommendations(updatedState); // Debug - check why recommendations is empty if (Object.keys(rirResult.recommendations).length === 0) { console.error("RIR result has empty recommendations:", rirResult); console.error("Updated state landmarks:", updatedState.volumeLandmarks); console.error("Updated state intelligence:", updatedState.intelligence); } expect(rirResult.success).toBe(true); // Verify the workflow produces coherent results expect(Object.keys(rirResult.recommendations).length).toBeGreaterThan(0); expect(optimizeResult.confidence).toBeGreaterThan(0); }); }); });