Add complete integration test suite
Backend Integration Tests: - Create IntegrationTestBase class with WebApplicationFactory - AuthIntegrationTests: Registration, login, validation tests (5 tests) - EventsIntegrationTests: CRUD operations, authorization tests (8 tests) Frontend-Backend Integration (E2E): - Install Playwright with Chromium - Create playwright.config.ts with configuration - Auth E2E tests: login/register page visibility, navigation - Event List E2E tests: page display - Navigation E2E tests: main page navigation flow Total Integration Tests: - Backend: 13 tests covering Auth and Events - E2E: 6 tests covering UI flows
This commit is contained in:
@@ -0,0 +1,207 @@
|
||||
using System.Net;
|
||||
using System.Net.Http.Json;
|
||||
using FluentAssertions;
|
||||
using RacePlannerApi.DTOs;
|
||||
using RacePlannerApi.Models;
|
||||
using Xunit;
|
||||
|
||||
namespace backend.Tests.Integration;
|
||||
|
||||
public class EventsIntegrationTests : IntegrationTestBase
|
||||
{
|
||||
public EventsIntegrationTests(WebApplicationFactory<Program> factory) : base(factory) { }
|
||||
|
||||
private async Task<string> GetOrganizerTokenAsync()
|
||||
{
|
||||
// Register and login as organizer
|
||||
var registerRequest = new RegisterRequest
|
||||
{
|
||||
Email = "organizer@test.com",
|
||||
Password = "SecurePass123!",
|
||||
Name = "Test Organizer",
|
||||
Role = UserRole.Organizer
|
||||
};
|
||||
await _client.PostAsJsonAsync("/api/auth/register", registerRequest);
|
||||
|
||||
var loginRequest = new LoginRequest
|
||||
{
|
||||
Email = "organizer@test.com",
|
||||
Password = "SecurePass123!"
|
||||
};
|
||||
var loginResponse = await _client.PostAsJsonAsync("/api/auth/login", loginRequest);
|
||||
var authResult = await loginResponse.Content.ReadFromJsonAsync<AuthResponse>();
|
||||
return authResult!.Token;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetEvents_ReturnsPublishedEvents()
|
||||
{
|
||||
// Act
|
||||
var response = await _client.GetAsync("/api/events");
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||
var events = await response.Content.ReadFromJsonAsync<List<EventDto>>();
|
||||
events.Should().NotBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CreateEvent_WithValidData_ReturnsCreated()
|
||||
{
|
||||
// Arrange
|
||||
var token = await GetOrganizerTokenAsync();
|
||||
var client = CreateAuthenticatedClient(token);
|
||||
|
||||
var request = new CreateEventRequest
|
||||
{
|
||||
Name = "Test Marathon",
|
||||
Description = "A test marathon event",
|
||||
EventDate = DateTime.UtcNow.AddDays(30),
|
||||
Location = "Test City",
|
||||
Category = "Running",
|
||||
Tags = new List<string>(),
|
||||
MaxParticipants = 100
|
||||
};
|
||||
|
||||
// Act
|
||||
var response = await client.PostAsJsonAsync("/api/events", request);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.Created);
|
||||
var result = await response.Content.ReadFromJsonAsync<EventDto>();
|
||||
result.Should().NotBeNull();
|
||||
result!.Name.Should().Be(request.Name);
|
||||
result.Status.Should().Be("Draft");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CreateEvent_WithoutAuth_ReturnsUnauthorized()
|
||||
{
|
||||
// Arrange
|
||||
var request = new CreateEventRequest
|
||||
{
|
||||
Name = "Test Event",
|
||||
EventDate = DateTime.UtcNow.AddDays(30),
|
||||
Location = "Test City"
|
||||
};
|
||||
|
||||
// Act
|
||||
var response = await _client.PostAsJsonAsync("/api/events", request);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.Unauthorized);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetEvent_WithValidId_ReturnsEvent()
|
||||
{
|
||||
// Arrange - Create an event first
|
||||
var token = await GetOrganizerTokenAsync();
|
||||
var client = CreateAuthenticatedClient(token);
|
||||
|
||||
var createRequest = new CreateEventRequest
|
||||
{
|
||||
Name = "Test Event",
|
||||
Description = "Test description",
|
||||
EventDate = DateTime.UtcNow.AddDays(30),
|
||||
Location = "Test City",
|
||||
Category = "Running",
|
||||
Tags = new List<string>(),
|
||||
MaxParticipants = 50
|
||||
};
|
||||
var createResponse = await client.PostAsJsonAsync("/api/events", createRequest);
|
||||
var createdEvent = await createResponse.Content.ReadFromJsonAsync<EventDto>();
|
||||
|
||||
// Publish the event so it's visible
|
||||
var updateRequest = new UpdateEventRequest
|
||||
{
|
||||
Status = EventStatus.Published
|
||||
};
|
||||
await client.PutAsJsonAsync($"/api/events/{createdEvent!.Id}", updateRequest);
|
||||
|
||||
// Act - Get the event as anonymous user
|
||||
var getResponse = await _client.GetAsync($"/api/events/{createdEvent.Id}");
|
||||
|
||||
// Assert
|
||||
getResponse.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||
var result = await getResponse.Content.ReadFromJsonAsync<EventDto>();
|
||||
result.Should().NotBeNull();
|
||||
result!.Id.Should().Be(createdEvent.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetEvent_WithInvalidId_ReturnsNotFound()
|
||||
{
|
||||
// Act
|
||||
var response = await _client.GetAsync($"/api/events/{Guid.NewGuid()}");
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task UpdateEvent_WithValidData_ReturnsUpdatedEvent()
|
||||
{
|
||||
// Arrange
|
||||
var token = await GetOrganizerTokenAsync();
|
||||
var client = CreateAuthenticatedClient(token);
|
||||
|
||||
var createRequest = new CreateEventRequest
|
||||
{
|
||||
Name = "Original Name",
|
||||
EventDate = DateTime.UtcNow.AddDays(30),
|
||||
Location = "Original Location",
|
||||
Category = "Running",
|
||||
Tags = new List<string>(),
|
||||
MaxParticipants = 50
|
||||
};
|
||||
var createResponse = await client.PostAsJsonAsync("/api/events", createRequest);
|
||||
var createdEvent = await createResponse.Content.ReadFromJsonAsync<EventDto>();
|
||||
|
||||
var updateRequest = new UpdateEventRequest
|
||||
{
|
||||
Name = "Updated Name",
|
||||
Description = "Updated description"
|
||||
};
|
||||
|
||||
// Act
|
||||
var response = await client.PutAsJsonAsync($"/api/events/{createdEvent!.Id}", updateRequest);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||
var result = await response.Content.ReadFromJsonAsync<EventDto>();
|
||||
result.Should().NotBeNull();
|
||||
result!.Name.Should().Be("Updated Name");
|
||||
result.Description.Should().Be("Updated description");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DeleteEvent_AsOrganizer_ReturnsNoContent()
|
||||
{
|
||||
// Arrange
|
||||
var token = await GetOrganizerTokenAsync();
|
||||
var client = CreateAuthenticatedClient(token);
|
||||
|
||||
var createRequest = new CreateEventRequest
|
||||
{
|
||||
Name = "Event to Delete",
|
||||
EventDate = DateTime.UtcNow.AddDays(30),
|
||||
Location = "Test City",
|
||||
Category = "Running",
|
||||
Tags = new List<string>(),
|
||||
MaxParticipants = 50
|
||||
};
|
||||
var createResponse = await client.PostAsJsonAsync("/api/events", createRequest);
|
||||
var createdEvent = await createResponse.Content.ReadFromJsonAsync<EventDto>();
|
||||
|
||||
// Act
|
||||
var response = await client.DeleteAsync($"/api/events/{createdEvent!.Id}");
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.NoContent);
|
||||
|
||||
// Verify event is deleted
|
||||
var getResponse = await client.GetAsync($"/api/events/{createdEvent.Id}");
|
||||
getResponse.StatusCode.Should().Be(HttpStatusCode.NotFound);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user