Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 30 additions & 30 deletions test/ClinicalScheduler/EvaluationPolicyServiceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,18 +91,18 @@ public void RequiresPrimaryEvaluator_RotationClosed_ReturnsFalse()
};

// Act - Pass rotationClosed = true
var result = _service.RequiresPrimaryEvaluator(5, weeks, serviceWeekSize: 2, rotationClosed: true);
var result = _service.RequiresPrimaryEvaluator(5, weeks, serviceMinConsecutiveWeeks: 2, rotationClosed: true);

// Assert
Assert.False(result);
}

#endregion

#region WeekSize = 1 Tests
#region MinConsecutiveWeeks = 1 Tests

[Fact]
public void RequiresPrimaryEvaluator_WeekSize1_NonExtendedWeek_ReturnsTrue()
public void RequiresPrimaryEvaluator_MinConsecutiveWeeks1_NonExtendedWeek_ReturnsTrue()
{
// Arrange
var weeks = new List<TestRotationWeekInfo>
Expand All @@ -111,14 +111,14 @@ public void RequiresPrimaryEvaluator_WeekSize1_NonExtendedWeek_ReturnsTrue()
};

// Act
var result = _service.RequiresPrimaryEvaluator(5, weeks, serviceWeekSize: 1);
var result = _service.RequiresPrimaryEvaluator(5, weeks, serviceMinConsecutiveWeeks: 1);

// Assert
Assert.True(result);
}

[Fact]
public void RequiresPrimaryEvaluator_WeekSize1_ExtendedWeek_ReturnsFalse()
public void RequiresPrimaryEvaluator_MinConsecutiveWeeks1_ExtendedWeek_ReturnsFalse()
{
// Arrange
var weeks = new List<TestRotationWeekInfo>
Expand All @@ -127,18 +127,18 @@ public void RequiresPrimaryEvaluator_WeekSize1_ExtendedWeek_ReturnsFalse()
};

// Act
var result = _service.RequiresPrimaryEvaluator(5, weeks, serviceWeekSize: 1);
var result = _service.RequiresPrimaryEvaluator(5, weeks, serviceMinConsecutiveWeeks: 1);

// Assert
Assert.False(result);
}

#endregion

#region WeekSize = 2 Tests
#region MinConsecutiveWeeks = 2 Tests

[Fact]
public void RequiresPrimaryEvaluator_WeekSize2_StartWeek_ReturnsFalse()
public void RequiresPrimaryEvaluator_MinConsecutiveWeeks2_StartWeek_ReturnsFalse()
{
// Arrange - First week of a 2-week block
var weeks = new List<TestRotationWeekInfo>
Expand All @@ -148,14 +148,14 @@ public void RequiresPrimaryEvaluator_WeekSize2_StartWeek_ReturnsFalse()
};

// Act
var result = _service.RequiresPrimaryEvaluator(28, weeks, serviceWeekSize: 2);
var result = _service.RequiresPrimaryEvaluator(28, weeks, serviceMinConsecutiveWeeks: 2);

// Assert
Assert.False(result); // First week doesn't need evaluator
}

[Fact]
public void RequiresPrimaryEvaluator_WeekSize2_SecondWeek_ReturnsTrue()
public void RequiresPrimaryEvaluator_MinConsecutiveWeeks2_SecondWeek_ReturnsTrue()
{
// Arrange - Second week of a 2-week block
var weeks = new List<TestRotationWeekInfo>
Expand All @@ -165,14 +165,14 @@ public void RequiresPrimaryEvaluator_WeekSize2_SecondWeek_ReturnsTrue()
};

// Act
var result = _service.RequiresPrimaryEvaluator(29, weeks, serviceWeekSize: 2);
var result = _service.RequiresPrimaryEvaluator(29, weeks, serviceMinConsecutiveWeeks: 2);

// Assert
Assert.True(result); // Second week needs evaluator
}

[Fact]
public void RequiresPrimaryEvaluator_WeekSize2_ThreeWeekRotationWithExtended_ReturnsFalse()
public void RequiresPrimaryEvaluator_MinConsecutiveWeeks2_ThreeWeekRotationWithExtended_ReturnsFalse()
{
// Arrange - 3-week rotation where week 3 is extended
var weeks = new List<TestRotationWeekInfo>
Expand All @@ -183,14 +183,14 @@ public void RequiresPrimaryEvaluator_WeekSize2_ThreeWeekRotationWithExtended_Ret
};

// Act - Check week 32 (would normally be evaluation week, but week 33 is extended)
var result = _service.RequiresPrimaryEvaluator(32, weeks, serviceWeekSize: 2);
var result = _service.RequiresPrimaryEvaluator(32, weeks, serviceMinConsecutiveWeeks: 2);

