Skip to content
Draft
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
80 changes: 79 additions & 1 deletion LineUp.Backend.Tests/CRUDTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,6 @@
public async Task CreateAvailability_Test()
{
// Arrange
sampleAvailability.Schedule = sampleSchedule;
var options = new DbContextOptionsBuilder<LineUpContext>()
.UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
.Options;
Expand Down Expand Up @@ -411,4 +410,83 @@
);
}
}

[Fact]
public async Task CreateRandomSchedule_Test()
{
// Arrange
var options = new DbContextOptionsBuilder<LineUpContext>()
.UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
.Options;

Random random = new Random();

List<DateOnly> randomCoverage = new List<DateOnly>();

for (int i = 0; i < random.Next(10); i++)
{
randomCoverage.Add(DateOnly.FromDateTime(DateTime.UtcNow.AddDays(i)));
}

Schedule randomSchedule = new Schedule
{
Guid = Guid.Empty,
Auth0UserId = "always-test-on-schedule",
DateCoverage = randomCoverage.ToArray(),
StartTime = new TimeOnly(9, 0),
EndTime = new TimeOnly(17, 0),
SchedulePreferences = new SchedulePreferences
{
MinutesPerSlot = 30,
ShiftIntervals = 30,
UsersPerShift = 1,
MaximumShiftDurationMinutes = 120,
MaximumShiftsPerWorker = 1,
},
Name = "Test Schedule",
};

using (var context = new LineUpContext(options))
{
context.Database.EnsureCreated();

var controller = new ScheduleController(context);

Check failure on line 453 in LineUp.Backend.Tests/CRUDTests.cs

View workflow job for this annotation

GitHub Actions / build

There is no argument given that corresponds to the required parameter 'emailService' of 'ScheduleController.ScheduleController(LineUpContext, IEmailService)'

Check failure on line 453 in LineUp.Backend.Tests/CRUDTests.cs

View workflow job for this annotation

GitHub Actions / build

There is no argument given that corresponds to the required parameter 'emailService' of 'ScheduleController.ScheduleController(LineUpContext, IEmailService)'

// Create a mock ClaimsPrincipal with the required NameIdentifier claim
var claims = new List<Claim> { new Claim(ClaimTypes.NameIdentifier, "test-user-123") };
var identity = new ClaimsIdentity(claims);
var principal = new ClaimsPrincipal(identity);
controller.ControllerContext = new ControllerContext
{
HttpContext = new DefaultHttpContext { User = principal },
};

var scheduleDto = new ScheduleDto
{
DateCoverage = randomSchedule.DateCoverage,
StartTime = randomSchedule.StartTime,
EndTime = randomSchedule.EndTime,
SchedulePreferences = randomSchedule.SchedulePreferences,
Name = randomSchedule.Name,
};

// Act
var result = await controller.CreateSchedule(scheduleDto);

// Assert
var createdResult = Assert.IsType<CreatedAtActionResult>(result);
Assert.Equal(nameof(ScheduleController.GetSchedule), createdResult.ActionName);
Assert.NotNull(createdResult.Value);

var returnedSchedule = Assert.IsType<Schedule>(createdResult.Value);
Assert.Equal("test-user-123", returnedSchedule.Auth0UserId);
Assert.Equal(randomSchedule.Name, returnedSchedule.Name);
Assert.Equal(randomSchedule.StartTime, returnedSchedule.StartTime);
Assert.Equal(randomSchedule.EndTime, returnedSchedule.EndTime);

// Verify that the schedule was actually saved to the database
var savedSchedules = await context.Schedules.CountAsync();
Assert.Equal(1, savedSchedules);
}
}
}
196 changes: 196 additions & 0 deletions LineUp.Backend.Tests/SwapTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
using System.Net;
using System.Security.Claims;
using Azure;
using LineUp.Backend.Controllers;
using LineUp.Backend.Models;
using LineUp.Core.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Moq;

namespace LineUp.Backend.Tests;

