Events-MVC (example with htmx)
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
#if POSTGRES
|
||||
using Events.EF.Data.Postgres;
|
||||
#else
|
||||
using Events.EF.Data.MSSQL;
|
||||
#endif
|
||||
using Events.EF.Models;
|
||||
using Events.MVC.Models;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Sieve.Models;
|
||||
using Sieve.Services;
|
||||
|
||||
namespace Events.Tests.UnitTests.Infrastructure;
|
||||
|
||||
internal static class ControllerTestContext
|
||||
{
|
||||
public static EventsContext CreateContext()
|
||||
{
|
||||
var options = new DbContextOptionsBuilder<EventsContext>()
|
||||
.UseInMemoryDatabase(Guid.NewGuid().ToString())
|
||||
.Options;
|
||||
|
||||
return new EventsContext(options);
|
||||
}
|
||||
|
||||
public static IOptions<PagingSettings> CreatePagingOptions(int pageSize = 10)
|
||||
{
|
||||
return Options.Create(new PagingSettings { PageSize = pageSize });
|
||||
}
|
||||
|
||||
public static SieveModel EmptySieveModel()
|
||||
{
|
||||
return new SieveModel();
|
||||
}
|
||||
|
||||
public static ISieveProcessor CreateSieveProcessor()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
services.AddLogging();
|
||||
services.AddOptions();
|
||||
services.AddScoped<ISieveProcessor, SieveProcessor>();
|
||||
|
||||
using var provider = services.BuildServiceProvider();
|
||||
using var scope = provider.CreateScope();
|
||||
return scope.ServiceProvider.GetRequiredService<ISieveProcessor>();
|
||||
}
|
||||
|
||||
public static Country CreateCountry(string code = "HR", string alpha3 = "HRV", string name = "Croatia")
|
||||
{
|
||||
return new Country
|
||||
{
|
||||
Code = code,
|
||||
Alpha3 = alpha3,
|
||||
Name = name
|
||||
};
|
||||
}
|
||||
|
||||
public static Person CreatePerson(int id = 1, string countryCode = "HR", string firstName = "Ivan", string lastName = "Horvat")
|
||||
{
|
||||
return new Person
|
||||
{
|
||||
Id = id,
|
||||
FirstName = firstName,
|
||||
LastName = lastName,
|
||||
FirstNameTranscription = firstName,
|
||||
LastNameTranscription = lastName,
|
||||
AddressLine = "Ilica 1",
|
||||
PostalCode = "10000",
|
||||
City = "Zagreb",
|
||||
AddressCountry = "Croatia",
|
||||
Email = $"{firstName.ToLowerInvariant()}.{lastName.ToLowerInvariant()}@example.com",
|
||||
ContactPhone = "+38591111222",
|
||||
BirthDate = new DateOnly(1990, 5, 1),
|
||||
DocumentNumber = $"DOC-{id}",
|
||||
CountryCode = countryCode
|
||||
};
|
||||
}
|
||||
|
||||
public static Event CreateEvent(int id = 100, string name = "Spring Games")
|
||||
{
|
||||
return new Event
|
||||
{
|
||||
Id = id,
|
||||
Name = name,
|
||||
EventDate = new DateOnly(2026, 4, 15)
|
||||
};
|
||||
}
|
||||
|
||||
public static Sport CreateSport(int id = 10, string name = "Football")
|
||||
{
|
||||
return new Sport
|
||||
{
|
||||
Id = id,
|
||||
Name = name
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
|
||||
namespace Events.Tests.UnitTests.Infrastructure;
|
||||
|
||||
internal static class ControllerTestExtensions
|
||||
{
|
||||
public static T WithTempData<T>(this T controller) where T : Controller
|
||||
{
|
||||
var httpContext = new DefaultHttpContext();
|
||||
controller.ControllerContext = new ControllerContext
|
||||
{
|
||||
HttpContext = httpContext
|
||||
};
|
||||
controller.TempData = new TempDataDictionary(httpContext, new TestTempDataProvider());
|
||||
return controller;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Npgsql;
|
||||
|
||||
namespace Events.Tests.UnitTests.Infrastructure;
|
||||
|
||||
public class ProviderSpecificQueryShould
|
||||
{
|
||||
[Fact]
|
||||
public async Task ReturnMatchingRowsWhenUsingILikeWithInMemoryProvider()
|
||||
{
|
||||
await using var ctx = ControllerTestContext.CreateContext();
|
||||
ctx.Countries.Add(ControllerTestContext.CreateCountry());
|
||||
ctx.People.Add(ControllerTestContext.CreatePerson());
|
||||
await ctx.SaveChangesAsync();
|
||||
|
||||
var people = await ctx.People
|
||||
.Where(person => person.FirstName != null && Microsoft.EntityFrameworkCore.EF.Functions.ILike(person.FirstName, "%iv%"))
|
||||
.ToListAsync();
|
||||
|
||||
Assert.Single(people);
|
||||
Assert.Equal("Ivan", people[0].FirstName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ThrowInvalidOperationExceptionWhenUsingILikeWithInMemoryProvider()
|
||||
{
|
||||
await using var ctx = ControllerTestContext.CreateContext();
|
||||
ctx.Countries.Add(ControllerTestContext.CreateCountry());
|
||||
ctx.People.Add(ControllerTestContext.CreatePerson());
|
||||
await ctx.SaveChangesAsync();
|
||||
|
||||
var exception = await Assert.ThrowsAsync<InvalidOperationException>(async () =>
|
||||
await ctx.People
|
||||
.Where(person => person.FirstName != null && Microsoft.EntityFrameworkCore.EF.Functions.ILike(person.FirstName, "%iv%"))
|
||||
.ToListAsync());
|
||||
|
||||
Assert.Contains("ILike", exception.Message, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExecuteILikeWhenUsingPostgreSqlProvider()
|
||||
{
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.SetBasePath(AppContext.BaseDirectory)
|
||||
.AddJsonFile("appsettings.json", optional: false)
|
||||
.AddUserSecrets<ProviderSpecificQueryShould>(optional: true)
|
||||
.Build();
|
||||
|
||||
var productionConnectionString = configuration.GetConnectionString("EventDB-Test");
|
||||
Assert.False(
|
||||
string.IsNullOrWhiteSpace(productionConnectionString),
|
||||
"The EventDB-Test connection string must be available so the PostgreSQL-backed provider test can connect to the PostgreSQL copy.");
|
||||
|
||||
var connectionStringBuilder = new NpgsqlConnectionStringBuilder(productionConnectionString)
|
||||
{
|
||||
SslMode = SslMode.Disable
|
||||
};
|
||||
|
||||
var options = new DbContextOptionsBuilder<Events.EF.Data.Postgres.EventsContext>()
|
||||
.UseNpgsql(connectionStringBuilder.ConnectionString)
|
||||
.Options;
|
||||
|
||||
await using var ctx = new Events.EF.Data.Postgres.EventsContext(options);
|
||||
|
||||
var people = await ctx.People
|
||||
.Where(person => person.FirstName != null && Microsoft.EntityFrameworkCore.EF.Functions.ILike(person.FirstName, "%iv%"))
|
||||
.Take(20)
|
||||
.ToListAsync();
|
||||
|
||||
Assert.NotEmpty(people);
|
||||
Assert.All(
|
||||
people,
|
||||
person => Assert.Contains(
|
||||
"iv",
|
||||
person.FirstName,
|
||||
StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||
|
||||
namespace Events.Tests.UnitTests.Infrastructure;
|
||||
|
||||
internal sealed class TestTempDataProvider : ITempDataProvider
|
||||
{
|
||||
private Dictionary<string, object> values = [];
|
||||
|
||||
public IDictionary<string, object> LoadTempData(HttpContext context)
|
||||
{
|
||||
return new Dictionary<string, object>(values);
|
||||
}
|
||||
|
||||
public void SaveTempData(HttpContext context, IDictionary<string, object> values)
|
||||
{
|
||||
this.values = new Dictionary<string, object>(values);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user