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
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
using System.Net;
using System.Net.Http.Json;
using System.Text.Json;
using CourseRegistration.Application.DTOs;
using FluentAssertions;
using Microsoft.AspNetCore.Mvc.Testing;
using Xunit;

namespace CourseRegistration.API.Tests.Controllers;

/// <summary>
/// Integration tests for CoursesController focusing on CreateCourse endpoint
/// </summary>
public class CoursesControllerIntegrationTests : IClassFixture<WebApplicationFactory<Program>>
{
private readonly WebApplicationFactory<Program> _factory;
private readonly HttpClient _client;

public CoursesControllerIntegrationTests(WebApplicationFactory<Program> factory)
{
_factory = factory;
_client = factory.CreateClient();
}

[Fact]
public async Task CreateCourse_WithValidData_ShouldReturn201Created()
{
// Arrange
var createCourseDto = new CreateCourseDto
{
CourseName = "Integration Test Course",
Description = "This is a test course created during integration testing",
InstructorName = "Dr. Test",
StartDate = DateTime.UtcNow.AddDays(30),
EndDate = DateTime.UtcNow.AddDays(60),
Schedule = "MWF 10:00-11:30"
};

// Act
var response = await _client.PostAsJsonAsync("/api/courses", createCourseDto);

// Assert
response.StatusCode.Should().Be(HttpStatusCode.Created);

var content = await response.Content.ReadAsStringAsync();
content.Should().NotBeNullOrEmpty();

var apiResponse = JsonSerializer.Deserialize<JsonElement>(content);
apiResponse.GetProperty("success").GetBoolean().Should().BeTrue();
apiResponse.GetProperty("data").GetProperty("courseName").GetString().Should().Be(createCourseDto.CourseName);
}

[Fact]
public async Task CreateCourse_WithStartDateInPast_ShouldReturn400BadRequest()
{
// Arrange
var createCourseDto = new CreateCourseDto
{
CourseName = "Invalid Course",
Description = "Course with past start date",
InstructorName = "Dr. Test",
StartDate = DateTime.UtcNow.AddDays(-5),
EndDate = DateTime.UtcNow.AddDays(30),
Schedule = "MWF 10:00-11:30"
};

// Act
var response = await _client.PostAsJsonAsync("/api/courses", createCourseDto);

// Assert
response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
}

[Fact]
public async Task CreateCourse_WithEndDateBeforeStartDate_ShouldReturn400BadRequest()
{
// Arrange
var createCourseDto = new CreateCourseDto
{
CourseName = "Invalid Course",
Description = "Course with end date before start date",
InstructorName = "Dr. Test",
StartDate = DateTime.UtcNow.AddDays(60),
EndDate = DateTime.UtcNow.AddDays(30),
Schedule = "MWF 10:00-11:30"
};

// Act
var response = await _client.PostAsJsonAsync("/api/courses", createCourseDto);

// Assert
response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
}

[Fact]
public async Task CreateCourse_ShouldReturnLocationHeader()
{
// Arrange
var createCourseDto = new CreateCourseDto
{
CourseName = "Location Header Test Course",
Description = "Testing location header",
InstructorName = "Dr. Location",
StartDate = DateTime.UtcNow.AddDays(30),
EndDate = DateTime.UtcNow.AddDays(60),
Schedule = "MWF 09:00-10:30"
};

// Act
var response = await _client.PostAsJsonAsync("/api/courses", createCourseDto);

// Assert
response.StatusCode.Should().Be(HttpStatusCode.Created);
response.Headers.Location.Should().NotBeNull();
response.Headers.Location!.ToString().Should().Contain("/api/Courses/");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.4" />
<PackageReference Include="FluentAssertions" Version="8.8.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.4" />
</ItemGroup>

<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\CourseRegistration.API\CourseRegistration.API.csproj" />
<ProjectReference Include="..\CourseRegistration.Application\CourseRegistration.Application.csproj" />
<ProjectReference Include="..\CourseRegistration.Domain\CourseRegistration.Domain.csproj" />
</ItemGroup>

</Project>
3 changes: 3 additions & 0 deletions api/CourseRegistration.API/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -299,3 +299,6 @@ static async Task SeedDatabase(CourseRegistrationDbContext context)
Log.Information("Database seeded successfully with {StudentCount} students, {CourseCount} courses, and {RegistrationCount} registrations.",
students.Length, courses.Length, registrations.Length);
}

// Make Program accessible for integration tests
public partial class Program { }
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="AutoMapper" Version="15.1.0" />
<PackageReference Include="coverlet.collector" Version="6.0.4" />
<PackageReference Include="FluentAssertions" Version="8.8.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.4" />
</ItemGroup>

<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\CourseRegistration.Application\CourseRegistration.Application.csproj" />
<ProjectReference Include="..\CourseRegistration.Domain\CourseRegistration.Domain.csproj" />
</ItemGroup>

</Project>
Loading