Files
raceplanner/backend/backend.Tests/Controllers/RegistrationsControllerTests.cs
T

478 lines
17 KiB
C#
Raw Normal View History

using System.Security.Claims;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Moq;
using FluentAssertions;
using RacePlannerApi.Controllers;
using RacePlannerApi.Data;
using RacePlannerApi.DTOs;
using RacePlannerApi.Models;
using backend.Tests.Utilities;
namespace backend.Tests.Controllers;
public class RegistrationsControllerTests : IDisposable
{
private readonly RacePlannerDbContext _context;
private readonly RegistrationsController _controller;
public RegistrationsControllerTests()
{
var options = new DbContextOptionsBuilder<RacePlannerDbContext>()
.UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
.Options;
_context = new RacePlannerDbContext(options);
_controller = new RegistrationsController(_context);
}
private void SetUserContext(Guid userId, string role = "Participant")
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.NameIdentifier, userId.ToString()),
new Claim(ClaimTypes.Role, role)
};
var identity = new ClaimsIdentity(claims, "TestAuthType");
var principal = new ClaimsPrincipal(identity);
_controller.ControllerContext = new ControllerContext
{
HttpContext = new DefaultHttpContext { User = principal }
};
}
public void Dispose()
{
_context.Dispose();
}
#region Create Registration - Positive Tests
[Fact]
public async Task CreateRegistration_WithValidData_CreatesRegistration()
{
// Arrange
var organizer = TestDataFactory.CreateUser(role: UserRole.Organizer);
var participant = TestDataFactory.CreateUser(email: "participant@example.com", role: UserRole.Participant);
_context.Users.AddRange(organizer, participant);
var eventEntity = TestDataFactory.CreateEvent(organizerId: organizer.Id, status: EventStatus.Published);
_context.Events.Add(eventEntity);
await _context.SaveChangesAsync();
SetUserContext(participant.Id, "Participant");
var request = new CreateRegistrationRequest
{
EventId = eventEntity.Id,
Category = "Open",
EmergencyContact = "Emergency Contact: 123-456-7890"
};
// Act
var result = await _controller.CreateRegistration(request);
// Assert
var createdResult = result.Result.Should().BeOfType<CreatedAtActionResult>().Subject;
var response = createdResult.Value.Should().BeOfType<RegistrationDto>().Subject;
response.EventId.Should().Be(eventEntity.Id);
response.ParticipantId.Should().Be(participant.Id);
response.Status.Should().Be("Pending");
}
[Fact]
public async Task CreateRegistration_SetsStatusToPending()
{
// Arrange
var organizer = TestDataFactory.CreateUser(role: UserRole.Organizer);
var participant = TestDataFactory.CreateUser(email: "participant2@example.com", role: UserRole.Participant);
_context.Users.AddRange(organizer, participant);
var eventEntity = TestDataFactory.CreateEvent(organizerId: organizer.Id, status: EventStatus.Published);
_context.Events.Add(eventEntity);
await _context.SaveChangesAsync();
SetUserContext(participant.Id, "Participant");
var request = new CreateRegistrationRequest
{
EventId = eventEntity.Id,
Category = "Open"
};
// Act
var result = await _controller.CreateRegistration(request);
// Assert
var createdResult = result.Result.Should().BeOfType<CreatedAtActionResult>().Subject;
var response = createdResult.Value.Should().BeOfType<RegistrationDto>().Subject;
response.Status.Should().Be("Pending");
}
#endregion
#region Create Registration - Negative Tests
[Fact]
public async Task CreateRegistration_ForDraftEvent_ReturnsBadRequest()
{
// Arrange
var organizer = TestDataFactory.CreateUser(role: UserRole.Organizer);
var participant = TestDataFactory.CreateUser(email: "participant3@example.com", role: UserRole.Participant);
_context.Users.AddRange(organizer, participant);
var draftEvent = TestDataFactory.CreateEvent(organizerId: organizer.Id, status: EventStatus.Draft);
_context.Events.Add(draftEvent);
await _context.SaveChangesAsync();
SetUserContext(participant.Id, "Participant");
var request = new CreateRegistrationRequest
{
EventId = draftEvent.Id,
Category = "Open"
};
// Act
var result = await _controller.CreateRegistration(request);
// Assert
var badRequestResult = result.Result.Should().BeOfType<BadRequestObjectResult>().Subject;
badRequestResult.Value.Should().BeEquivalentTo(new { error = "Event is not open for registration" });
}
[Fact]
public async Task CreateRegistration_DuplicateRegistration_ReturnsConflict()
{
// Arrange
var organizer = TestDataFactory.CreateUser(role: UserRole.Organizer);
var participant = TestDataFactory.CreateUser(email: "participant4@example.com", role: UserRole.Participant);
_context.Users.AddRange(organizer, participant);
var eventEntity = TestDataFactory.CreateEvent(organizerId: organizer.Id, status: EventStatus.Published);
_context.Events.Add(eventEntity);
// Create existing registration
var existingRegistration = TestDataFactory.CreateRegistration(eventEntity.Id, participant.Id);
_context.Registrations.Add(existingRegistration);
await _context.SaveChangesAsync();
SetUserContext(participant.Id, "Participant");
var request = new CreateRegistrationRequest
{
EventId = eventEntity.Id,
Category = "Open"
};
// Act
var result = await _controller.CreateRegistration(request);
// Assert
var conflictResult = result.Result.Should().BeOfType<ConflictObjectResult>().Subject;
conflictResult.Value.Should().BeEquivalentTo(new { error = "Already registered for this event" });
}
[Fact]
public async Task CreateRegistration_ForFullEvent_ReturnsBadRequest()
{
// Arrange
var organizer = TestDataFactory.CreateUser(role: UserRole.Organizer);
var participant1 = TestDataFactory.CreateUser(email: "participant1@example.com", role: UserRole.Participant);
var participant2 = TestDataFactory.CreateUser(email: "participant2@example.com", role: UserRole.Participant);
_context.Users.AddRange(organizer, participant1, participant2);
var eventEntity = TestDataFactory.CreateEvent(organizerId: organizer.Id, status: EventStatus.Published);
eventEntity.MaxParticipants = 1;
_context.Events.Add(eventEntity);
// Fill the event
var registration = TestDataFactory.CreateRegistration(eventEntity.Id, participant1.Id, RegistrationStatus.Confirmed);
_context.Registrations.Add(registration);
await _context.SaveChangesAsync();
SetUserContext(participant2.Id, "Participant");
var request = new CreateRegistrationRequest
{
EventId = eventEntity.Id,
Category = "Open"
};
// Act
var result = await _controller.CreateRegistration(request);
// Assert
var badRequestResult = result.Result.Should().BeOfType<BadRequestObjectResult>().Subject;
badRequestResult.Value.Should().BeEquivalentTo(new { error = "Event is full" });
}
[Fact]
public async Task CreateRegistration_ForNonExistentEvent_ReturnsNotFound()
{
// Arrange
var participant = TestDataFactory.CreateUser(role: UserRole.Participant);
_context.Users.Add(participant);
await _context.SaveChangesAsync();
SetUserContext(participant.Id, "Participant");
var request = new CreateRegistrationRequest
{
EventId = Guid.NewGuid(),
Category = "Open"
};
// Act
var result = await _controller.CreateRegistration(request);
// Assert
var notFoundResult = result.Result.Should().BeOfType<NotFoundObjectResult>().Subject;
notFoundResult.Value.Should().BeEquivalentTo(new { error = "Event not found" });
}
#endregion
#region Get Registration - Positive Tests
[Fact]
public async Task GetRegistration_ParticipantCanViewOwnRegistration()
{
// Arrange
var organizer = TestDataFactory.CreateUser(role: UserRole.Organizer);
var participant = TestDataFactory.CreateUser(email: "participant5@example.com", role: UserRole.Participant);
_context.Users.AddRange(organizer, participant);
var eventEntity = TestDataFactory.CreateEvent(organizerId: organizer.Id, status: EventStatus.Published);
_context.Events.Add(eventEntity);
var registration = TestDataFactory.CreateRegistration(eventEntity.Id, participant.Id);
_context.Registrations.Add(registration);
await _context.SaveChangesAsync();
SetUserContext(participant.Id, "Participant");
// Act
var result = await _controller.GetRegistration(registration.Id);
// Assert
result.Result.Should().BeOfType<OkObjectResult>();
}
[Fact]
public async Task GetRegistration_OrganizerCanViewAnyRegistrationForTheirEvent()
{
// Arrange
var organizer = TestDataFactory.CreateUser(role: UserRole.Organizer);
var participant = TestDataFactory.CreateUser(email: "participant6@example.com", role: UserRole.Participant);
_context.Users.AddRange(organizer, participant);
var eventEntity = TestDataFactory.CreateEvent(organizerId: organizer.Id, status: EventStatus.Published);
_context.Events.Add(eventEntity);
var registration = TestDataFactory.CreateRegistration(eventEntity.Id, participant.Id);
_context.Registrations.Add(registration);
await _context.SaveChangesAsync();
SetUserContext(organizer.Id, "Organizer");
// Act
var result = await _controller.GetRegistration(registration.Id);
// Assert
result.Result.Should().BeOfType<OkObjectResult>();
}
[Fact]
public async Task GetMyRegistrations_ReturnsParticipantsRegistrations()
{
// Arrange
var organizer = TestDataFactory.CreateUser(role: UserRole.Organizer);
var participant = TestDataFactory.CreateUser(email: "participant7@example.com", role: UserRole.Participant);
_context.Users.AddRange(organizer, participant);
var event1 = TestDataFactory.CreateEvent(organizerId: organizer.Id, status: EventStatus.Published);
var event2 = TestDataFactory.CreateEvent(name: "Event 2", organizerId: organizer.Id, status: EventStatus.Published);
_context.Events.AddRange(event1, event2);
var registration1 = TestDataFactory.CreateRegistration(event1.Id, participant.Id);
var registration2 = TestDataFactory.CreateRegistration(event2.Id, participant.Id);
_context.Registrations.AddRange(registration1, registration2);
await _context.SaveChangesAsync();
SetUserContext(participant.Id, "Participant");
// Act
var result = await _controller.GetMyRegistrations();
// Assert
var okResult = result.Result.Should().BeOfType<OkObjectResult>().Subject;
var registrations = okResult.Value.Should().BeAssignableTo<IEnumerable<RegistrationDto>>().Subject;
registrations.Should().HaveCount(2);
}
#endregion
#region Get Registration - Negative Tests
[Fact]
public async Task GetRegistration_NonExistentRegistration_ReturnsNotFound()
{
// Arrange
var participant = TestDataFactory.CreateUser(role: UserRole.Participant);
_context.Users.Add(participant);
await _context.SaveChangesAsync();
SetUserContext(participant.Id, "Participant");
// Act
var result = await _controller.GetRegistration(Guid.NewGuid());
// Assert
result.Result.Should().BeOfType<NotFoundResult>();
}
#endregion
#region Cancel Registration - Positive Tests
[Fact]
public async Task CancelRegistration_ParticipantCanCancelOwnRegistration()
{
// Arrange
var organizer = TestDataFactory.CreateUser(role: UserRole.Organizer);
var participant = TestDataFactory.CreateUser(email: "participant8@example.com", role: UserRole.Participant);
_context.Users.AddRange(organizer, participant);
var eventEntity = TestDataFactory.CreateEvent(organizerId: organizer.Id, status: EventStatus.Published);
_context.Events.Add(eventEntity);
var registration = TestDataFactory.CreateRegistration(eventEntity.Id, participant.Id, RegistrationStatus.Pending);
_context.Registrations.Add(registration);
await _context.SaveChangesAsync();
SetUserContext(participant.Id, "Participant");
// Act
var result = await _controller.CancelRegistration(registration.Id);
// Assert
var okResult = result.Result.Should().BeOfType<OkObjectResult>().Subject;
var response = okResult.Value.Should().BeOfType<RegistrationDto>().Subject;
response.Status.Should().Be("Cancelled");
// Verify in database
var updatedRegistration = await _context.Registrations.FindAsync(registration.Id);
updatedRegistration!.Status.Should().Be(RegistrationStatus.Cancelled);
}
[Fact]
public async Task CancelRegistration_OrganizerCanCancelAnyRegistration()
{
// Arrange
var organizer = TestDataFactory.CreateUser(role: UserRole.Organizer);
var participant = TestDataFactory.CreateUser(email: "participant9@example.com", role: UserRole.Participant);
_context.Users.AddRange(organizer, participant);
var eventEntity = TestDataFactory.CreateEvent(organizerId: organizer.Id, status: EventStatus.Published);
_context.Events.Add(eventEntity);
var registration = TestDataFactory.CreateRegistration(eventEntity.Id, participant.Id, RegistrationStatus.Pending);
_context.Registrations.Add(registration);
await _context.SaveChangesAsync();
SetUserContext(organizer.Id, "Organizer");
// Act
var result = await _controller.CancelRegistration(registration.Id);
// Assert
var okResult = result.Result.Should().BeOfType<OkObjectResult>().Subject;
var response = okResult.Value.Should().BeOfType<RegistrationDto>().Subject;
response.Status.Should().Be("Cancelled");
}
#endregion
#region Cancel Registration - Negative Tests
[Fact]
public async Task CancelRegistration_NonExistentRegistration_ReturnsNotFound()
{
// Arrange
var participant = TestDataFactory.CreateUser(role: UserRole.Participant);
_context.Users.Add(participant);
await _context.SaveChangesAsync();
SetUserContext(participant.Id, "Participant");
// Act
var result = await _controller.CancelRegistration(Guid.NewGuid());
// Assert
result.Result.Should().BeOfType<NotFoundResult>();
}
#endregion
#region Update Registration - Positive Tests
[Fact]
public async Task UpdateRegistration_ParticipantCanUpdateOwnRegistration()
{
// Arrange
var organizer = TestDataFactory.CreateUser(role: UserRole.Organizer);
var participant = TestDataFactory.CreateUser(email: "participant10@example.com", role: UserRole.Participant);
_context.Users.AddRange(organizer, participant);
var eventEntity = TestDataFactory.CreateEvent(organizerId: organizer.Id, status: EventStatus.Published);
_context.Events.Add(eventEntity);
var registration = TestDataFactory.CreateRegistration(eventEntity.Id, participant.Id);
_context.Registrations.Add(registration);
await _context.SaveChangesAsync();
SetUserContext(participant.Id, "Participant");
var request = new UpdateRegistrationRequest
{
Category = "Updated Category",
EmergencyContact = "Updated Emergency Contact"
};
// Act
var result = await _controller.UpdateRegistration(registration.Id, request);
// Assert
var okResult = result.Result.Should().BeOfType<OkObjectResult>().Subject;
var response = okResult.Value.Should().BeOfType<RegistrationDto>().Subject;
response.Category.Should().Be("Updated Category");
}
#endregion
#region Update Registration - Negative Tests
[Fact]
public async Task UpdateRegistration_NonExistentRegistration_ReturnsNotFound()
{
// Arrange
var participant = TestDataFactory.CreateUser(role: UserRole.Participant);
_context.Users.Add(participant);
await _context.SaveChangesAsync();
SetUserContext(participant.Id, "Participant");
var request = new UpdateRegistrationRequest { Category = "Updated" };
// Act
var result = await _controller.UpdateRegistration(Guid.NewGuid(), request);
// Assert
result.Result.Should().BeOfType<NotFoundResult>();
}
#endregion
}