Files
PnvPanel/backend/tests/PnvPanel.Application.Tests/Admin/Support/ApproveRoleRequestCommandHandlerTests.cs
T
Leonid Pershin ae379f8e0f
CI / Backend (build + test) (push) Successful in 1m19s
CI / Frontend (lint + typecheck + build) (push) Successful in 32s
Implement pricing management functionality and update related components
- Added new endpoints for managing global pricing settings, including retrieval and updates for `PricePerConfigPerQuarter` and `PricePerConfigPerYear`.
- Updated `RoleService` and related commands to remove pricing fields from role management, ensuring a clear separation between role configurations and global pricing.
- Enhanced the `FactoryResetCommandHandler` to include seeding of pricing settings during a factory reset.
- Modified frontend components to support new pricing settings, including forms for creating and updating pricing information.
- Updated API documentation to reflect changes in pricing management endpoints and their expected request/response formats.
- Adjusted tests to ensure proper coverage for new pricing functionalities and their integration with existing role management features.
2026-07-18 19:34:29 +03:00

201 lines
7.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using NSubstitute;
using PnvPanel.Application.Admin.Roles;
using PnvPanel.Application.Admin.Support;
using PnvPanel.Application.Common.Interfaces;
using PnvPanel.Application.Common.Models;
using PnvPanel.Application.Support;
using PnvPanel.Application.Tests.TestSupport;
using PnvPanel.Domain.Support;
using Xunit;
namespace PnvPanel.Application.Tests.Admin.Support;
public class ApproveRoleRequestCommandHandlerTests
{
private readonly IRoleService _roleService = Substitute.For<IRoleService>();
private readonly IRealtimeNotifier _notifier = Substitute.For<IRealtimeNotifier>();
private readonly ITelegramNotifier _telegramNotifier = Substitute.For<ITelegramNotifier>();
[Fact]
public async Task Handle_ForNewRoleRequest_CreatesRoleAssignsAndResolves()
{
using var dbContext = InMemoryDbContextFactory.Create();
var userId = Guid.NewGuid();
var ticket = SupportTicket.CreateRoleRequestForNewRole(userId, "premium", 10, 5);
dbContext.SupportTickets.Add(ticket);
await dbContext.SaveChangesAsync(CancellationToken.None);
var newRoleId = Guid.NewGuid();
_roleService
.CreateRoleAsync("premium", 10, 5, Arg.Any<CancellationToken>())
.Returns(Result.Success(new RoleDto(newRoleId, "premium", 10, 5, false)));
_roleService
.ChangeUserRoleAsync(userId, newRoleId, Arg.Any<CancellationToken>())
.Returns(Result.Success());
var currentUser = FakeCurrentUser.Authenticated(Guid.NewGuid(), "admin");
var handler = new ApproveRoleRequestCommandHandler(
dbContext,
_roleService,
_notifier,
_telegramNotifier,
currentUser
);
var result = await handler.Handle(
new ApproveRoleRequestCommand(ticket.Id),
CancellationToken.None
);
Assert.True(result.IsSuccess);
Assert.Equal(TicketStatus.Resolved, ticket.Status);
await _roleService
.Received(1)
.CreateRoleAsync("premium", 10, 5, Arg.Any<CancellationToken>());
await _roleService
.Received(1)
.ChangeUserRoleAsync(userId, newRoleId, Arg.Any<CancellationToken>());
await _telegramNotifier
.Received(1)
.NotifyUserAsync(
userId,
Arg.Any<string>(),
Arg.Any<string?>(),
Arg.Any<CancellationToken>()
);
}
[Fact]
public async Task Handle_ForExistingRoleRequest_SkipsRoleCreation()
{
using var dbContext = InMemoryDbContextFactory.Create();
var userId = Guid.NewGuid();
var roleId = Guid.NewGuid();
var ticket = SupportTicket.CreateRoleRequestForExistingRole(userId, roleId);
dbContext.SupportTickets.Add(ticket);
await dbContext.SaveChangesAsync(CancellationToken.None);
_roleService
.ChangeUserRoleAsync(userId, roleId, Arg.Any<CancellationToken>())
.Returns(Result.Success());
var currentUser = FakeCurrentUser.Authenticated(Guid.NewGuid());
var handler = new ApproveRoleRequestCommandHandler(
dbContext,
_roleService,
_notifier,
_telegramNotifier,
currentUser
);
var result = await handler.Handle(
new ApproveRoleRequestCommand(ticket.Id),
CancellationToken.None
);
Assert.True(result.IsSuccess);
await _roleService
.DidNotReceive()
.CreateRoleAsync(
Arg.Any<string>(),
Arg.Any<int>(),
Arg.Any<int>(),
Arg.Any<CancellationToken>()
);
}
[Fact]
public async Task Handle_WhenNotRoleRequestType_ReturnsError()
{
using var dbContext = InMemoryDbContextFactory.Create();
var ticket = SupportTicket.CreateBugReport(Guid.NewGuid());
dbContext.SupportTickets.Add(ticket);
await dbContext.SaveChangesAsync(CancellationToken.None);
var currentUser = FakeCurrentUser.Authenticated(Guid.NewGuid());
var handler = new ApproveRoleRequestCommandHandler(
dbContext,
_roleService,
_notifier,
_telegramNotifier,
currentUser
);
var result = await handler.Handle(
new ApproveRoleRequestCommand(ticket.Id),
CancellationToken.None
);
Assert.False(result.IsSuccess);
Assert.Equal(SupportErrors.NotRoleRequest, result.Error);
}
[Fact]
public async Task Handle_WhenTicketIsOwnedByAdmin_StillApproves()
{
// Одобрить свою же заявку можно — единственный реальный риск (снять admin с последнего
// администратора) ловит RoleService.ChangeUserRoleAsync, а не этот хендлер (см. соседний тест).
using var dbContext = InMemoryDbContextFactory.Create();
var adminId = Guid.NewGuid();
var roleId = Guid.NewGuid();
var ticket = SupportTicket.CreateRoleRequestForExistingRole(adminId, roleId);
dbContext.SupportTickets.Add(ticket);
await dbContext.SaveChangesAsync(CancellationToken.None);
_roleService
.ChangeUserRoleAsync(adminId, roleId, Arg.Any<CancellationToken>())
.Returns(Result.Success());
var currentUser = FakeCurrentUser.Authenticated(adminId, "admin");
var handler = new ApproveRoleRequestCommandHandler(
dbContext,
_roleService,
_notifier,
_telegramNotifier,
currentUser
);
var result = await handler.Handle(
new ApproveRoleRequestCommand(ticket.Id),
CancellationToken.None
);
Assert.True(result.IsSuccess);
Assert.Equal(TicketStatus.Resolved, ticket.Status);
}
[Fact]
public async Task Handle_WhenRoleServiceRefusesLastAdminDowngrade_PropagatesFailure()
{
using var dbContext = InMemoryDbContextFactory.Create();
var adminId = Guid.NewGuid();
var roleId = Guid.NewGuid();
var ticket = SupportTicket.CreateRoleRequestForExistingRole(adminId, roleId);
dbContext.SupportTickets.Add(ticket);
await dbContext.SaveChangesAsync(CancellationToken.None);
_roleService
.ChangeUserRoleAsync(adminId, roleId, Arg.Any<CancellationToken>())
.Returns(Result.Failure(RoleErrors.CannotRemoveLastAdmin));
var currentUser = FakeCurrentUser.Authenticated(adminId, "admin");
var handler = new ApproveRoleRequestCommandHandler(
dbContext,
_roleService,
_notifier,
_telegramNotifier,
currentUser
);
var result = await handler.Handle(
new ApproveRoleRequestCommand(ticket.Id),
CancellationToken.None
);
Assert.False(result.IsSuccess);
Assert.Equal(RoleErrors.CannotRemoveLastAdmin, result.Error);
// Тикет остаётся Open — можно повторить попытку после назначения второго админа.
Assert.Equal(TicketStatus.Open, ticket.Status);
}
}