Refactored Fake.cs to configure both in-memory and SQL Server database contexts for testing, using the "Default" connection string from configuration. Added detailed EF logging and SQL executor setup. In TestBase.cs, fixed Setup to use the correct repository instance for seeding email templates.
311 lines
11 KiB
C#
311 lines
11 KiB
C#
using Bogus;
|
|
using CommandDotNet;
|
|
using DigitalData.Core.Abstraction.Application.Repository;
|
|
using DigitalData.UserManager.Domain.Entities;
|
|
using EnvelopeGenerator.Application;
|
|
using EnvelopeGenerator.Application.Common.Configurations;
|
|
using EnvelopeGenerator.Application.Common.Extensions;
|
|
using EnvelopeGenerator.Application.EnvelopeReceivers.Commands;
|
|
using EnvelopeGenerator.Application.Envelopes.Commands;
|
|
using EnvelopeGenerator.Application.Histories.Commands;
|
|
using EnvelopeGenerator.Application.Receivers.Commands;
|
|
using EnvelopeGenerator.Application.Users.Commands;
|
|
using EnvelopeGenerator.Domain.Constants;
|
|
using EnvelopeGenerator.Domain.Entities;
|
|
using EnvelopeGenerator.Infrastructure;
|
|
using MediatR;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Hosting;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Options;
|
|
using QuestPDF.Fluent;
|
|
using QuestPDF.Infrastructure;
|
|
|
|
namespace EnvelopeGenerator.Tests;
|
|
|
|
public class Fake
|
|
{
|
|
public static readonly Faker Provider = new("de");
|
|
|
|
public static Host CreateHost(Action<IServiceCollection>? configureServices = null) => Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder()
|
|
.ConfigureAppConfiguration((context, config) =>
|
|
{
|
|
// add appsettings.json
|
|
config.SetBasePath(Directory.GetCurrentDirectory());
|
|
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
|
|
})
|
|
.ConfigureServices((context, services) =>
|
|
{
|
|
IConfiguration configuration = context.Configuration;
|
|
|
|
// add Application and Infrastructure services
|
|
#pragma warning disable CS0618
|
|
services.AddEnvelopeGeneratorServices(configuration);
|
|
|
|
var cnnStrName = "Default";
|
|
|
|
var connStr = context.Configuration.GetConnectionString(cnnStrName)
|
|
?? throw new InvalidOperationException($"Connection string '{cnnStrName}' is missing in the application configuration.");
|
|
|
|
services.AddEnvelopeGeneratorInfrastructureServices(opt =>
|
|
{
|
|
opt.AddDbContext(dbCtxOpt => dbCtxOpt.UseInMemoryDatabase("EnvelopeGeneratorTestDb"));
|
|
|
|
opt.AddDbTriggerParams(context.Configuration);
|
|
|
|
opt.AddDbContext((provider, options) =>
|
|
{
|
|
var logger = provider.GetRequiredService<ILogger<EGDbContext>>();
|
|
options.UseSqlServer(connStr)
|
|
.LogTo(log => logger.LogInformation("{log}", log), Microsoft.Extensions.Logging.LogLevel.Trace)
|
|
.EnableSensitiveDataLogging()
|
|
.EnableDetailedErrors();
|
|
});
|
|
opt.AddSQLExecutor(executor => executor.ConnectionString = connStr);
|
|
|
|
});
|
|
|
|
var prodCnnStr = context.Configuration.GetConnectionString("Default");
|
|
services.AddDbContext<EGDbContext2Prod>(opt => opt.UseSqlServer(prodCnnStr));
|
|
|
|
// add custom services
|
|
configureServices?.Invoke(services);
|
|
#pragma warning restore CS0618
|
|
})
|
|
.Build()
|
|
.ToFake();
|
|
|
|
public class Host : IHost
|
|
{
|
|
#region Root
|
|
private readonly IHost _root;
|
|
|
|
public Host(IHost root)
|
|
{
|
|
_root = root;
|
|
}
|
|
|
|
public IServiceProvider Services => _root.Services;
|
|
|
|
public void Dispose()
|
|
{
|
|
_root.Dispose();
|
|
}
|
|
|
|
public Task StartAsync(CancellationToken cancel = default)
|
|
{
|
|
return _root.StartAsync(cancel);
|
|
}
|
|
|
|
public Task StopAsync(CancellationToken cancel = default)
|
|
{
|
|
return _root.StopAsync(cancel);
|
|
}
|
|
#endregion
|
|
|
|
#region Shortcuts
|
|
public IMediator Mediator => Services.GetRequiredService<IMediator>();
|
|
|
|
public IRepository<TEntity> GetRepository<TEntity>() => Services.GetRequiredService<IRepository<TEntity>>();
|
|
|
|
public async Task<Host> AddSamples()
|
|
{
|
|
await AddSampleReceivers();
|
|
await AddSampleUser();
|
|
return this;
|
|
}
|
|
#endregion
|
|
|
|
#region Sample Receivers
|
|
public List<(int Id, string EmailAddress)> _sampleReceivers = new();
|
|
|
|
public IEnumerable<(int Id, string EmailAddress)> SampleReceivers
|
|
=> _sampleReceivers.Any()
|
|
? _sampleReceivers
|
|
: throw new InvalidOperationException(
|
|
"No sample receivers have been initialized. Call AddSampleReceivers() before accessing this property."
|
|
);
|
|
|
|
public async Task<Host> AddSampleReceivers()
|
|
{
|
|
var mediator = Mediator;
|
|
foreach (var cmd in Provider.CreateReceiverCommands())
|
|
{
|
|
var (receiver, _) = await mediator.Send(cmd);
|
|
_sampleReceivers.Add((receiver.Id, cmd.EmailAddress));
|
|
}
|
|
return this;
|
|
}
|
|
#endregion
|
|
|
|
#region Sample User
|
|
private User? _user;
|
|
|
|
public User User => _user ?? throw new InvalidOperationException(
|
|
"The 'User' instance has not been initialized. Call AddSampleUser() before accessing this property.");
|
|
|
|
public async Task<Host> AddSampleUser()
|
|
{
|
|
var repo = GetRepository<User>();
|
|
var cmd = Provider.CreateUserCommand();
|
|
_user = await repo.CreateAsync(cmd);
|
|
return this;
|
|
}
|
|
#endregion
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents a mock database context that inherits from <see cref="EGDbContext"/>.
|
|
/// This context is intended for testing purposes while connecting to the production database.
|
|
/// </summary>
|
|
public class EGDbContext2Prod : EGDbContextBase
|
|
{
|
|
public EGDbContext2Prod(DbContextOptions<EGDbContext2Prod> options, IOptions<DbTriggerParams> triggerParamOptions, ILogger<EGDbContext>? logger = null) : base(options, triggerParamOptions, logger)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
|
|
public static class Extensions
|
|
{
|
|
public static Fake.Host ToFake(this IHost host) => new(host);
|
|
|
|
public static T PickEnum<T>(this Faker faker) where T : struct, Enum
|
|
{
|
|
var values = Enum.GetValues(typeof(T));
|
|
var index = faker.Random.Int(0, values.Length - 1);
|
|
return (T)values.GetValue(index)!;
|
|
}
|
|
|
|
#region Receiver Command
|
|
public static CreateReceiverCommand CreateReceiverCommand(this Faker fake, string? emailAddress = null) => new()
|
|
{
|
|
EmailAddress = emailAddress ?? fake.Internet.Email(),
|
|
};
|
|
|
|
public static List<CreateReceiverCommand> CreateReceiverCommands(this Faker fake, int minCount = 10, int maxCount = 20)
|
|
=> Enumerable.Range(0, fake.Random.Number(minCount, maxCount))
|
|
.Select(_ => fake.CreateReceiverCommand())
|
|
.ToList();
|
|
#endregion
|
|
|
|
#region Envelope
|
|
public static CreateEnvelopeCommand CreateEnvelopeCommand(this Faker fake, int userId) => new()
|
|
{
|
|
Message = fake.Lorem.Paragraph(fake.Random.Number(2, 5)),
|
|
Title = fake.Lorem.Words(fake.Random.Number(3, 4)).Join(" "),
|
|
UserId = userId,
|
|
UseSQLExecutor = false
|
|
};
|
|
|
|
public static List<CreateEnvelopeCommand> CreateEnvelopeCommands(this Faker fake, params int[] userIDs)
|
|
=> Enumerable.Range(0, userIDs.Length)
|
|
.Select(fake.CreateEnvelopeCommand)
|
|
.ToList();
|
|
|
|
public static Envelope CreateEnvelope(this Faker faker, int userId, bool tfaEnabled = false) => new()
|
|
{
|
|
Id = faker.Random.Number(1, 1000),
|
|
UserId = userId,
|
|
Status = EnvelopeStatus.EnvelopeCreated,
|
|
Uuid = Guid.NewGuid().ToString(),
|
|
Title = faker.Lorem.Paragraph(faker.Random.Number(1, 2)),
|
|
Message = faker.Lorem.Paragraph(faker.Random.Number(2, 5)),
|
|
TfaEnabled = tfaEnabled,
|
|
AddedWhen = DateTime.UtcNow,
|
|
CertificationType = (int)CertificationType.AdvancedElectronicSignature,
|
|
UseAccessCode = false,
|
|
ContractType = (int)ContractType.Contract,
|
|
Language = "de",
|
|
SendReminderEmails = false,
|
|
Comment = faker.Lorem.Sentence(10),
|
|
DocResult = faker.CreatePdfAsByte()
|
|
};
|
|
#endregion
|
|
|
|
#region Document
|
|
public static byte[] CreatePdfAsByte(this Faker faker)
|
|
{
|
|
string name = faker.Name.FullName();
|
|
string address = faker.Address.FullAddress();
|
|
string lorem = faker.Lorem.Paragraphs(2);
|
|
|
|
QuestPDF.Settings.License = LicenseType.Community;
|
|
var document = QuestPDF.Fluent.Document.Create(container =>
|
|
{
|
|
container.Page(page =>
|
|
{
|
|
page.Margin(50);
|
|
page.Header().Text("Random PDF").FontSize(20).Bold();
|
|
page.Content().Column(col =>
|
|
{
|
|
col.Item().Text($"Vor- und Nachname: {name}");
|
|
col.Item().Text($"Adresse: {address}");
|
|
col.Item().Text(lorem);
|
|
});
|
|
});
|
|
});
|
|
|
|
using var ms = new MemoryStream();
|
|
document.GeneratePdf(ms);
|
|
return ms.ToArray();
|
|
}
|
|
|
|
public static string CreatePdfAsBase64(this Faker faker) => Convert.ToBase64String(faker.CreatePdfAsByte());
|
|
|
|
public static DocumentCreateCommand CreateDocumentCommand(this Faker faker) => new()
|
|
{
|
|
DataAsBase64 = faker.CreatePdfAsBase64()
|
|
};
|
|
|
|
public static List<DocumentCreateCommand> CreateDocumentCommands(this Faker fake, int minCount = 10, int maxCount = 20)
|
|
=> Enumerable.Range(0, fake.Random.Number(minCount, maxCount))
|
|
.Select(_ => fake.CreateDocumentCommand())
|
|
.ToList();
|
|
#endregion
|
|
|
|
#region Envelope Receiver
|
|
public static EnvelopeReceiver CreateEnvelopeReceiver(this Faker faker, int envelopeId, int receiverId) => new()
|
|
{
|
|
EnvelopeId = envelopeId,
|
|
ReceiverId = receiverId,
|
|
Status = ReceiverStatus.Unsigned,
|
|
AddedWhen = DateTime.UtcNow,
|
|
AccessCode = faker.Random.Number(1000, 9999).ToString(),
|
|
ChangedWhen = DateTime.UtcNow,
|
|
CompanyName = faker.Company.CompanyName(),
|
|
JobTitle = faker.Name.JobTitle(),
|
|
Name = faker.Name.FullName(),
|
|
};
|
|
#endregion
|
|
|
|
#region History
|
|
public static CreateHistoryCommand CreateHistoryCommand(this Faker fake, string key, EnvelopeStatus? status = null)
|
|
{
|
|
return new()
|
|
{
|
|
Status = status ?? fake.PickEnum<EnvelopeStatus>(),
|
|
Comment = fake.Lorem.Sentence(),
|
|
Key = key,
|
|
};
|
|
}
|
|
#endregion
|
|
|
|
#region User Command
|
|
public static CreateUserCommand CreateUserCommand(this Faker fake) => new()
|
|
{
|
|
Prename = fake.Name.FirstName(),
|
|
Name = fake.Name.LastName(),
|
|
Username = fake.Internet.UserName(),
|
|
Shortname = fake.Random.String2(3, 8),
|
|
Email = fake.Internet.Email()
|
|
};
|
|
|
|
public static List<CreateUserCommand> CreateUserCommands(this Faker fake, int minCount = 10, int maxCount = 20)
|
|
=> Enumerable.Range(0, fake.Random.Number(minCount, maxCount))
|
|
.Select(_ => fake.CreateUserCommand())
|
|
.ToList();
|
|
#endregion
|
|
} |