// Assert
Assert.False(result); // No evaluation needed because week 3 is extended
}

[Fact]
public void RequiresPrimaryEvaluator_WeekSize2_RegularTwoWeekBlock_SecondWeekTrue()
public void RequiresPrimaryEvaluator_MinConsecutiveWeeks2_RegularTwoWeekBlock_SecondWeekTrue()
{
// Arrange - Regular 2-week block
var weeks = new List<TestRotationWeekInfo>
Expand All @@ -201,14 +201,14 @@ public void RequiresPrimaryEvaluator_WeekSize2_RegularTwoWeekBlock_SecondWeekTru
};

// Act - Check week 36 (second week of block)
var result = _service.RequiresPrimaryEvaluator(36, weeks, serviceWeekSize: 2);
var result = _service.RequiresPrimaryEvaluator(36, weeks, serviceMinConsecutiveWeeks: 2);

// Assert
Assert.True(result); // Second week needs evaluator
}

[Fact]
public void RequiresPrimaryEvaluator_WeekSize2_LastWeekOfYear_ReturnsTrue()
public void RequiresPrimaryEvaluator_MinConsecutiveWeeks2_LastWeekOfYear_ReturnsTrue()
{
// Arrange - Last week with no next week
var weeks = new List<TestRotationWeekInfo>
Expand All @@ -218,7 +218,7 @@ public void RequiresPrimaryEvaluator_WeekSize2_LastWeekOfYear_ReturnsTrue()
};

// Act - Check week 43 (last week, no next week)
var result = _service.RequiresPrimaryEvaluator(43, weeks, serviceWeekSize: 2);
var result = _service.RequiresPrimaryEvaluator(43, weeks, serviceMinConsecutiveWeeks: 2);

// Assert
Assert.True(result); // Last week needs evaluator
Expand Down Expand Up @@ -289,36 +289,36 @@ public void RequiresPrimaryEvaluator_Rotation603Year2026_CorrectEvaluation(int w
var relevantWeeks = weeks.Where(w => w.WeekNum >= weekNum - 1 && w.WeekNum <= weekNum + 1).ToList();

// Act
var result = _service.RequiresPrimaryEvaluator(weekNum, relevantWeeks, serviceWeekSize: 2);
var result = _service.RequiresPrimaryEvaluator(weekNum, relevantWeeks, serviceMinConsecutiveWeeks: 2);

// Assert
Assert.Equal(shouldRequireEvaluator, result);
}

#endregion

#region No WeekSize Configuration Tests
#region No MinConsecutiveWeeks Configuration Tests

[Fact]
public void RequiresPrimaryEvaluator_NoWeekSize_ReturnsFalse()
public void RequiresPrimaryEvaluator_NoMinConsecutiveWeeks_ReturnsFalse()
{
// Arrange
var weeks = new List<TestRotationWeekInfo>
{
new() { WeekNum = 5, ExtendedRotation = false }
};

// Act - No serviceWeekSize provided
// Act - No serviceMinConsecutiveWeeks provided
var result = _service.RequiresPrimaryEvaluator(5, weeks);

// Assert
Assert.False(result); // Default behavior when no weekSize
Assert.False(result); // Default behavior when no MinConsecutiveWeeks
}

[Theory]
[InlineData(0)]
[InlineData(-1)]
public void RequiresPrimaryEvaluator_InvalidWeekSize_ReturnsFalse(int weekSize)
public void RequiresPrimaryEvaluator_InvalidMinConsecutiveWeeks_ReturnsFalse(int MinConsecutiveWeeks)
{
// Arrange
var weeks = new List<TestRotationWeekInfo>
Expand All @@ -327,15 +327,15 @@ public void RequiresPrimaryEvaluator_InvalidWeekSize_ReturnsFalse(int weekSize)
};

// Act
var result = _service.RequiresPrimaryEvaluator(5, weeks, serviceWeekSize: weekSize);
var result = _service.RequiresPrimaryEvaluator(5, weeks, serviceMinConsecutiveWeeks: MinConsecutiveWeeks);

// Assert
Assert.False(result); // Invalid weekSize (0, negative) defaults to false
Assert.False(result); // Invalid MinConsecutiveWeeks (0, negative) defaults to false
}


