using Kit.Helpers.SqlHelperAbstract; using Server.WatchBody.Core.Dal.Src.Domain; using Server.WatchBody.Core.Dal.Src.Repository; using Xunit; namespace Server.WatchBody.Core.Tests; // Тесты DailyLogRepository / WorkoutMetricsRepository / BreakRepository // по repository_tests\DailyLogRepository.md, WorkoutMetricsRepository.md, BreakRepository.md. public class DailyLogRepositoryTests { private static readonly Guid D1 = Guid.Parse("dddd0000-0000-0000-0000-000000000001"); [Fact] public void Upsert_1Основной_8Параметров() { var expArgs = new ConnectionString().PrepareExecute("src.daily_log_upsert") .AsStoredProcedure() .AddParameter("p_athlete_id", 1) .AddParameter("p_id", D1) .AddParameter("p_date", new DateOnly(2026, 10, 17)) .AddParameter("p_bp_sys", 130) .AddParameter("p_bp_dias", 80) .AddParameter("p_weight_kg", 157.5m) .AddParameter("p_hr_resting", 60) .AddParameter("p_wellbeing", 5) .BuildParams(); var cs = ConnectionStringTest.Scalar(expArgs, D1); var result = new DailyLogRepository(cs).Upsert(1, new DailyLog { Id = D1, Date = new DateOnly(2026, 10, 17), BpSys = 130, BpDias = 80, WeightKg = 157.5m, HrResting = 60, Wellbeing = 5, }); Assert.Equal(D1, result); } [Fact] public void Select_1Основной_1Сущность() { var expArgs = new ConnectionString().PrepareExecute("src.daily_log_select") .AsStoredProcedure() .AddParameter("p_athlete_id", 1) .AddParameter("p_date_from", DBNull.Value) .AddParameter("p_date_to", DBNull.Value) .BuildParams(); var table = TestInfra.Table(TestInfra.DailyLogCols, [D1, 1, new DateTime(2026, 10, 17), 130, 80, 157.5m, 60, DBNull.Value, DBNull.Value, 5]); var cs = new ConnectionStringTest(expArgs, table); var rows = new DailyLogRepository(cs).Select(new DailyLogFilter { AthleteId = 1 }).ToList(); var d = Assert.Single(rows); Assert.Equal(new DateOnly(2026, 10, 17), d.Date); Assert.Null(d.WaistCm); } [Fact] public void Select_2Граничный_Пустая() { var expArgs = new ConnectionString().PrepareExecute("src.daily_log_select") .AsStoredProcedure() .AddParameter("p_athlete_id", 1) .AddParameter("p_date_from", DBNull.Value) .AddParameter("p_date_to", DBNull.Value) .BuildParams(); var cs = new ConnectionStringTest(expArgs, TestInfra.Table(TestInfra.DailyLogCols)); Assert.Empty(new DailyLogRepository(cs).Select(new DailyLogFilter { AthleteId = 1 })); } } public class WorkoutMetricsRepositoryTests { private static readonly Guid W1 = Guid.Parse("aaaa0000-0000-0000-0000-000000000001"); [Fact] public void Upsert_1Основной_8Параметров() { var expArgs = new ConnectionString().PrepareExecute("src.workout_metrics_upsert") .AsStoredProcedure() .AddParameter("p_athlete_id", 1) .AddParameter("p_workout_id", W1) .AddParameter("p_adherence", 92.5m) .AddParameter("p_tonnage", 4200.0m) .AddParameter("p_tonnage_by_group", "{\"push\":4200}") .AddParameter("p_e1pm_by_exercise", "{}") .AddParameter("p_hr_metrics", "{}") .AddParameter("p_red_flags", "[]") .BuildParams(); var cs = ConnectionStringTest.Scalar(expArgs, 9); var result = new WorkoutMetricsRepository(cs).Upsert(1, new WorkoutMetrics { WorkoutId = W1, Adherence = 92.5m, Tonnage = 4200.0m, TonnageByGroup = "{\"push\":4200}", E1pmByExercise = "{}", HrMetrics = "{}", RedFlags = "[]", }); Assert.Equal(9, result); } [Fact] public void Select_1Основной_StartedAt() { var expArgs = new ConnectionString().PrepareExecute("src.workout_metrics_select") .AsStoredProcedure() .AddParameter("p_athlete_id", 1) .AddParameter("p_workout_id", DBNull.Value) .AddParameter("p_date_from", DBNull.Value) .AddParameter("p_date_to", DBNull.Value) .BuildParams(); var table = TestInfra.Table(TestInfra.MetricsCols, [9, W1, 1, 92.5m, 4200.0m, "{}", "{}", "{}", "[]", new DateTime(2026, 10, 17, 20, 0, 0), new DateTime(2026, 10, 17, 18, 0, 0)]); var cs = new ConnectionStringTest(expArgs, table); var rows = new WorkoutMetricsRepository(cs).Select(new WorkoutMetricsFilter { AthleteId = 1 }).ToList(); var m = Assert.Single(rows); Assert.Equal(92.5m, m.Adherence); } [Fact] public void Select_2Граничный_Пустая() { var expArgs = new ConnectionString().PrepareExecute("src.workout_metrics_select") .AsStoredProcedure() .AddParameter("p_athlete_id", 1) .AddParameter("p_workout_id", DBNull.Value) .AddParameter("p_date_from", DBNull.Value) .AddParameter("p_date_to", DBNull.Value) .BuildParams(); var cs = new ConnectionStringTest(expArgs, TestInfra.Table(TestInfra.MetricsCols)); Assert.Empty(new WorkoutMetricsRepository(cs).Select(new WorkoutMetricsFilter { AthleteId = 1 })); } } public class BreakRepositoryTests { private static readonly Guid B1 = Guid.Parse("eeee0000-0000-0000-0000-000000000001"); private static readonly Guid B2 = Guid.Parse("eeee0000-0000-0000-0000-000000000002"); [Fact] public void Insert_1Основной_KindNull_КакDbNull() { var expArgs = new ConnectionString().PrepareExecute("src.break_insert") .AsStoredProcedure() .AddParameter("p_athlete_id", 1) .AddParameter("p_id", B2) .AddParameter("p_kind", DBNull.Value) .AddParameter("p_source", "auto") .AddParameter("p_started_on", new DateOnly(2026, 10, 1)) .AddParameter("p_planned_return", DBNull.Value) .AddParameter("p_note", "") .BuildParams(); var cs = ConnectionStringTest.Scalar(expArgs, B2); var result = new BreakRepository(cs).Insert(1, new Break { Id = B2, Kind = null, Source = "auto", StartedOn = new DateOnly(2026, 10, 1), PlannedReturn = null, Note = "", }); Assert.Equal(B2, result); } [Fact] public void Update_1Основной_6Параметров() { var expArgs = new ConnectionString().PrepareExecute("src.break_update") .AsStoredProcedure() .AddParameter("p_athlete_id", 1) .AddParameter("p_id", B1) .AddParameter("p_kind", "vacation") .AddParameter("p_note", "TEST-отпуск") .AddParameter("p_planned_return", new DateOnly(2026, 10, 27)) .AddParameter("p_ended_on", DBNull.Value) .BuildParams(); var cs = ConnectionStringTest.Scalar(expArgs, 1); var result = new BreakRepository(cs).Update(1, new Break { Id = B1, Kind = "vacation", Note = "TEST-отпуск", PlannedReturn = new DateOnly(2026, 10, 27), EndedOn = null, }); Assert.Equal(1, result); } [Fact] public void Select_1Основной_2Сущности_KindNull() { var expArgs = new ConnectionString().PrepareExecute("src.break_select") .AsStoredProcedure() .AddParameter("p_athlete_id", 1) .AddParameter("p_kind", DBNull.Value) .AddParameter("p_date_from", DBNull.Value) .AddParameter("p_date_to", DBNull.Value) .BuildParams(); var table = TestInfra.Table(TestInfra.BreakCols, [B1, 1, "vacation", "manual", new DateTime(2026, 10, 20), new DateTime(2026, 10, 27), DBNull.Value, "TEST-отпуск"], [B2, 1, DBNull.Value, "auto", new DateTime(2026, 10, 1), DBNull.Value, DBNull.Value, ""]); var cs = new ConnectionStringTest(expArgs, table); var rows = new BreakRepository(cs).Select(new BreakFilter { AthleteId = 1 }).ToList(); Assert.Equal(2, rows.Count); Assert.Null(rows[1].Kind); Assert.Equal(DateOnly.FromDateTime(new DateTime(2026, 10, 20)), rows[0].StartedOn); } [Fact] public void Select_2Граничный_Пустая() { var expArgs = new ConnectionString().PrepareExecute("src.break_select") .AsStoredProcedure() .AddParameter("p_athlete_id", 1) .AddParameter("p_kind", DBNull.Value) .AddParameter("p_date_from", DBNull.Value) .AddParameter("p_date_to", DBNull.Value) .BuildParams(); var cs = new ConnectionStringTest(expArgs, TestInfra.Table(TestInfra.BreakCols)); Assert.Empty(new BreakRepository(cs).Select(new BreakFilter { AthleteId = 1 })); } }