public class SwapTests
{
Schedule sampleSchedule = new Schedule
{
Guid = Guid.Empty,
Auth0UserId = "always-test-on-schedule",
DateCoverage =
[
DateOnly.FromDateTime(DateTime.UtcNow),
DateOnly.FromDateTime(DateTime.UtcNow.AddDays(1)),
DateOnly.FromDateTime(DateTime.UtcNow.AddDays(2)),
],
StartTime = new TimeOnly(9, 0),
EndTime = new TimeOnly(12, 0),
SchedulePreferences = new SchedulePreferences
{
MinutesPerSlot = 30,
ShiftIntervals = 30,
UsersPerShift = 1,
MaximumShiftDurationMinutes = 120,
MaximumShiftsPerWorker = 1,
},
Name = "Test Schedule",
};

Availability sample1 = new Availability
{
UserName = "Test Availability",
UserEmail = "[email protected]",
AvailabilitySlots =
[
// Day 0: 9:00 - 12:00
DateTime.UtcNow.Date.AddHours(9),
DateTime.UtcNow.Date.AddHours(9).AddMinutes(30),
DateTime.UtcNow.Date.AddHours(10),
DateTime.UtcNow.Date.AddHours(10).AddMinutes(30),
DateTime.UtcNow.Date.AddHours(11),
DateTime.UtcNow.Date.AddHours(11).AddMinutes(30),
],
Schedule = new Schedule
{
Guid = Guid.Empty,
Auth0UserId = "replace this schedule",
DateCoverage = [],
StartTime = new TimeOnly(0, 0),
EndTime = new TimeOnly(0, 0),
SchedulePreferences = new SchedulePreferences
{
MinutesPerSlot = 30,
ShiftIntervals = 30,
UsersPerShift = 1,
MaximumShiftDurationMinutes = 120,
MaximumShiftsPerWorker = 1,
},
Name = "ReplaceThisScheduleWithSampleSchedule",
},
Preferences = new AvailabilityPreferences(),
};
Availability sample2 = new Availability
{
UserName = "Test Availability",
UserEmail = "[email protected]",
AvailabilitySlots =
[
// Day 1: 9:00 - 12:00
DateTime.UtcNow.Date.AddDays(1).AddHours(9),
DateTime.UtcNow.Date.AddDays(1).AddHours(9).AddMinutes(30),
DateTime.UtcNow.Date.AddDays(1).AddHours(10),
DateTime.UtcNow.Date.AddDays(1).AddHours(10).AddMinutes(30),
DateTime.UtcNow.Date.AddDays(1).AddHours(11),
DateTime.UtcNow.Date.AddDays(1).AddHours(11).AddMinutes(30),
],
Schedule = new Schedule
{
Guid = Guid.Empty,
Auth0UserId = "replace this schedule",
DateCoverage = [],
StartTime = new TimeOnly(0, 0),
EndTime = new TimeOnly(0, 0),
SchedulePreferences = new SchedulePreferences
{
MinutesPerSlot = 30,
ShiftIntervals = 30,
UsersPerShift = 1,
MaximumShiftDurationMinutes = 120,
MaximumShiftsPerWorker = 1,
},
Name = "ReplaceThisScheduleWithSampleSchedule",
},
Preferences = new AvailabilityPreferences(),
};
Availability sample3 = new Availability
{
UserName = "Test Availability",
UserEmail = "[email protected]",
AvailabilitySlots =
[
// Day 2: 9:00 - 12:00
DateTime.UtcNow.Date.AddDays(2).AddHours(9),
DateTime.UtcNow.Date.AddDays(2).AddHours(9).AddMinutes(30),
DateTime.UtcNow.Date.AddDays(2).AddHours(10),
DateTime.UtcNow.Date.AddDays(2).AddHours(10).AddMinutes(30),
DateTime.UtcNow.Date.AddDays(2).AddHours(11),
DateTime.UtcNow.Date.AddDays(2).AddHours(11).AddMinutes(30),
],
Schedule = new Schedule
{
Guid = Guid.Empty,
Auth0UserId = "replace this schedule",
DateCoverage = [],
StartTime = new TimeOnly(0, 0),
EndTime = new TimeOnly(0, 0),
SchedulePreferences = new SchedulePreferences
{
MinutesPerSlot = 30,
ShiftIntervals = 30,
UsersPerShift = 1,
MaximumShiftDurationMinutes = 120,
MaximumShiftsPerWorker = 1,
},
Name = "ReplaceThisScheduleWithSampleSchedule",
},
Preferences = new AvailabilityPreferences(),
};

//[Fact]
public async Task SwapAccepted_Test()
{
// Arrange
var options = new DbContextOptionsBuilder<LineUpContext>()
.UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
.Options;

using (var context = new LineUpContext(options))
{
context.Database.EnsureCreated();

var controller = new ScheduleController(context);

Check failure on line 151 in LineUp.Backend.Tests/SwapTests.cs

View workflow job for this annotation

GitHub Actions / build

There is no argument given that corresponds to the required parameter 'emailService' of 'ScheduleController.ScheduleController(LineUpContext, IEmailService)'

Check failure on line 151 in LineUp.Backend.Tests/SwapTests.cs

View workflow job for this annotation

GitHub Actions / build

There is no argument given that corresponds to the required parameter 'emailService' of 'ScheduleController.ScheduleController(LineUpContext, IEmailService)'

// Create a mock ClaimsPrincipal with the required NameIdentifier claim
var claims = new List<Claim> { new Claim(ClaimTypes.NameIdentifier, "test-user-123") };
var identity = new ClaimsIdentity(claims);
var principal = new ClaimsPrincipal(identity);
controller.ControllerContext = new ControllerContext
{
HttpContext = new DefaultHttpContext { User = principal },
};

var scheduleDto = new ScheduleDto
{
DateCoverage = sampleSchedule.DateCoverage,
StartTime = sampleSchedule.StartTime,
EndTime = sampleSchedule.EndTime,
SchedulePreferences = sampleSchedule.SchedulePreferences,
Name = sampleSchedule.Name,
};
var result = await controller.CreateSchedule(scheduleDto);
CreatedAtActionResult scheduleCreatedResult = Assert.IsType<CreatedAtActionResult>(
result
);
Schedule returnedSchedule = Assert.IsType<Schedule>(scheduleCreatedResult.Value);
Guid guid = returnedSchedule.Guid;

var availability1Dto = new AvailabilityCreateDto
{
AvailabilitySlots = sample1.AvailabilitySlots,
UserName = sample1.UserName,
UserEmail = sample1.UserEmail,
Preferences = sample1.Preferences,
FormAnswers = sample1.FormAnswers,
};
var availabilityCreateResult = await controller.CreateAvailability(
guid,
availability1Dto
);

// Act

// Assert
Assert.IsType<CreatedAtActionResult>(availabilityCreateResult);
}
}
}
83 changes: 83 additions & 0 deletions LineUp.Backend/Controllers/ScheduleController.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
using System.Diagnostics;
using System.Security.Claims;
using LineUp.Backend.Models;
using LineUp.Backend.Services;
using LineUp.Core.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using NuGet.Protocol;
using SQLitePCL;

