feat: initial project setup

- Add .NET 8 backend with Clean Architecture
- Add React + Vite + TypeScript frontend
- Implement authentication with JWT
- Implement Azure Blob Storage client
- Implement OCR integration
- Implement supplier matching service
- Implement voucher generation
- Implement Fortnox provider
- Add unit and integration tests
- Add Docker Compose configuration
This commit is contained in:
Invoice Master
2026-02-04 20:14:34 +01:00
commit 05ea67144f
250 changed files with 50402 additions and 0 deletions

View File

@@ -0,0 +1,94 @@
using InvoiceMaster.IntegrationTests.Factories;
using System.Net;
using System.Net.Http.Json;
using System.Text.Json;
using Xunit;
using FluentAssertions;
namespace InvoiceMaster.IntegrationTests.Controllers;
public class AuthControllerTests : IClassFixture<CustomWebApplicationFactory>
{
private readonly CustomWebApplicationFactory _factory;
private readonly HttpClient _client;
public AuthControllerTests(CustomWebApplicationFactory factory)
{
_factory = factory;
_client = factory.CreateClient();
}
[Fact]
public async Task Register_WithValidData_ShouldReturnSuccess()
{
var request = new
{
email = $"test{Guid.NewGuid()}@example.com",
password = "Password123!",
fullName = "Test User"
};
var response = await _client.PostAsJsonAsync("/api/v1/auth/register", request);
var content = await response.Content.ReadAsStringAsync();
response.StatusCode.Should().Be(HttpStatusCode.OK);
content.Should().Contain("success\"");
content.Should().Contain("accessToken\"");
}
[Fact]
public async Task Register_WithInvalidEmail_ShouldReturnBadRequest()
{
var request = new
{
email = "invalid-email",
password = "Password123!"
};
var response = await _client.PostAsJsonAsync("/api/v1/auth/register", request);
response.StatusCode.Should().Be(HttpStatusCode.BadRequest);
}
[Fact]
public async Task Login_WithValidCredentials_ShouldReturnTokens()
{
var email = $"login{Guid.NewGuid()}@example.com";
var password = "Password123!";
var registerRequest = new { email, password, fullName = "Test User" };
await _client.PostAsJsonAsync("/api/v1/auth/register", registerRequest);
var loginRequest = new { email, password };
var response = await _client.PostAsJsonAsync("/api/v1/auth/login", loginRequest);
var content = await response.Content.ReadAsStringAsync();
response.StatusCode.Should().Be(HttpStatusCode.OK);
content.Should().Contain("accessToken\"");
content.Should().Contain("refreshToken\"");
}
[Fact]
public async Task Login_WithInvalidCredentials_ShouldReturnUnauthorized()
{
var request = new
{
email = "nonexistent@example.com",
password = "WrongPassword"
};
var response = await _client.PostAsJsonAsync("/api/v1/auth/login", request);
response.StatusCode.Should().Be(HttpStatusCode.Unauthorized);
}
[Fact]
public async Task HealthCheck_ShouldReturnHealthy()
{
var response = await _client.GetAsync("/api/v1/health");
var content = await response.Content.ReadAsStringAsync();
response.StatusCode.Should().Be(HttpStatusCode.OK);
content.Should().Contain("healthy");
}
}