KoogleApp/test
beo3000 0a9205a2f3 Complete phase G4: Membership Services
- UserService: RequestClubMembership (by ID, name, invite token),
  ApproveMembership, RejectMembership, GetPendingMemberships
- ClubService: CreateInvitation, GetInvitationByToken, ValidateInvitation,
  IncrementInvitationUsage, GetInvitationsByClub, GetByName
- Add PendingMembershipDto, ClubInvitationDto, CreateClubInvitationDto
- Update tests to pass AppDbContext to ClubService

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-25 18:27:40 +01:00
..
Koogle.Tests Complete phase G4: Membership Services 2025-12-25 18:27:40 +01:00
README.md added test-framework 2025-12-24 14:11:31 +01:00

README.md

Koogle Test Suite

Comprehensive testing infrastructure for the Koogle club management application.

Test Projects

Koogle.Tests

Main test project containing:

  • Unit Tests: Domain entities, services, Fluxor reducers
  • Integration Tests: API endpoints, database operations
  • Component Tests: bUnit tests for Blazor components
  • Performance Tests: Response time and memory allocation tests

Koogle.E2E

End-to-end tests using Playwright:

  • Authentication flow tests
  • User journey tests
  • UI interaction tests

Running Tests

All Tests

dotnet test test/Koogle.Tests

Specific Test Categories

# Unit tests only
dotnet test test/Koogle.Tests --filter "FullyQualifiedName~Unit"

# Integration tests only
dotnet test test/Koogle.Tests --filter "FullyQualifiedName~Integration"

# Component tests only
dotnet test test/Koogle.Tests --filter "FullyQualifiedName~Components"

# Performance tests only
dotnet test test/Koogle.Tests --filter "FullyQualifiedName~Performance"

E2E Tests

Before running E2E tests:

  1. Install Playwright browsers:
pwsh test/Koogle.E2E/bin/Debug/net9.0/playwright.ps1 install
  1. Start the application:
dotnet run --project src/Koogle.Web
  1. Run E2E tests:
E2E_BASE_URL=https://localhost:7001 dotnet test test/Koogle.E2E

Environment variables:

  • E2E_BASE_URL: Application URL (default: https://localhost:7001)
  • E2E_HEADLESS: Set to "false" to see browser (default: headless)
  • E2E_SLOWMO: Milliseconds to slow down operations for debugging

Test Coverage

dotnet test test/Koogle.Tests --collect:"XPlat Code Coverage"

Report location: test/Koogle.Tests/TestResults/*/coverage.cobertura.xml

Test Structure

test/
├── Koogle.Tests/
│   ├── Common/                    # Shared test utilities
│   │   ├── TestDataGenerator.cs   # Bogus-based test data
│   │   └── MockExtensions.cs      # Mock setup helpers
│   │
│   ├── Unit/
│   │   ├── Domain/               # Entity tests
│   │   ├── Services/             # Service unit tests
│   │   └── Store/                # Fluxor reducer tests
│   │
│   ├── Integration/              # API & DB integration tests
│   │
│   ├── Components/               # bUnit Blazor tests
│   │
│   └── Performance/              # Performance benchmarks
│
└── Koogle.E2E/
    ├── PageObjectModels/         # Page abstractions
    └── *Tests.cs                 # E2E test files

Test Patterns

AAA Pattern

All tests follow Arrange-Act-Assert:

[Fact]
public async Task GetByIdAsync_ReturnsClub_WhenExists()
{
    // Arrange
    var club = TestDataGenerator.CreateClub();
    _repositoryMock.SetupGetByIdAsync(club.Id, club);

    // Act
    var result = await _sut.GetByIdAsync(club.Id);

    // Assert
    result.Should().NotBeNull();
    result!.Id.Should().Be(club.Id);
}

Theory-Based Testing

For parameterized tests:

[Theory]
[InlineData(ExpenseCalculation.None)]
[InlineData(ExpenseCalculation.Average)]
[InlineData(ExpenseCalculation.Maximum)]
public async Task CreateAsync_HandlesAllExpenseCalculationTypes(ExpenseCalculation calc)
{
    // Test each enum value
}

State Immutability Testing

For Fluxor reducers:

[Fact]
public void Reducers_DoNotMutateOriginalState()
{
    var originalState = ClubState.Initial with { Clubs = [...] };
    var originalCount = originalState.Clubs.Count;

    ClubReducers.OnDeleteClubSuccess(originalState, action);

    originalState.Clubs.Should().HaveCount(originalCount);
}

Writing New Tests

1. Use TestDataGenerator

var club = TestDataGenerator.CreateClub(
    name: "My Club",
    expenseCalculation: ExpenseCalculation.Average);

2. Use MockExtensions

_repositoryMock
    .SetupGetAllAsync(clubs)
    .SetupAddAsync();

3. Use FluentAssertions

result.Should().NotBeNull();
result.Should().HaveCount(3);
result.Should().Contain(x => x.Name == "Club A");

Dependencies

Package Purpose
xUnit Test framework
FluentAssertions Readable assertions
Moq Mocking
bUnit Blazor component testing
Bogus Test data generation
AutoFixture Object creation
Microsoft.AspNetCore.Mvc.Testing Integration testing
Microsoft.Playwright E2E testing
Coverlet Code coverage
RichardSzalay.MockHttp MockHttp for HttpClient