namespace LineUp.Backend.Controllers;

Expand Down Expand Up @@ -279,7 +282,7 @@
Schedule = schedule,
AvailabilitySlots = availability.AvailabilitySlots,
UserName = availability.UserName,
UserEmail = availability.UserEmail,

Check warning on line 285 in LineUp.Backend/Controllers/ScheduleController.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference assignment.
Preferences = availability.Preferences,
FormAnswers = availability.FormAnswers,
};
Expand All @@ -296,4 +299,84 @@
availabilityToInsert
);
}

[HttpGet("{guid:guid}/getByEmail")]
public async Task<IActionResult> GetAvailability(Guid guid, [FromQuery] string email)
{
var result = await context
.Availabilities.Include(a => a.Schedule)
.FirstOrDefaultAsync(a => a.UserEmail == email && a.Schedule.Guid == guid);
if (result != null)
return Ok(result);
return StatusCode(StatusCodes.Status406NotAcceptable);
}

[HttpPost("{guid:guid}/requestSwap")]
public async Task<IActionResult> RequestSwap(Guid guid, [FromBody] SwapRequestDto request)
{
DateTime[] shiftStartTimes = request.shiftStartTimes;
int requesterId = request.RequesterId;
int recipientId = request.RecipientId;

Schedule? schedule = context.Schedules.FirstOrDefault<Schedule>(s => s.Guid == guid);
if (schedule == null || shiftStartTimes == null || !shiftStartTimes.Any())
{
return BadRequest("Request does not specify all necessary fields.");
}
List<ShiftAssignment> requesterShiftCollection = new List<ShiftAssignment>();
List<ShiftAssignment> recipientShiftCollection = new List<ShiftAssignment>();
var scheduleResult = await context.Schedules.FirstOrDefaultAsync(s => s.Guid == guid);

if (scheduleResult == null)
return NotFound("The provided schedule could not be found.");
int scheduleID = scheduleResult.Id;

try
{ //Attempt to find the shift assignments from the backend.
foreach (DateTime start in shiftStartTimes)
{
var result = await context.ShiftAssignments.FirstOrDefaultAsync(s =>
s.ScheduleId == scheduleID
&& s.StartTime == start
&& s.Availability.Id == requesterId

Check warning on line 341 in LineUp.Backend/Controllers/ScheduleController.cs

View workflow job for this annotation

GitHub Actions / build

Dereference of a possibly null reference.
); //Attempt to find if the given shift belongs to requester
if (result != null)
requesterShiftCollection.Add(result);
else
{
result = await context.ShiftAssignments.FirstOrDefaultAsync(s =>
s.ScheduleId == scheduleID
&& s.StartTime == start
&& s.Availability.Id == recipientId

Check warning on line 350 in LineUp.Backend/Controllers/ScheduleController.cs

View workflow job for this annotation

GitHub Actions / build

Dereference of a possibly null reference.
); //Attempt to find if the given shift belongs to recipient
if (result != null)
requesterShiftCollection.Add(result);
else
{ //If it doesn't belong to either, throw an exception
throw new FileNotFoundException();
}
}
}
}
catch (FileNotFoundException e)

Check warning on line 361 in LineUp.Backend/Controllers/ScheduleController.cs

View workflow job for this annotation

GitHub Actions / build

The variable 'e' is declared but never used
{
return UnprocessableEntity(
"One or more of the dates provided did not have a shift assigned to either party."
);
}
if (requesterShiftCollection.Count < 1 && recipientShiftCollection.Count < 1)
return UnprocessableEntity("No shift assignments were found for the time specified.");

//Sort through the shifts (assume an unsorted list)
SwapRequest swapRequest = new SwapRequest
{
FromPartyA = requesterShiftCollection,
FromPartyB = recipientShiftCollection,
Schedule = schedule,
};
Console.WriteLine("\n Creating Swap Request: " + swapRequest.ToJson());
context.SwapRequests.Add(swapRequest);
context.SaveChanges();
return Ok(swapRequest.Guid);
}
}
Loading
Loading