Initial import
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
using FluentAssertions;
|
||||
using MinAttest.Application.Features.Attests.Commands;
|
||||
using MinAttest.Application.Features.Employers.Commands;
|
||||
using MinAttest.Application.Features.Persons.Commands;
|
||||
using MinAttest.Contracts.Attests;
|
||||
using Xunit;
|
||||
|
||||
namespace MinAttest.Tests.Domain;
|
||||
|
||||
public class ValidationTests
|
||||
{
|
||||
[Fact]
|
||||
public void UpsertPersonCommand_invalid_when_missing_hash()
|
||||
{
|
||||
var v = new UpsertPersonCommandValidator();
|
||||
var r = v.Validate(new UpsertPersonCommand("", null, null));
|
||||
r.IsValid.Should().BeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void UpsertEmployerCommand_invalid_when_missing_fields()
|
||||
{
|
||||
var v = new UpsertEmployerCommandValidator();
|
||||
var r = v.Validate(new UpsertEmployerCommand("", ""));
|
||||
r.IsValid.Should().BeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PersonUploadAttestCommand_requires_title_and_dates()
|
||||
{
|
||||
var v = new PersonUploadAttestCommandValidator();
|
||||
var cmd = new PersonUploadAttestCommand(Guid.NewGuid(), new PersonAttestUploadRequest(
|
||||
Title: "",
|
||||
From: new DateOnly(2024,12,31),
|
||||
To: new DateOnly(2024,1,1),
|
||||
Summary: null,
|
||||
BlobPath: "",
|
||||
BlobHash: null,
|
||||
ContentBase64: null,
|
||||
ContentType: null));
|
||||
var r = v.Validate(cmd);
|
||||
r.IsValid.Should().BeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void EmployerIssueAttestCommand_requires_person_title_and_dates()
|
||||
{
|
||||
var v = new EmployerIssueAttestCommandValidator();
|
||||
var cmd = new EmployerIssueAttestCommand(Guid.Empty, new EmployerAttestUploadRequest(
|
||||
PersonId: Guid.Empty,
|
||||
Title: "",
|
||||
From: new DateOnly(2024,12,31),
|
||||
To: new DateOnly(2024,1,1),
|
||||
Summary: null,
|
||||
BlobPath: "",
|
||||
BlobHash: null,
|
||||
ContentBase64: null,
|
||||
ContentType: null));
|
||||
var r = v.Validate(cmd);
|
||||
r.IsValid.Should().BeFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
using System.Net;
|
||||
using System.Net.Http.Json;
|
||||
using FluentAssertions;
|
||||
using MinAttest.Contracts.Attests;
|
||||
using MinAttest.Contracts.Employers;
|
||||
using MinAttest.Contracts.Persons;
|
||||
using MinAttest.Tests.Integration.Server;
|
||||
using Xunit;
|
||||
|
||||
namespace MinAttest.Tests.Integration.Api;
|
||||
|
||||
[Collection("IntegrationCollection")]
|
||||
public class EmployersApiTests : IClassFixture<ApiWebAppFactory>
|
||||
{
|
||||
private readonly HttpClient _client;
|
||||
public EmployersApiTests(ApiWebAppFactory factory) => _client = factory.CreateClient();
|
||||
|
||||
[Fact]
|
||||
public async Task Employer_issue_and_list_and_download_via_http()
|
||||
{
|
||||
// Upsert employer
|
||||
var employerUpsert = new EmployerUpsertRequest("321654987", "ApiCo AS");
|
||||
var employerResp = await _client.PostAsJsonAsync("/api/v1/employers", employerUpsert);
|
||||
employerResp.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||
var employer = await employerResp.Content.ReadFromJsonAsync<EmployerResponse>();
|
||||
employer.Should().NotBeNull();
|
||||
|
||||
// Upsert person
|
||||
var personResp = await _client.PostAsJsonAsync("/api/v1/persons", new PersonUpsertRequest("hash-api-emp-1", "emp-person@example.com", null));
|
||||
personResp.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||
var person = await personResp.Content.ReadFromJsonAsync<PersonResponse>();
|
||||
person.Should().NotBeNull();
|
||||
|
||||
// Issue attest for person
|
||||
var issueReq = new EmployerAttestUploadRequest(
|
||||
PersonId: person!.Id,
|
||||
Title: "ApiEmployerAttest",
|
||||
From: new DateOnly(2024,1,1),
|
||||
To: new DateOnly(2024,6,1),
|
||||
Summary: null,
|
||||
BlobPath: string.Empty,
|
||||
BlobHash: null,
|
||||
ContentBase64: Convert.ToBase64String(new byte[]{7,8,9}),
|
||||
ContentType: "application/octet-stream");
|
||||
|
||||
var issueResp = await _client.PostAsJsonAsync($"/api/v1/employers/{employer!.Id}/attests", issueReq);
|
||||
issueResp.StatusCode.Should().Be(HttpStatusCode.Created);
|
||||
var created = await issueResp.Content.ReadFromJsonAsync<Dictionary<string, object>>();
|
||||
created.Should().NotBeNull();
|
||||
var createdId = Guid.Parse(created!["attestId"].ToString()!);
|
||||
|
||||
// List employer attests
|
||||
var listResp = await _client.GetAsync($"/api/v1/employers/{employer.Id}/attests");
|
||||
listResp.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||
|
||||
// Download
|
||||
var dlResp = await _client.GetAsync($"/api/v1/employers/{employer.Id}/attests/{createdId}/download");
|
||||
dlResp.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||
(await dlResp.Content.ReadAsByteArrayAsync()).Length.Should().BeGreaterThan(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using System.Net;
|
||||
using System.Net.Http.Json;
|
||||
using FluentAssertions;
|
||||
using MinAttest.Contracts.Attests;
|
||||
using MinAttest.Contracts.Persons;
|
||||
using MinAttest.Tests.Integration.Server;
|
||||
using Xunit;
|
||||
|
||||
namespace MinAttest.Tests.Integration.Api;
|
||||
|
||||
[Collection("IntegrationCollection")]
|
||||
public class PersonsApiTests : IClassFixture<ApiWebAppFactory>
|
||||
{
|
||||
private readonly HttpClient _client;
|
||||
public PersonsApiTests(ApiWebAppFactory factory) => _client = factory.CreateClient();
|
||||
|
||||
[Fact]
|
||||
public async Task Upsert_person_and_upload_and_list()
|
||||
{
|
||||
var upsertResp = await _client.PostAsJsonAsync("/api/v1/persons", new PersonUpsertRequest("hash-api-1", "api@example.com", null));
|
||||
upsertResp.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||
var person = await upsertResp.Content.ReadFromJsonAsync<PersonResponse>();
|
||||
person.Should().NotBeNull();
|
||||
|
||||
var uploadReq = new PersonAttestUploadRequest(
|
||||
Title: "ApiAttest",
|
||||
From: new DateOnly(2024,1,1),
|
||||
To: new DateOnly(2024,6,1),
|
||||
Summary: "",
|
||||
BlobPath: "",
|
||||
BlobHash: null,
|
||||
ContentBase64: Convert.ToBase64String(new byte[]{1,2,3}),
|
||||
ContentType: "application/octet-stream");
|
||||
|
||||
var uploadResp = await _client.PostAsJsonAsync($"/api/v1/persons/{person!.Id}/attests", uploadReq);
|
||||
uploadResp.StatusCode.Should().Be(HttpStatusCode.Created);
|
||||
|
||||
var listResp = await _client.GetAsync($"/api/v1/persons/{person.Id}/attests");
|
||||
listResp.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
using System.Net;
|
||||
using System.Net.Http.Json;
|
||||
using FluentAssertions;
|
||||
using MinAttest.Contracts.Attests;
|
||||
using MinAttest.Contracts.Persons;
|
||||
using MinAttest.Contracts.ShareLinks;
|
||||
using MinAttest.Tests.Integration.Server;
|
||||
using Xunit;
|
||||
|
||||
namespace MinAttest.Tests.Integration.Api;
|
||||
|
||||
[Collection("IntegrationCollection")]
|
||||
public class ShareLinksApiTests : IClassFixture<ApiWebAppFactory>
|
||||
{
|
||||
private readonly HttpClient _client;
|
||||
public ShareLinksApiTests(ApiWebAppFactory factory) => _client = factory.CreateClient();
|
||||
|
||||
[Fact]
|
||||
public async Task Create_list_revoke_sharelink_via_http()
|
||||
{
|
||||
// Upsert person
|
||||
var personResp = await _client.PostAsJsonAsync("/api/v1/persons", new PersonUpsertRequest("hash-api-share-1", "share-person@example.com", null));
|
||||
personResp.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||
var person = await personResp.Content.ReadFromJsonAsync<PersonResponse>();
|
||||
|
||||
// Upload attest
|
||||
var upload = new PersonAttestUploadRequest(
|
||||
Title: "ShareAttest",
|
||||
From: new DateOnly(2024,1,1),
|
||||
To: new DateOnly(2024,6,1),
|
||||
Summary: null,
|
||||
BlobPath: string.Empty,
|
||||
BlobHash: null,
|
||||
ContentBase64: Convert.ToBase64String(new byte[]{1,2,3,4}),
|
||||
ContentType: "application/pdf");
|
||||
var upResp = await _client.PostAsJsonAsync($"/api/v1/persons/{person!.Id}/attests", upload);
|
||||
upResp.StatusCode.Should().Be(HttpStatusCode.Created);
|
||||
var created = await upResp.Content.ReadFromJsonAsync<Dictionary<string, object>>();
|
||||
var attestId = Guid.Parse(created!["attestId"].ToString()!);
|
||||
|
||||
// Create share link
|
||||
var createReq = new CreateShareLinkRequest(TimeSpan.FromDays(7), false);
|
||||
var slResp = await _client.PostAsJsonAsync($"/api/v1/attests/{attestId}/sharelinks", createReq);
|
||||
slResp.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||
var link = await slResp.Content.ReadFromJsonAsync<ShareLinkResponse>();
|
||||
link.Should().NotBeNull();
|
||||
|
||||
// List
|
||||
var listResp = await _client.GetAsync($"/api/v1/attests/{attestId}/sharelinks");
|
||||
listResp.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||
|
||||
// Revoke
|
||||
var delResp = await _client.DeleteAsync($"/api/v1/attests/{attestId}/sharelinks/{link!.ShareId}");
|
||||
delResp.StatusCode.Should().Be(HttpStatusCode.NoContent);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using FluentAssertions;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using MinAttest.Application.Features.Attests.Commands;
|
||||
using MinAttest.Application.Features.Attests.Queries;
|
||||
using MinAttest.Contracts.Attests;
|
||||
using Xunit;
|
||||
|
||||
namespace MinAttest.Tests.Integration;
|
||||
|
||||
[Collection("IntegrationCollection")]
|
||||
public class AttestsIntegrationTests
|
||||
{
|
||||
private readonly IntegrationTestFixture _fixture;
|
||||
|
||||
public AttestsIntegrationTests(IntegrationTestFixture fixture) => _fixture = fixture;
|
||||
|
||||
[Fact]
|
||||
public async Task Person_upload_and_list_attest_success()
|
||||
{
|
||||
var sp = _fixture.Services;
|
||||
var mediator = sp.GetRequiredService<IMediator>();
|
||||
|
||||
// Ensure person exists
|
||||
var upsert = await mediator.Send(new MinAttest.Application.Features.Persons.Commands.UpsertPersonCommand("person-hash-123", "person@example.com", null));
|
||||
var personId = upsert.Id;
|
||||
|
||||
var req = new PersonAttestUploadRequest(
|
||||
Title: "TestAttest",
|
||||
From: new DateOnly(2023,1,1),
|
||||
To: new DateOnly(2023,12,31),
|
||||
Summary: "Test summary",
|
||||
BlobPath: string.Empty,
|
||||
BlobHash: null,
|
||||
ContentBase64: Convert.ToBase64String(new byte[] {1,2,3}),
|
||||
ContentType: "application/octet-stream"
|
||||
);
|
||||
|
||||
var createdId = await mediator.Send(new PersonUploadAttestCommand(personId, req));
|
||||
createdId.Should().NotBeNull();
|
||||
|
||||
var list = await mediator.Send(new ListPersonAttestsQuery(personId, 10));
|
||||
list.Should().NotBeNull();
|
||||
list!.Any(a => a.Id == createdId).Should().BeTrue();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using FluentAssertions;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using MinAttest.Application.Features.Employers.Commands;
|
||||
using MinAttest.Application.Features.Employers.Queries;
|
||||
using Xunit;
|
||||
|
||||
namespace MinAttest.Tests.Integration;
|
||||
|
||||
[Collection("IntegrationCollection")]
|
||||
public class EmployerUsersIntegrationTests
|
||||
{
|
||||
private readonly IntegrationTestFixture _fixture;
|
||||
public EmployerUsersIntegrationTests(IntegrationTestFixture fixture) => _fixture = fixture;
|
||||
[Fact]
|
||||
public async Task Upsert_list_get_delete_employer_user()
|
||||
{
|
||||
var mediator = _fixture.Services.GetRequiredService<IMediator>();
|
||||
|
||||
// Ensure employer exists
|
||||
var employer = await mediator.Send(new UpsertEmployerCommand("999999999", "TestBedrift AS"));
|
||||
|
||||
// Upsert user
|
||||
var user = await mediator.Send(new UpsertEmployerUserCommand(
|
||||
employer.Id, "oid-123", "hr@example.com", "Hr User", "Issuer"));
|
||||
user.Should().NotBeNull();
|
||||
|
||||
// List
|
||||
var list = await mediator.Send(new ListEmployerUsersQuery(employer.Id));
|
||||
list.Should().Contain(u => u.ExternalObjectId == "oid-123");
|
||||
|
||||
// Get
|
||||
var got = await mediator.Send(new GetEmployerUserQuery(employer.Id, user!.Id));
|
||||
got.Should().NotBeNull();
|
||||
got!.Email.Should().Be("hr@example.com");
|
||||
|
||||
// Delete
|
||||
var deleted = await mediator.Send(new DeleteEmployerUserCommand(employer.Id, user.Id));
|
||||
deleted.Should().BeTrue();
|
||||
|
||||
// Delete again -> false or idempotent? we return false when not found
|
||||
var deletedAgain = await mediator.Send(new DeleteEmployerUserCommand(employer.Id, user.Id));
|
||||
deletedAgain.Should().BeFalse();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
using FluentAssertions;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using MinAttest.Application.Features.Attests.Commands;
|
||||
using MinAttest.Application.Features.Attests.Queries;
|
||||
using MinAttest.Application.Features.Employers.Commands;
|
||||
using MinAttest.Contracts.Attests;
|
||||
using Xunit;
|
||||
|
||||
namespace MinAttest.Tests.Integration;
|
||||
|
||||
[Collection("IntegrationCollection")]
|
||||
public class EmployersAttestsIntegrationTests
|
||||
{
|
||||
private readonly IntegrationTestFixture _fixture;
|
||||
public EmployersAttestsIntegrationTests(IntegrationTestFixture fixture) => _fixture = fixture;
|
||||
[Fact]
|
||||
public async Task Employer_issue_and_list_attests()
|
||||
{
|
||||
var mediator = _fixture.Services.GetRequiredService<IMediator>();
|
||||
|
||||
// Ensure employer & person
|
||||
var employer = await mediator.Send(new UpsertEmployerCommand("555555555", "NewCo AS"));
|
||||
var person = await mediator.Send(new MinAttest.Application.Features.Persons.Commands.UpsertPersonCommand("person-hash-456", "person2@example.com", null));
|
||||
|
||||
var req = new EmployerAttestUploadRequest(
|
||||
PersonId: person.Id,
|
||||
Title: "IssuedAttest",
|
||||
From: new DateOnly(2023,1,1),
|
||||
To: new DateOnly(2023,12,31),
|
||||
Summary: null,
|
||||
BlobPath: string.Empty,
|
||||
BlobHash: null,
|
||||
ContentBase64: Convert.ToBase64String(new byte[]{4,5,6}),
|
||||
ContentType: "application/octet-stream");
|
||||
|
||||
var createdId = await mediator.Send(new EmployerIssueAttestCommand(employer.Id, req));
|
||||
createdId.Should().NotBeNull();
|
||||
|
||||
var list = await mediator.Send(new ListEmployerAttestsQuery(employer.Id, 10));
|
||||
list.Should().Contain(a => a.Id == createdId);
|
||||
|
||||
// Content
|
||||
var content = await mediator.Send(new GetAttestContentQuery(createdId!.Value));
|
||||
content.Should().NotBeNull();
|
||||
content!.Content.Length.Should().BeGreaterThan(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using FluentAssertions;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using MinAttest.Application.Features.Employers.Commands;
|
||||
using MinAttest.Application.Features.Employers.Queries;
|
||||
using Xunit;
|
||||
|
||||
namespace MinAttest.Tests.Integration;
|
||||
|
||||
[Collection("IntegrationCollection")]
|
||||
public class EmployersIntegrationTests
|
||||
{
|
||||
private readonly IntegrationTestFixture _fixture;
|
||||
public EmployersIntegrationTests(IntegrationTestFixture fixture) => _fixture = fixture;
|
||||
[Fact]
|
||||
public async Task Upsert_and_get_and_list_employers_work()
|
||||
{
|
||||
var mediator = _fixture.Services.GetRequiredService<IMediator>();
|
||||
|
||||
var upsert = await mediator.Send(new UpsertEmployerCommand("123456789", "Acme AS"));
|
||||
upsert.OrgNumber.Should().Be("123456789");
|
||||
upsert.Name.Should().Be("Acme AS");
|
||||
|
||||
var list = await mediator.Send(new ListEmployersQuery());
|
||||
list.Should().Contain(e => e.OrgNumber == "123456789");
|
||||
|
||||
var get = await mediator.Send(new GetEmployerQuery(upsert.Id));
|
||||
get.Should().NotBeNull();
|
||||
get!.Name.Should().Be("Acme AS");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using Xunit;
|
||||
|
||||
namespace MinAttest.Tests.Integration;
|
||||
|
||||
[CollectionDefinition("IntegrationCollection")]
|
||||
public class IntegrationCollection : ICollectionFixture<IntegrationTestFixture>
|
||||
{
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using MinAttest.Application;
|
||||
using MinAttest.Application.Abstractions;
|
||||
using MinAttest.Application.Common.Behaviors;
|
||||
using MinAttest.Infrastructure.Data;
|
||||
using Xunit;
|
||||
|
||||
namespace MinAttest.Tests.Integration;
|
||||
|
||||
public class IntegrationTestFixture : IAsyncLifetime
|
||||
{
|
||||
public IServiceProvider Services { get; private set; } = default!;
|
||||
public string ConnectionString { get; private set; } = string.Empty;
|
||||
|
||||
public async Task InitializeAsync()
|
||||
{
|
||||
await Server.TestDb.StartAsync();
|
||||
ConnectionString = Server.TestDb.ConnectionString;
|
||||
|
||||
var services = new ServiceCollection();
|
||||
|
||||
services.AddDbContext<AppDbContext>(opt => opt.UseSqlServer(ConnectionString));
|
||||
services.AddScoped<IAppDbContext>(sp => sp.GetRequiredService<AppDbContext>());
|
||||
|
||||
services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(ApplicationAssembly).Assembly));
|
||||
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
|
||||
|
||||
Services = services.BuildServiceProvider();
|
||||
|
||||
// Migrate and seed
|
||||
using var scope = Services.CreateScope();
|
||||
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
|
||||
await db.Database.MigrateAsync();
|
||||
|
||||
await SeedAsync(db);
|
||||
}
|
||||
|
||||
public async Task DisposeAsync()
|
||||
{
|
||||
await Server.TestDb.StopAsync();
|
||||
}
|
||||
|
||||
private static async Task SeedAsync(AppDbContext db)
|
||||
{
|
||||
if (!db.Persons.Any())
|
||||
{
|
||||
var personId = Guid.NewGuid();
|
||||
db.Persons.Add(new MinAttest.Domain.Entities.Person
|
||||
{
|
||||
Id = personId,
|
||||
NationalIdHash = "person-hash-123",
|
||||
Email = "person@example.com"
|
||||
});
|
||||
|
||||
var employerId = Guid.NewGuid();
|
||||
db.Employers.Add(new MinAttest.Domain.Entities.Employer
|
||||
{
|
||||
Id = employerId,
|
||||
OrgNumber = "999999999",
|
||||
Name = "TestBedrift AS"
|
||||
});
|
||||
await db.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using Microsoft.AspNetCore.Mvc.Testing;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using MinAttest.Infrastructure.Data;
|
||||
|
||||
namespace MinAttest.Tests.Integration.Server;
|
||||
|
||||
public class ApiWebAppFactory : WebApplicationFactory<Program>
|
||||
{
|
||||
protected override void ConfigureWebHost(Microsoft.AspNetCore.Hosting.IWebHostBuilder builder)
|
||||
{
|
||||
builder.ConfigureServices(services =>
|
||||
{
|
||||
var descriptor = services.SingleOrDefault(d => d.ServiceType == typeof(DbContextOptions<AppDbContext>));
|
||||
if (descriptor is not null)
|
||||
{
|
||||
services.Remove(descriptor);
|
||||
}
|
||||
services.AddDbContext<AppDbContext>(options => options.UseSqlServer(TestDb.ConnectionString));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using Testcontainers.MsSql;
|
||||
|
||||
namespace MinAttest.Tests.Integration.Server;
|
||||
|
||||
public static class TestDb
|
||||
{
|
||||
private static MsSqlContainer? _container;
|
||||
private static readonly object _lock = new();
|
||||
private static bool _started;
|
||||
|
||||
public static string ConnectionString { get; private set; } = string.Empty;
|
||||
|
||||
public static async Task StartAsync()
|
||||
{
|
||||
if (_started) return;
|
||||
lock (_lock)
|
||||
{
|
||||
if (_container == null)
|
||||
{
|
||||
_container = new MsSqlBuilder()
|
||||
.WithImage("mcr.microsoft.com/mssql/server:2022-latest")
|
||||
.WithPassword("Your_password123")
|
||||
.WithPortBinding(14333, 1433)
|
||||
.Build();
|
||||
}
|
||||
}
|
||||
await _container!.StartAsync();
|
||||
ConnectionString = _container.GetConnectionString() + ";Database=MinAttest_Integration";
|
||||
_started = true;
|
||||
}
|
||||
|
||||
public static async Task StopAsync()
|
||||
{
|
||||
if (_container is null) return;
|
||||
await _container.StopAsync();
|
||||
await _container.DisposeAsync();
|
||||
_container = null;
|
||||
_started = false;
|
||||
ConnectionString = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
using FluentAssertions;
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using MinAttest.Application.Features.Attests.Commands;
|
||||
using MinAttest.Application.Features.ShareLinks.Commands;
|
||||
using MinAttest.Application.Features.ShareLinks.Queries;
|
||||
using MinAttest.Contracts.Attests;
|
||||
using MinAttest.Contracts.ShareLinks;
|
||||
using Xunit;
|
||||
|
||||
namespace MinAttest.Tests.Integration;
|
||||
|
||||
[Collection("IntegrationCollection")]
|
||||
public class ShareLinksIntegrationTests
|
||||
{
|
||||
private readonly IntegrationTestFixture _fixture;
|
||||
public ShareLinksIntegrationTests(IntegrationTestFixture fixture) => _fixture = fixture;
|
||||
[Fact]
|
||||
public async Task Create_list_revoke_sharelink_for_attest()
|
||||
{
|
||||
var mediator = _fixture.Services.GetRequiredService<IMediator>();
|
||||
|
||||
// Ensure person
|
||||
var person = await mediator.Send(new MinAttest.Application.Features.Persons.Commands.UpsertPersonCommand("person-hash-123", "person@example.com", null));
|
||||
|
||||
// Create attest
|
||||
var attestId = await mediator.Send(new PersonUploadAttestCommand(person.Id, new PersonAttestUploadRequest(
|
||||
Title: "Test",
|
||||
From: new DateOnly(2023,1,1),
|
||||
To: new DateOnly(2023,12,31),
|
||||
Summary: null,
|
||||
BlobPath: string.Empty,
|
||||
BlobHash: null,
|
||||
ContentBase64: Convert.ToBase64String(new byte[]{1,2,3}),
|
||||
ContentType: "application/octet-stream"
|
||||
)));
|
||||
|
||||
attestId.Should().NotBeNull();
|
||||
|
||||
// Create sharelink
|
||||
var created = await mediator.Send(new CreateShareLinkCommand(attestId!.Value, new CreateShareLinkRequest(TimeSpan.FromDays(7), false), "https://localhost"));
|
||||
created.Should().NotBeNull();
|
||||
|
||||
// List
|
||||
var list = await mediator.Send(new ListShareLinksQuery(attestId.Value));
|
||||
list.Should().Contain(sl => sl.ShareId == created!.ShareId);
|
||||
|
||||
// Revoke
|
||||
var revoked = await mediator.Send(new RevokeShareLinkCommand(attestId.Value, created!.ShareId));
|
||||
revoked.Should().BeTrue();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
|
||||
<PackageReference Include="xunit" Version="2.*" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.*" />
|
||||
<PackageReference Include="FluentAssertions" Version="8.*" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.*" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.9" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="9.0.9" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="9.0.9" />
|
||||
<PackageReference Include="Azure.Core" Version="1.48.0" />
|
||||
<PackageReference Include="Testcontainers" Version="4.*" />
|
||||
<PackageReference Include="Testcontainers.MsSql" Version="4.*" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\MinAttest.Api\MinAttest.Api.csproj" />
|
||||
<ProjectReference Include="..\..\src\MinAttest.Application\MinAttest.Application.csproj" />
|
||||
<ProjectReference Include="..\..\src\MinAttest.Infrastructure\MinAttest.Infrastructure.csproj" />
|
||||
<ProjectReference Include="..\..\src\MinAttest.Domain\MinAttest.Domain.csproj" />
|
||||
<ProjectReference Include="..\..\src\MinAttest.Contracts\MinAttest.Contracts.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"ConnectionStrings": {
|
||||
"Default": "Server=localhost,1433;Database=MinAttest_Integration;User Id=sa;Password=Your_password123;TrustServerCertificate=True;"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user