test(backend): cover step 17 modules and extract stubs
Add tests for partnership workflow, middleman adaptation and idea notifications; extract reusable test stubs into separate files; add architecture guard forbidding object-valued dictionaries in data contracts.
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
using TarninaHub.Application.Abstractions;
|
||||
using TarninaHub.Application.Dtos;
|
||||
|
||||
namespace TarninaHub.Tests.Stubs;
|
||||
|
||||
/// <summary>Configurable IApplicationService stub for controller tests.</summary>
|
||||
public sealed class StubApplicationService : IApplicationService
|
||||
{
|
||||
private readonly CreateApplicationResult _createResult;
|
||||
|
||||
public StubApplicationService(CreateApplicationResult createResult)
|
||||
{
|
||||
_createResult = createResult;
|
||||
}
|
||||
|
||||
public Task<CreateApplicationResult> CreateAsync(
|
||||
string userId,
|
||||
CreateApplicationRequest request,
|
||||
CancellationToken cancellationToken) => Task.FromResult(_createResult);
|
||||
|
||||
public Task<ApplicationResponse?> GetAsync(string applicationId, CancellationToken cancellationToken) =>
|
||||
Task.FromResult(_createResult.Application);
|
||||
|
||||
public Task<IReadOnlyList<ApplicationResponse>> ListForAuthorAsync(
|
||||
string authorId,
|
||||
CancellationToken cancellationToken) => Task.FromResult<IReadOnlyList<ApplicationResponse>>([]);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using TarninaHub.Application.Abstractions;
|
||||
using TarninaHub.Application.Dtos;
|
||||
|
||||
namespace TarninaHub.Tests.Stubs;
|
||||
|
||||
/// <summary>No-op IIdeaAssistant stub for controller tests.</summary>
|
||||
public sealed class StubIdeaAssistant : IIdeaAssistant
|
||||
{
|
||||
public Task<IdeaAssistResponse?> AssistAsync(
|
||||
string ideaId,
|
||||
IdeaAssistRequest request,
|
||||
CancellationToken cancellationToken) =>
|
||||
Task.FromResult<IdeaAssistResponse?>(new IdeaAssistResponse([], "opis", false));
|
||||
}
|
||||
@@ -17,6 +17,9 @@ public sealed class StubIdeaService : IIdeaService
|
||||
public Task<IReadOnlyList<IdeaResponse>> ListForAuthorAsync(string authorId, CancellationToken cancellationToken) =>
|
||||
Task.FromResult<IReadOnlyList<IdeaResponse>>(Idea is null ? [] : [Idea]);
|
||||
|
||||
public Task<IReadOnlyList<string>> ListDistinctAuthorIdsAsync(CancellationToken cancellationToken) =>
|
||||
Task.FromResult<IReadOnlyList<string>>(Idea is null ? [] : [Idea.AuthorId]);
|
||||
|
||||
public Task<IdeaResponse?> UpdateAsync(string ideaId, UpdateIdeaRequest request, CancellationToken cancellationToken) =>
|
||||
Task.FromResult(Idea);
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
using TarninaHub.Application.Abstractions;
|
||||
using TarninaHub.Application.Dtos;
|
||||
|
||||
namespace TarninaHub.Tests.Stubs;
|
||||
|
||||
/// <summary>Innovation lookup stub returning a fixed (or null) innovation.</summary>
|
||||
public sealed class StubInnovationLookup : IInnovationService
|
||||
{
|
||||
private readonly InnovationResponse? _innovation;
|
||||
|
||||
public StubInnovationLookup(InnovationResponse? innovation)
|
||||
{
|
||||
_innovation = innovation;
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<InnovationResponse>> ListAsync(
|
||||
string? challengeId,
|
||||
string? stage,
|
||||
string? query,
|
||||
bool onlyPublished,
|
||||
CancellationToken cancellationToken) => Task.FromResult<IReadOnlyList<InnovationResponse>>([]);
|
||||
|
||||
public Task<InnovationResponse?> GetAsync(string innovationId, CancellationToken cancellationToken) =>
|
||||
Task.FromResult(_innovation);
|
||||
|
||||
public Task<InnovationResponse> CreateAsync(
|
||||
InnovationRequest request,
|
||||
CancellationToken cancellationToken) => throw new NotSupportedException();
|
||||
|
||||
public Task<InnovationResponse?> UpdateAsync(
|
||||
string innovationId,
|
||||
InnovationRequest request,
|
||||
CancellationToken cancellationToken) => throw new NotSupportedException();
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
using TarninaHub.Application.Abstractions;
|
||||
using TarninaHub.Application.Dtos;
|
||||
|
||||
namespace TarninaHub.Tests.Stubs;
|
||||
|
||||
/// <summary>Configurable IInnovationService stub for controller tests.</summary>
|
||||
public sealed class StubInnovationService : IInnovationService
|
||||
{
|
||||
public Task<IReadOnlyList<InnovationResponse>> ListAsync(
|
||||
string? challengeId,
|
||||
string? stage,
|
||||
string? query,
|
||||
bool onlyPublished,
|
||||
CancellationToken cancellationToken) => Task.FromResult<IReadOnlyList<InnovationResponse>>([]);
|
||||
|
||||
public Task<InnovationResponse?> GetAsync(string innovationId, CancellationToken cancellationToken) =>
|
||||
Task.FromResult<InnovationResponse?>(null);
|
||||
|
||||
public Task<InnovationResponse> CreateAsync(
|
||||
InnovationRequest request,
|
||||
CancellationToken cancellationToken) => Task.FromResult(new InnovationResponse(
|
||||
"innovation:new",
|
||||
request.Title,
|
||||
request.Summary ?? string.Empty,
|
||||
request.Description ?? string.Empty,
|
||||
request.ChallengeId,
|
||||
request.Stage,
|
||||
request.Cost,
|
||||
request.Contact,
|
||||
request.Media ?? [],
|
||||
request.Published,
|
||||
DateTimeOffset.UtcNow));
|
||||
|
||||
public Task<InnovationResponse?> UpdateAsync(
|
||||
string innovationId,
|
||||
InnovationRequest request,
|
||||
CancellationToken cancellationToken) => Task.FromResult<InnovationResponse?>(null);
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using TarninaHub.Application.Abstractions;
|
||||
using TarninaHub.Application.Dtos;
|
||||
|
||||
namespace TarninaHub.Tests.Stubs;
|
||||
|
||||
/// <summary>No-op INotificationService stub for controller tests.</summary>
|
||||
public sealed class StubNotificationService : INotificationService
|
||||
{
|
||||
public int StaffNotifications { get; private set; }
|
||||
|
||||
public int UserNotifications { get; private set; }
|
||||
|
||||
public Task NotifyStaffAsync(
|
||||
string type,
|
||||
IReadOnlyDictionary<string, string?> payload,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
StaffNotifications++;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task NotifyUserAsync(
|
||||
string userId,
|
||||
string type,
|
||||
IReadOnlyDictionary<string, string?> payload,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
UserNotifications++;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<IReadOnlyList<NotificationResponse>> ListForUserAsync(
|
||||
string userId,
|
||||
CancellationToken cancellationToken) => Task.FromResult<IReadOnlyList<NotificationResponse>>([]);
|
||||
|
||||
public Task<NotificationResponse?> MarkReadAsync(
|
||||
string notificationId,
|
||||
string userId,
|
||||
CancellationToken cancellationToken) => Task.FromResult<NotificationResponse?>(null);
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using TarninaHub.Application.Abstractions;
|
||||
using TarninaHub.Application.Dtos;
|
||||
|
||||
namespace TarninaHub.Tests.Stubs;
|
||||
|
||||
/// <summary>Configurable ISubmissionService stub for controller tests.</summary>
|
||||
public sealed class StubSubmissionService : ISubmissionService
|
||||
{
|
||||
public SubmissionResponse? Current { get; set; }
|
||||
|
||||
public SubmissionResponse? UpdateResult { get; set; }
|
||||
|
||||
public string? LastRequestedStatus { get; private set; }
|
||||
|
||||
public Task<SubmissionResponse> CreateAsync(
|
||||
string authorId,
|
||||
CreateSubmissionRequest request,
|
||||
CancellationToken cancellationToken) => Task.FromResult(Current ?? throw new InvalidOperationException());
|
||||
|
||||
public Task<PagedResponse<SubmissionResponse>> ListAsync(
|
||||
string viewerId,
|
||||
bool isStaff,
|
||||
string? status,
|
||||
int page,
|
||||
int pageSize,
|
||||
CancellationToken cancellationToken) => Task.FromResult(
|
||||
new PagedResponse<SubmissionResponse>([], page, pageSize, 0));
|
||||
|
||||
public Task<SubmissionResponse?> GetAsync(string submissionId, CancellationToken cancellationToken) =>
|
||||
Task.FromResult(Current);
|
||||
|
||||
public Task<SubmissionResponse?> UpdateStatusAsync(
|
||||
string submissionId,
|
||||
string newStatus,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
LastRequestedStatus = newStatus;
|
||||
|
||||
return Task.FromResult(UpdateResult);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using TarninaHub.Application.Abstractions;
|
||||
using TarninaHub.Application.Dtos;
|
||||
|
||||
namespace TarninaHub.Tests.Stubs;
|
||||
|
||||
/// <summary>No-op ITestFeedbackService stub for controller tests.</summary>
|
||||
public sealed class StubTestFeedbackService : ITestFeedbackService
|
||||
{
|
||||
public Task<TestFeedbackResponse?> CreateAsync(
|
||||
string innovationId,
|
||||
string authorId,
|
||||
CreateTestFeedbackRequest request,
|
||||
CancellationToken cancellationToken) => Task.FromResult<TestFeedbackResponse?>(null);
|
||||
|
||||
public Task<IReadOnlyList<TestFeedbackResponse>> ListForInnovationAsync(
|
||||
string innovationId,
|
||||
CancellationToken cancellationToken) => Task.FromResult<IReadOnlyList<TestFeedbackResponse>>([]);
|
||||
}
|
||||
Reference in New Issue
Block a user