[Fact]
public void RequiresPrimaryEvaluator_WeekSize4_OnlyLastWeekRequiresEvaluation()
public void RequiresPrimaryEvaluator_MinConsecutiveWeeks4_OnlyLastWeekRequiresEvaluation()
{
// Arrange - 4-week rotation blocks
var weeks = new List<TestRotationWeekInfo>
Expand All @@ -348,10 +348,10 @@ public void RequiresPrimaryEvaluator_WeekSize4_OnlyLastWeekRequiresEvaluation()
};

// Act & Assert - For 4-week blocks, only the last week (4th) should require evaluation
Assert.False(_service.RequiresPrimaryEvaluator(10, weeks, serviceWeekSize: 4)); // First week
Assert.False(_service.RequiresPrimaryEvaluator(11, weeks, serviceWeekSize: 4)); // Second week
Assert.False(_service.RequiresPrimaryEvaluator(12, weeks, serviceWeekSize: 4)); // Third week
Assert.True(_service.RequiresPrimaryEvaluator(13, weeks, serviceWeekSize: 4)); // Fourth week (last)
Assert.False(_service.RequiresPrimaryEvaluator(10, weeks, serviceMinConsecutiveWeeks: 4)); // First week
Assert.False(_service.RequiresPrimaryEvaluator(11, weeks, serviceMinConsecutiveWeeks: 4)); // Second week
Assert.False(_service.RequiresPrimaryEvaluator(12, weeks, serviceMinConsecutiveWeeks: 4)); // Third week
Assert.True(_service.RequiresPrimaryEvaluator(13, weeks, serviceMinConsecutiveWeeks: 4)); // Fourth week (last)
}

#endregion
Expand Down
2 changes: 1 addition & 1 deletion test/ClinicalScheduler/RotationMappingExtensionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public void ToDto_MapsRotationPropertiesCorrectly()
ServiceId = 10,
ServiceName = "Surgery Service",
ShortName = "Surgery",
WeekSize = 2,
MinConsecutiveWeeks = 2,
ScheduleEditPermission = "SVMSecure.ClnSched.EditSurgery"
}
};
Expand Down
81 changes: 81 additions & 0 deletions test/ClinicalScheduler/RotationsControllerTest.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using MockQueryable.NSubstitute;
using NSubstitute;
using Viper.Areas.ClinicalScheduler.Controllers;
using Viper.Areas.ClinicalScheduler.Models.DTOs.Responses;
using Viper.Areas.ClinicalScheduler.Services;
using Viper.Models.ClinicalScheduler;

