diff --git a/LiftLog.Maui/LiftLog.Maui.csproj b/LiftLog.Maui/LiftLog.Maui.csproj index f481b4b9..f59f933c 100644 --- a/LiftLog.Maui/LiftLog.Maui.csproj +++ b/LiftLog.Maui/LiftLog.Maui.csproj @@ -69,6 +69,7 @@ true + true false true diff --git a/LiftLog.Ui/Store/CurrentSession/CurrentSessionState.cs b/LiftLog.Ui/Store/CurrentSession/CurrentSessionState.cs index a06f3178..f6a74535 100644 --- a/LiftLog.Ui/Store/CurrentSession/CurrentSessionState.cs +++ b/LiftLog.Ui/Store/CurrentSession/CurrentSessionState.cs @@ -8,5 +8,17 @@ public record CurrentSessionState( Session? HistorySession, Session? FeedSession, Guid? LatestSetTimerNotificationId - ); + ) + { + public static CurrentSessionState FromWorkoutSession(Session session) + { + return new CurrentSessionState( + IsHydrated: true, + WorkoutSession: session, + HistorySession: null, + FeedSession: null, + LatestSetTimerNotificationId: null + ); + } + } } diff --git a/tests/LiftLog.Tests.App/Encryption/OsEncryptionServiceTests.cs b/tests/LiftLog.Tests.App/Encryption/OsEncryptionServiceTests.cs index dfb08c4c..e66488b7 100644 --- a/tests/LiftLog.Tests.App/Encryption/OsEncryptionServiceTests.cs +++ b/tests/LiftLog.Tests.App/Encryption/OsEncryptionServiceTests.cs @@ -86,9 +86,9 @@ public static void Spec() ); // Assert - Assert.Equal(data1, decryptedData1); - Assert.Equal(data2, decryptedData2); - Assert.Equal(encryptedData1.IV, encryptedData2.IV); + data1.Should().Equal(decryptedData1); + data2.Should().Equal(decryptedData2); + encryptedData1.IV.Should().BeEquivalentTo(encryptedData2.IV); }); }); @@ -113,7 +113,7 @@ public static void Spec() encryptedData.EncryptedPayload[0] ^= 0xFF; // Assert - await Assert.ThrowsAsync( + Assert.ThrowsAsync( async () => await sut.DecryptAesCbcAndVerifyRsa256PssAsync( encryptedData, diff --git a/tests/LiftLog.Tests.App/GlobalUsings.cs b/tests/LiftLog.Tests.App/GlobalUsings.cs index fef46b37..3b2acbf2 100644 --- a/tests/LiftLog.Tests.App/GlobalUsings.cs +++ b/tests/LiftLog.Tests.App/GlobalUsings.cs @@ -1,7 +1,7 @@ global using System.Collections.Immutable; global using FluentAssertions; global using NSubstitute; +global using NUnit.Framework; global using Oatmilk; +global using Oatmilk.Nunit; global using static Oatmilk.TestBuilder; -global using Oatmilk.Xunit; -global using Xunit; diff --git a/tests/LiftLog.Tests.App/LiftLog.Tests.App.csproj b/tests/LiftLog.Tests.App/LiftLog.Tests.App.csproj index c05c8078..6afc30ff 100644 --- a/tests/LiftLog.Tests.App/LiftLog.Tests.App.csproj +++ b/tests/LiftLog.Tests.App/LiftLog.Tests.App.csproj @@ -10,15 +10,13 @@ - + - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/tests/LiftLog.Tests.App/SessionBehaviors/SessionSuperset.cs b/tests/LiftLog.Tests.App/SessionBehaviors/SessionSuperset.cs new file mode 100644 index 00000000..d1c3cba5 --- /dev/null +++ b/tests/LiftLog.Tests.App/SessionBehaviors/SessionSuperset.cs @@ -0,0 +1,191 @@ +using LiftLog.Lib.Models; +using LiftLog.Ui.Store.CurrentSession; + +namespace LiftLog.Tests.App.SessionBehaviors; + +public class SessionSupersetTests +{ + [Describe("Session supersets")] + public void Spec() + { + Describe( + "When given a session with supersets", + () => + { + Session session = null!; + CurrentSessionState GetState() => CurrentSessionState.FromWorkoutSession(session); + Session CycleExerciseReps(int exerciseIndex, int setIndex) => + CurrentSessionReducers + .CycleExerciseReps( + GetState(), + new CycleExerciseRepsAction( + SessionTarget.WorkoutSession, + ExerciseIndex: exerciseIndex, + SetIndex: setIndex + ) + ) + .WorkoutSession!; + + ExerciseBlueprint Exercise(int index, bool supersetWithNext) => + Blueprints.CreateExerciseBlueprint(x => + x with + { + Name = $"Ex{index}", + SupersetWithNext = supersetWithNext + } + ); + + BeforeEach( + () => + session = Sessions.CreateSession( + sessionBlueprint: Blueprints.CreateSessionBlueprint() with + { + Exercises = + [ + Exercise(0, supersetWithNext: false), + Exercise(1, supersetWithNext: true), + Exercise(2, supersetWithNext: false), + Exercise(3, supersetWithNext: true), + Exercise(4, supersetWithNext: true), + Exercise(5, supersetWithNext: false) + ] + }, + fillFirstSet: false + ) + ); + + It("should have the first exercise and set as the next exercise") + .When(() => + { + var nextExercise = session.NextExercise; + nextExercise.Should().NotBeNull(); + nextExercise.Blueprint.Name.Should().Be(session.RecordedExercises[0].Blueprint.Name); + }); + + Describe("and the last completed set was the first exercise (not a superset)") + .As(() => + { + BeforeEach(() => + { + session = CycleExerciseReps(0, 0); + }); + + It( + "Should have the next set be the first exercise", + () => + { + var nextExercise = session.NextExercise; + nextExercise.Should().NotBeNull(); + nextExercise + .Blueprint.Name.Should() + .Be(session.RecordedExercises[0].Blueprint.Name); + } + ); + }); + + Describe( + "and the last completed set was the second exercise (a superset with the third exercise)" + ) + .As(() => + { + BeforeEach(() => + { + session = CycleExerciseReps(1, 0); + }); + + It("Should have the next set be the third exercise") + .When(() => + { + var nextExercise = session.NextExercise; + nextExercise.Should().NotBeNull(); + nextExercise + .Blueprint.Name.Should() + .Be(session.RecordedExercises[2].Blueprint.Name); + }); + }); + Describe( + "and the last completed set was the third exercise (a superset with the previous exercise)" + ) + .As(() => + { + BeforeEach(() => + { + session = CycleExerciseReps(2, 0); + }); + + It("Should have the next set be the second exercise") + .When(() => + { + var nextExercise = session.NextExercise; + nextExercise.Should().NotBeNull(); + nextExercise + .Blueprint.Name.Should() + .Be(session.RecordedExercises[1].Blueprint.Name); + }); + }); + Describe( + "and the last completed set was the fourth exercise (a superset with the fifth and sixth exercise)" + ) + .As(() => + { + BeforeEach(() => + { + session = CycleExerciseReps(3, 0); + }); + + It("Should have the next set be the fifth exercise") + .When(() => + { + var nextExercise = session.NextExercise; + nextExercise.Should().NotBeNull(); + nextExercise + .Blueprint.Name.Should() + .Be(session.RecordedExercises[4].Blueprint.Name); + }); + }); + + Describe( + "and the last completed set was the fifth exercise (a superset with the fourth and sixth exercise)" + ) + .As(() => + { + BeforeEach(() => + { + session = CycleExerciseReps(4, 0); + }); + + It("Should have the next set be the sixth exercise") + .When(() => + { + var nextExercise = session.NextExercise; + nextExercise.Should().NotBeNull(); + nextExercise + .Blueprint.Name.Should() + .Be(session.RecordedExercises[5].Blueprint.Name); + }); + }); + + Describe( + "and the last completed set was the sixth exercise (a superset with the fourth and fifth exercise)" + ) + .As(() => + { + BeforeEach(() => + { + session = CycleExerciseReps(4, 0); + }); + + It("Should have the next set be the fourth exercise") + .When(() => + { + var nextExercise = session.NextExercise; + nextExercise.Should().NotBeNull(); + nextExercise + .Blueprint.Name.Should() + .Be(session.RecordedExercises[4].Blueprint.Name); + }); + }); + } + ); + } +} diff --git a/tests/LiftLog.Tests.App/Sessions.cs b/tests/LiftLog.Tests.App/Sessions.cs index 3f1505ac..6e66073f 100644 --- a/tests/LiftLog.Tests.App/Sessions.cs +++ b/tests/LiftLog.Tests.App/Sessions.cs @@ -6,7 +6,8 @@ public static class Sessions { public static Session CreateSession( SessionBlueprint? sessionBlueprint = null, - Func? transform = null + Func? transform = null, + bool fillFirstSet = true ) { sessionBlueprint ??= Blueprints.CreateSessionBlueprint(); @@ -15,7 +16,7 @@ public static Session CreateSession( Id: Guid.NewGuid(), Blueprint: sessionBlueprint, RecordedExercises: sessionBlueprint - .Exercises.Select(x => CreateRecordedExercise(x)) + .Exercises.Select(x => CreateRecordedExercise(x, fillFirstSet: fillFirstSet)) .ToImmutableList(), Date: DateOnly.Parse("2021-04-05"), Bodyweight: null @@ -25,7 +26,8 @@ public static Session CreateSession( public static RecordedExercise CreateRecordedExercise( ExerciseBlueprint? exerciseBlueprint = null, - Func? transform = null + Func? transform = null, + bool fillFirstSet = true ) { exerciseBlueprint ??= Blueprints.CreateExerciseBlueprint(); @@ -37,9 +39,9 @@ public static RecordedExercise CreateRecordedExercise( .Range(0, exerciseBlueprint.Sets) .Select( (i) => - i switch + (fillFirstSet, i) switch { - 0 + (true, 0) => new PotentialSet( new( RepsCompleted: exerciseBlueprint.RepsPerSet,