namespace Viper.test.ClinicalScheduler
{
Expand Down Expand Up @@ -330,6 +332,85 @@ public async Task GetRotation_AccessDeniedRotation_ReturnsForbidden()
// The security is working correctly - users only see services they have permissions for


#endregion

#region BuildWeekScheduleItem Tests (lines 522-528)

// Empty InstructorSchedules avoids the Week navigation property NPE that occurs in
// GetRecentCliniciansAsync when MockQueryable doesn't load navigation properties.
private void SetupForScheduleResponse()
{
var instSched = new List<InstructorSchedule>().BuildMockDbSet();
var rwp = new List<RotationWeeklyPref>().BuildMockDbSet();

MockContext.InstructorSchedules.Returns(instSched);
MockContext.RotationWeeklyPrefs.Returns(rwp);

var baseDate = new DateTime(TestYear, 6, 1, 0, 0, 0, DateTimeKind.Utc);
_mockWeekService.GetWeeksAsync(Arg.Any<int>(), Arg.Any<bool>(), Arg.Any<CancellationToken>())
.Returns(
[
new() { WeekId = 1, WeekNum = 1, DateStart = baseDate, DateEnd = baseDate.AddDays(6), TermCode = TestTermCode },
new() { WeekId = 2, WeekNum = 2, DateStart = baseDate.AddDays(7), DateEnd = baseDate.AddDays(13), TermCode = TestTermCode }
]);
}

private static RotationDto CardiologyRotationWithMinConsecutiveWeeks(int? minConsecutiveWeeks) => new()
{
RotId = CardiologyRotationId,
Name = "Cardiology",
ServiceId = CardiologyServiceId,
Service = new ServiceDto
{
ServiceId = CardiologyServiceId,
ServiceName = "Cardiology Service",
MinConsecutiveWeeks = minConsecutiveWeeks
}
};

#endregion

#region BuildSimpleRotationResponse Tests (lines 621-627)

[Fact]
public async Task GetRotationSchedule_WhenNoWeeks_ServiceMinConsecutiveWeeksIsIncludedInResponse()
{
SetupMockPermissions(hasFullPermissions: true);
_mockWeekService.GetWeeksAsync(Arg.Any<int>(), Arg.Any<bool>(), Arg.Any<CancellationToken>())
.Returns([]);

const int minConsecutiveWeeks = 4;
_mockRotationService.GetRotationAsync(CardiologyRotationId, Arg.Any<CancellationToken>())
.Returns(CardiologyRotationWithMinConsecutiveWeeks(minConsecutiveWeeks));
RecreateController();

var result = await _controller.GetRotationSchedule(CardiologyRotationId, TestYear);

var okResult = Assert.IsType<OkObjectResult>(result.Result);
var rotationProp = okResult.Value!.GetType().GetProperty("Rotation")?.GetValue(okResult.Value);
var serviceProp = rotationProp?.GetType().GetProperty("Service")?.GetValue(rotationProp);
var actual = serviceProp?.GetType().GetProperty("MinConsecutiveWeeks")?.GetValue(serviceProp);
Assert.Equal(minConsecutiveWeeks, (int?)actual);
}

[Fact]
public async Task GetRotationSchedule_WhenNoWeeks_AndServiceIsNull_ServiceIsNullInResponse()
{
SetupMockPermissions(hasFullPermissions: true);
_mockWeekService.GetWeeksAsync(Arg.Any<int>(), Arg.Any<bool>(), Arg.Any<CancellationToken>())
.Returns([]);
_mockRotationService.GetRotationAsync(CardiologyRotationId, Arg.Any<CancellationToken>())
.Returns(new RotationDto { RotId = CardiologyRotationId, Name = "Cardiology", ServiceId = CardiologyServiceId, Service = null });
RecreateController();

var result = await _controller.GetRotationSchedule(CardiologyRotationId, TestYear);

var okResult = Assert.IsType<OkObjectResult>(result.Result);
var rotationProp = okResult.Value!.GetType().GetProperty("Rotation")?.GetValue(okResult.Value);
var serviceProp = rotationProp?.GetType().GetProperty("Service")?.GetValue(rotationProp);
Assert.Null(serviceProp);
}

#endregion

#region GetRotationsWithScheduledWeeks Security Tests
Expand Down
12 changes: 6 additions & 6 deletions test/ClinicalScheduler/ServiceMappingExtensionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public void ToDto_MapsServicePropertiesCorrectly()
ServiceId = 10,
ServiceName = "Surgery Service",
ShortName = "Surgery",
WeekSize = 2,
MinConsecutiveWeeks = 2,
ScheduleEditPermission = "SVMSecure.ClnSched.EditSurgery"
};

Expand All @@ -24,7 +24,7 @@ public void ToDto_MapsServicePropertiesCorrectly()
// Assert
Assert.Equal(service.ServiceId, dto.ServiceId);
Assert.Equal(service.ServiceName, dto.ServiceName);
Assert.Equal(service.WeekSize, dto.WeekSize);
Assert.Equal(service.MinConsecutiveWeeks, dto.MinConsecutiveWeeks);
Assert.Equal(service.ScheduleEditPermission, dto.ScheduleEditPermission);
}

Expand Down Expand Up @@ -73,7 +73,7 @@ public void ToDto_HandlesNullScheduleEditPermission()
ServiceId = 10,
ServiceName = "Surgery Service",
ShortName = "Surgery",
WeekSize = 2,
MinConsecutiveWeeks = 2,
ScheduleEditPermission = null
};

Expand All @@ -86,22 +86,22 @@ public void ToDto_HandlesNullScheduleEditPermission()
}

[Fact]
public void ToDto_HandlesZeroWeekSize()
public void ToDto_HandlesZeroMinConsecutiveWeeks()
{
// Arrange
var service = new Service
{
ServiceId = 10,
ServiceName = "Special Service",
ShortName = "SPEC",
WeekSize = 0
MinConsecutiveWeeks = 0
};

// Act
var dto = service.ToDto();

// Assert
Assert.Equal(0, dto.WeekSize);
Assert.Equal(0, dto.MinConsecutiveWeeks);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,7 @@ private object BuildWeekScheduleItem(WeekDto week, IEnumerable<InstructorSchedul
var requiresPrimary = _evaluationPolicyService.RequiresPrimaryEvaluator(
week.WeekNum,
rotationWeeks,
rotation?.Service?.WeekSize,
rotation?.Service?.MinConsecutiveWeeks,
rotationClosed);

return new
Expand Down Expand Up @@ -621,7 +621,7 @@ private object BuildSimpleRotationResponse(RotationDto rotation)
{
rotation.Service.ServiceId,
rotation.Service.ServiceName,
rotation.Service.WeekSize
rotation.Service.MinConsecutiveWeeks
} : null
};
}
Expand Down
Loading
Loading