0
0
mirror of https://github.com/alex289/CleanArchitecture.git synced 2025-07-03 20:12:56 +00:00

Merge pull request #21 from alex289/feature/pagination

feat: Add pagination
This commit is contained in:
Alex 2023-08-31 19:35:46 +02:00 committed by GitHub
commit f46994c60a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 204 additions and 52 deletions

View File

@ -1,8 +1,8 @@
using System; using System;
using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using CleanArchitecture.Api.Models; using CleanArchitecture.Api.Models;
using CleanArchitecture.Application.Interfaces; using CleanArchitecture.Application.Interfaces;
using CleanArchitecture.Application.ViewModels;
using CleanArchitecture.Application.ViewModels.Tenants; using CleanArchitecture.Application.ViewModels.Tenants;
using CleanArchitecture.Domain.Notifications; using CleanArchitecture.Domain.Notifications;
using MediatR; using MediatR;
@ -28,10 +28,14 @@ public sealed class TenantController : ApiController
[HttpGet] [HttpGet]
[SwaggerOperation("Get a list of all tenants")] [SwaggerOperation("Get a list of all tenants")]
[SwaggerResponse(200, "Request successful", typeof(ResponseMessage<IEnumerable<TenantViewModel>>))] [SwaggerResponse(200, "Request successful", typeof(ResponseMessage<PagedResult<TenantViewModel>>))]
public async Task<IActionResult> GetAllTenantsAsync() public async Task<IActionResult> GetAllTenantsAsync(
[FromQuery] PageQuery query,
[FromQuery] string searchTerm = "")
{ {
var tenants = await _tenantService.GetAllTenantsAsync(); var tenants = await _tenantService.GetAllTenantsAsync(
query,
searchTerm);
return Response(tenants); return Response(tenants);
} }

View File

@ -1,8 +1,8 @@
using System; using System;
using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using CleanArchitecture.Api.Models; using CleanArchitecture.Api.Models;
using CleanArchitecture.Application.Interfaces; using CleanArchitecture.Application.Interfaces;
using CleanArchitecture.Application.ViewModels;
using CleanArchitecture.Application.ViewModels.Users; using CleanArchitecture.Application.ViewModels.Users;
using CleanArchitecture.Domain.Notifications; using CleanArchitecture.Domain.Notifications;
using MediatR; using MediatR;
@ -28,10 +28,14 @@ public sealed class UserController : ApiController
[HttpGet] [HttpGet]
[SwaggerOperation("Get a list of all users")] [SwaggerOperation("Get a list of all users")]
[SwaggerResponse(200, "Request successful", typeof(ResponseMessage<IEnumerable<UserViewModel>>))] [SwaggerResponse(200, "Request successful", typeof(ResponseMessage<PagedResult<UserViewModel>>))]
public async Task<IActionResult> GetAllUsersAsync() public async Task<IActionResult> GetAllUsersAsync(
[FromQuery] PageQuery query,
[FromQuery] string searchTerm = "")
{ {
var users = await _userService.GetAllUsersAsync(); var users = await _userService.GetAllUsersAsync(
query,
searchTerm);
return Response(users); return Response(users);
} }

View File

@ -21,7 +21,7 @@ public sealed class GetAllUsersTestFixture : QueryHandlerBaseFixture
Handler = new GetAllUsersQueryHandler(UserRepository); Handler = new GetAllUsersQueryHandler(UserRepository);
} }
public void SetupUserAsync() public User SetupUserAsync()
{ {
var user = new User( var user = new User(
ExistingUserId, ExistingUserId,
@ -35,6 +35,8 @@ public sealed class GetAllUsersTestFixture : QueryHandlerBaseFixture
var query = new[] { user }.BuildMock(); var query = new[] { user }.BuildMock();
UserRepository.GetAllNoTracking().Returns(query); UserRepository.GetAllNoTracking().Returns(query);
return user;
} }
public void SetupDeletedUserAsync() public void SetupDeletedUserAsync()

View File

@ -2,6 +2,7 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using CleanArchitecture.Application.Queries.Tenants.GetAll; using CleanArchitecture.Application.Queries.Tenants.GetAll;
using CleanArchitecture.Application.Tests.Fixtures.Queries.Tenants; using CleanArchitecture.Application.Tests.Fixtures.Queries.Tenants;
using CleanArchitecture.Application.ViewModels;
using FluentAssertions; using FluentAssertions;
using Xunit; using Xunit;
@ -16,13 +17,23 @@ public sealed class GetAllTenantsQueryHandlerTests
{ {
var tenant = _fixture.SetupTenant(); var tenant = _fixture.SetupTenant();
var query = new PageQuery
{
PageSize = 10,
Page = 1
};
var result = await _fixture.QueryHandler.Handle( var result = await _fixture.QueryHandler.Handle(
new GetAllTenantsQuery(), new GetAllTenantsQuery(query),
default); default);
_fixture.VerifyNoDomainNotification(); _fixture.VerifyNoDomainNotification();
tenant.Should().BeEquivalentTo(result.First()); result.PageSize.Should().Be(query.PageSize);
result.Page.Should().Be(query.Page);
result.Count.Should().Be(1);
tenant.Should().BeEquivalentTo(result.Items.First());
} }
[Fact] [Fact]
@ -30,10 +41,20 @@ public sealed class GetAllTenantsQueryHandlerTests
{ {
_fixture.SetupTenant(true); _fixture.SetupTenant(true);
var query = new PageQuery
{
PageSize = 10,
Page = 1
};
var result = await _fixture.QueryHandler.Handle( var result = await _fixture.QueryHandler.Handle(
new GetAllTenantsQuery(), new GetAllTenantsQuery(query),
default); default);
result.Should().HaveCount(0); result.PageSize.Should().Be(query.PageSize);
result.Page.Should().Be(query.Page);
result.Count.Should().Be(0);
result.Items.Should().HaveCount(0);
} }
} }

View File

@ -2,6 +2,7 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using CleanArchitecture.Application.Queries.Users.GetAll; using CleanArchitecture.Application.Queries.Users.GetAll;
using CleanArchitecture.Application.Tests.Fixtures.Queries.Users; using CleanArchitecture.Application.Tests.Fixtures.Queries.Users;
using CleanArchitecture.Application.ViewModels;
using FluentAssertions; using FluentAssertions;
using Xunit; using Xunit;
@ -14,15 +15,25 @@ public sealed class GetAllUsersQueryHandlerTests
[Fact] [Fact]
public async Task Should_Get_All_Users() public async Task Should_Get_All_Users()
{ {
_fixture.SetupUserAsync(); var user = _fixture.SetupUserAsync();
var query = new PageQuery
{
PageSize = 1,
Page = 1
};
var result = await _fixture.Handler.Handle( var result = await _fixture.Handler.Handle(
new GetAllUsersQuery(), new GetAllUsersQuery(query, user.Email),
default); default);
_fixture.VerifyNoDomainNotification(); _fixture.VerifyNoDomainNotification();
var userViewModels = result.ToArray(); result.PageSize.Should().Be(query.PageSize);
result.Page.Should().Be(query.Page);
result.Count.Should().Be(1);
var userViewModels = result.Items.ToArray();
userViewModels.Should().NotBeNull(); userViewModels.Should().NotBeNull();
userViewModels.Should().ContainSingle(); userViewModels.Should().ContainSingle();
userViewModels.FirstOrDefault()!.Id.Should().Be(_fixture.ExistingUserId); userViewModels.FirstOrDefault()!.Id.Should().Be(_fixture.ExistingUserId);
@ -33,12 +44,22 @@ public sealed class GetAllUsersQueryHandlerTests
{ {
_fixture.SetupDeletedUserAsync(); _fixture.SetupDeletedUserAsync();
var query = new PageQuery
{
PageSize = 10,
Page = 1
};
var result = await _fixture.Handler.Handle( var result = await _fixture.Handler.Handle(
new GetAllUsersQuery(), new GetAllUsersQuery(query),
default); default);
_fixture.VerifyNoDomainNotification(); _fixture.VerifyNoDomainNotification();
result.Should().BeEmpty(); result.PageSize.Should().Be(query.PageSize);
result.Page.Should().Be(query.Page);
result.Count.Should().Be(0);
result.Items.Should().BeEmpty();
} }
} }

View File

@ -1,10 +1,10 @@
using System.Collections.Generic;
using CleanArchitecture.Application.Interfaces; using CleanArchitecture.Application.Interfaces;
using CleanArchitecture.Application.Queries.Tenants.GetAll; using CleanArchitecture.Application.Queries.Tenants.GetAll;
using CleanArchitecture.Application.Queries.Tenants.GetTenantById; using CleanArchitecture.Application.Queries.Tenants.GetTenantById;
using CleanArchitecture.Application.Queries.Users.GetAll; using CleanArchitecture.Application.Queries.Users.GetAll;
using CleanArchitecture.Application.Queries.Users.GetUserById; using CleanArchitecture.Application.Queries.Users.GetUserById;
using CleanArchitecture.Application.Services; using CleanArchitecture.Application.Services;
using CleanArchitecture.Application.ViewModels;
using CleanArchitecture.Application.ViewModels.Tenants; using CleanArchitecture.Application.ViewModels.Tenants;
using CleanArchitecture.Application.ViewModels.Users; using CleanArchitecture.Application.ViewModels.Users;
using MediatR; using MediatR;
@ -26,12 +26,12 @@ public static class ServiceCollectionExtension
{ {
// User // User
services.AddScoped<IRequestHandler<GetUserByIdQuery, UserViewModel?>, GetUserByIdQueryHandler>(); services.AddScoped<IRequestHandler<GetUserByIdQuery, UserViewModel?>, GetUserByIdQueryHandler>();
services.AddScoped<IRequestHandler<GetAllUsersQuery, IEnumerable<UserViewModel>>, GetAllUsersQueryHandler>(); services.AddScoped<IRequestHandler<GetAllUsersQuery, PagedResult<UserViewModel>>, GetAllUsersQueryHandler>();
// Tenant // Tenant
services.AddScoped<IRequestHandler<GetTenantByIdQuery, TenantViewModel?>, GetTenantByIdQueryHandler>(); services.AddScoped<IRequestHandler<GetTenantByIdQuery, TenantViewModel?>, GetTenantByIdQueryHandler>();
services services
.AddScoped<IRequestHandler<GetAllTenantsQuery, IEnumerable<TenantViewModel>>, GetAllTenantsQueryHandler>(); .AddScoped<IRequestHandler<GetAllTenantsQuery, PagedResult<TenantViewModel>>, GetAllTenantsQueryHandler>();
return services; return services;
} }

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using CleanArchitecture.Application.ViewModels;
using CleanArchitecture.Application.ViewModels.Tenants; using CleanArchitecture.Application.ViewModels.Tenants;
namespace CleanArchitecture.Application.Interfaces; namespace CleanArchitecture.Application.Interfaces;
@ -11,5 +12,5 @@ public interface ITenantService
public Task UpdateTenantAsync(UpdateTenantViewModel tenant); public Task UpdateTenantAsync(UpdateTenantViewModel tenant);
public Task DeleteTenantAsync(Guid tenantId); public Task DeleteTenantAsync(Guid tenantId);
public Task<TenantViewModel?> GetTenantByIdAsync(Guid tenantId, bool deleted); public Task<TenantViewModel?> GetTenantByIdAsync(Guid tenantId, bool deleted);
public Task<IEnumerable<TenantViewModel>> GetAllTenantsAsync(); public Task<PagedResult<TenantViewModel>> GetAllTenantsAsync(PageQuery query, string searchTerm = "");
} }

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using CleanArchitecture.Application.ViewModels;
using CleanArchitecture.Application.ViewModels.Users; using CleanArchitecture.Application.ViewModels.Users;
namespace CleanArchitecture.Application.Interfaces; namespace CleanArchitecture.Application.Interfaces;
@ -9,7 +10,7 @@ public interface IUserService
{ {
public Task<UserViewModel?> GetUserByUserIdAsync(Guid userId, bool isDeleted); public Task<UserViewModel?> GetUserByUserIdAsync(Guid userId, bool isDeleted);
public Task<UserViewModel?> GetCurrentUserAsync(); public Task<UserViewModel?> GetCurrentUserAsync();
public Task<IEnumerable<UserViewModel>> GetAllUsersAsync(); public Task<PagedResult<UserViewModel>> GetAllUsersAsync(PageQuery query, string searchTerm = "");
public Task<Guid> CreateUserAsync(CreateUserViewModel user); public Task<Guid> CreateUserAsync(CreateUserViewModel user);
public Task UpdateUserAsync(UpdateUserViewModel user); public Task UpdateUserAsync(UpdateUserViewModel user);
public Task DeleteUserAsync(Guid userId); public Task DeleteUserAsync(Guid userId);

View File

@ -1,7 +1,8 @@
using System.Collections.Generic; using CleanArchitecture.Application.ViewModels;
using CleanArchitecture.Application.ViewModels.Tenants; using CleanArchitecture.Application.ViewModels.Tenants;
using MediatR; using MediatR;
namespace CleanArchitecture.Application.Queries.Tenants.GetAll; namespace CleanArchitecture.Application.Queries.Tenants.GetAll;
public sealed record GetAllTenantsQuery : IRequest<IEnumerable<TenantViewModel>>; public sealed record GetAllTenantsQuery(PageQuery Query, string SearchTerm = "") :
IRequest<PagedResult<TenantViewModel>>;

View File

@ -1,7 +1,7 @@
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using CleanArchitecture.Application.ViewModels;
using CleanArchitecture.Application.ViewModels.Tenants; using CleanArchitecture.Application.ViewModels.Tenants;
using CleanArchitecture.Domain.Interfaces.Repositories; using CleanArchitecture.Domain.Interfaces.Repositories;
using MediatR; using MediatR;
@ -10,7 +10,7 @@ using Microsoft.EntityFrameworkCore;
namespace CleanArchitecture.Application.Queries.Tenants.GetAll; namespace CleanArchitecture.Application.Queries.Tenants.GetAll;
public sealed class GetAllTenantsQueryHandler : public sealed class GetAllTenantsQueryHandler :
IRequestHandler<GetAllTenantsQuery, IEnumerable<TenantViewModel>> IRequestHandler<GetAllTenantsQuery, PagedResult<TenantViewModel>>
{ {
private readonly ITenantRepository _tenantRepository; private readonly ITenantRepository _tenantRepository;
@ -19,15 +19,30 @@ public sealed class GetAllTenantsQueryHandler :
_tenantRepository = tenantRepository; _tenantRepository = tenantRepository;
} }
public async Task<IEnumerable<TenantViewModel>> Handle( public async Task<PagedResult<TenantViewModel>> Handle(
GetAllTenantsQuery request, GetAllTenantsQuery request,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
return await _tenantRepository var tenantsQuery = _tenantRepository
.GetAllNoTracking() .GetAllNoTracking()
.Include(x => x.Users) .Include(x => x.Users)
.Where(x => !x.Deleted) .Where(x => !x.Deleted);
.Select(x => TenantViewModel.FromTenant(x))
if (!string.IsNullOrWhiteSpace(request.SearchTerm))
{
tenantsQuery = tenantsQuery.Where(tenant =>
tenant.Name.Contains(request.SearchTerm));
}
var totalCount = await tenantsQuery.CountAsync(cancellationToken);
var tenants = await tenantsQuery
.Skip((request.Query.Page - 1) * request.Query.PageSize)
.Take(request.Query.PageSize)
.Select(tenant => TenantViewModel.FromTenant(tenant))
.ToListAsync(cancellationToken); .ToListAsync(cancellationToken);
return new PagedResult<TenantViewModel>(
totalCount, tenants, request.Query.Page, request.Query.PageSize);
} }
} }

View File

@ -1,7 +1,8 @@
using System.Collections.Generic; using CleanArchitecture.Application.ViewModels;
using CleanArchitecture.Application.ViewModels.Users; using CleanArchitecture.Application.ViewModels.Users;
using MediatR; using MediatR;
namespace CleanArchitecture.Application.Queries.Users.GetAll; namespace CleanArchitecture.Application.Queries.Users.GetAll;
public sealed record GetAllUsersQuery : IRequest<IEnumerable<UserViewModel>>; public sealed record GetAllUsersQuery(PageQuery Query, string SearchTerm = "") :
IRequest<PagedResult<UserViewModel>>;

View File

@ -1,7 +1,7 @@
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using CleanArchitecture.Application.ViewModels;
using CleanArchitecture.Application.ViewModels.Users; using CleanArchitecture.Application.ViewModels.Users;
using CleanArchitecture.Domain.Interfaces.Repositories; using CleanArchitecture.Domain.Interfaces.Repositories;
using MediatR; using MediatR;
@ -10,7 +10,7 @@ using Microsoft.EntityFrameworkCore;
namespace CleanArchitecture.Application.Queries.Users.GetAll; namespace CleanArchitecture.Application.Queries.Users.GetAll;
public sealed class GetAllUsersQueryHandler : public sealed class GetAllUsersQueryHandler :
IRequestHandler<GetAllUsersQuery, IEnumerable<UserViewModel>> IRequestHandler<GetAllUsersQuery, PagedResult<UserViewModel>>
{ {
private readonly IUserRepository _userRepository; private readonly IUserRepository _userRepository;
@ -19,12 +19,31 @@ public sealed class GetAllUsersQueryHandler :
_userRepository = userRepository; _userRepository = userRepository;
} }
public async Task<IEnumerable<UserViewModel>> Handle(GetAllUsersQuery request, CancellationToken cancellationToken) public async Task<PagedResult<UserViewModel>> Handle(
GetAllUsersQuery request,
CancellationToken cancellationToken)
{ {
return await _userRepository var usersQuery = _userRepository
.GetAllNoTracking() .GetAllNoTracking()
.Where(x => !x.Deleted) .Where(x => !x.Deleted);
.Select(x => UserViewModel.FromUser(x))
if (!string.IsNullOrWhiteSpace(request.SearchTerm))
{
usersQuery = usersQuery.Where(user =>
user.Email.Contains(request.SearchTerm) ||
user.FirstName.Contains(request.SearchTerm) ||
user.LastName.Contains(request.SearchTerm));
}
var totalCount = await usersQuery.CountAsync(cancellationToken);
var users = await usersQuery
.Skip((request.Query.Page - 1) * request.Query.PageSize)
.Take(request.Query.PageSize)
.Select(user => UserViewModel.FromUser(user))
.ToListAsync(cancellationToken); .ToListAsync(cancellationToken);
return new PagedResult<UserViewModel>(
totalCount, users, request.Query.Page, request.Query.PageSize);
} }
} }

View File

@ -4,6 +4,7 @@ using System.Threading.Tasks;
using CleanArchitecture.Application.Interfaces; using CleanArchitecture.Application.Interfaces;
using CleanArchitecture.Application.Queries.Tenants.GetAll; using CleanArchitecture.Application.Queries.Tenants.GetAll;
using CleanArchitecture.Application.Queries.Tenants.GetTenantById; using CleanArchitecture.Application.Queries.Tenants.GetTenantById;
using CleanArchitecture.Application.ViewModels;
using CleanArchitecture.Application.ViewModels.Tenants; using CleanArchitecture.Application.ViewModels.Tenants;
using CleanArchitecture.Domain.Commands.Tenants.CreateTenant; using CleanArchitecture.Domain.Commands.Tenants.CreateTenant;
using CleanArchitecture.Domain.Commands.Tenants.DeleteTenant; using CleanArchitecture.Domain.Commands.Tenants.DeleteTenant;
@ -49,8 +50,8 @@ public sealed class TenantService : ITenantService
return await _bus.QueryAsync(new GetTenantByIdQuery(tenantId, deleted)); return await _bus.QueryAsync(new GetTenantByIdQuery(tenantId, deleted));
} }
public async Task<IEnumerable<TenantViewModel>> GetAllTenantsAsync() public async Task<PagedResult<TenantViewModel>> GetAllTenantsAsync(PageQuery query, string searchTerm = "")
{ {
return await _bus.QueryAsync(new GetAllTenantsQuery()); return await _bus.QueryAsync(new GetAllTenantsQuery(query, searchTerm));
} }
} }

View File

@ -4,6 +4,7 @@ using System.Threading.Tasks;
using CleanArchitecture.Application.Interfaces; using CleanArchitecture.Application.Interfaces;
using CleanArchitecture.Application.Queries.Users.GetAll; using CleanArchitecture.Application.Queries.Users.GetAll;
using CleanArchitecture.Application.Queries.Users.GetUserById; using CleanArchitecture.Application.Queries.Users.GetUserById;
using CleanArchitecture.Application.ViewModels;
using CleanArchitecture.Application.ViewModels.Users; using CleanArchitecture.Application.ViewModels.Users;
using CleanArchitecture.Domain.Commands.Users.ChangePassword; using CleanArchitecture.Domain.Commands.Users.ChangePassword;
using CleanArchitecture.Domain.Commands.Users.CreateUser; using CleanArchitecture.Domain.Commands.Users.CreateUser;
@ -35,9 +36,9 @@ public sealed class UserService : IUserService
return await _bus.QueryAsync(new GetUserByIdQuery(_user.GetUserId(), false)); return await _bus.QueryAsync(new GetUserByIdQuery(_user.GetUserId(), false));
} }
public async Task<IEnumerable<UserViewModel>> GetAllUsersAsync() public async Task<PagedResult<UserViewModel>> GetAllUsersAsync(PageQuery query, string searchTerm = "")
{ {
return await _bus.QueryAsync(new GetAllUsersQuery()); return await _bus.QueryAsync(new GetAllUsersQuery(query, searchTerm));
} }
public async Task<Guid> CreateUserAsync(CreateUserViewModel user) public async Task<Guid> CreateUserAsync(CreateUserViewModel user)

View File

@ -0,0 +1,20 @@
using System;
namespace CleanArchitecture.Application.ViewModels;
public sealed class PageQuery
{
private int _pageSize = 10;
public int PageSize
{
get => _pageSize;
set => _pageSize = Math.Max(0, value);
}
private int _page = 1;
public int Page
{
get => _page;
set => _page = Math.Max(1, value);
}
}

View File

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
namespace CleanArchitecture.Application.ViewModels;
public sealed class PagedResult<T>
{
public int Count { get; init; }
public IList<T> Items { get; init; } = Array.Empty<T>();
public int Page { get; init; }
public int PageSize { get; init; }
public PagedResult(int count, IList<T> items, int page, int pageSize)
{
Count = count;
Items = items;
Page = page;
PageSize = pageSize;
}
// used by json deserializer
private PagedResult()
{
}
public static PagedResult<T> Empty()
{
return new PagedResult<T>
{
Count = 0,
Items = Array.Empty<T>(),
Page = 1,
PageSize = 10
};
}
}

View File

@ -1,8 +1,8 @@
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Threading.Tasks; using System.Threading.Tasks;
using CleanArchitecture.Application.ViewModels;
using CleanArchitecture.Application.ViewModels.Tenants; using CleanArchitecture.Application.ViewModels.Tenants;
using CleanArchitecture.IntegrationTests.Extensions; using CleanArchitecture.IntegrationTests.Extensions;
using CleanArchitecture.IntegrationTests.Fixtures; using CleanArchitecture.IntegrationTests.Fixtures;
@ -43,15 +43,16 @@ public sealed class TenantControllerTests : IClassFixture<TenantTestFixture>
[Priority(5)] [Priority(5)]
public async Task Should_Get_All_Tenants() public async Task Should_Get_All_Tenants()
{ {
var response = await _fixture.ServerClient.GetAsync("api/v1/Tenant"); var response = await _fixture.ServerClient.GetAsync(
"api/v1/Tenant?searchTerm=Test&pageSize=5&page=1");
response.StatusCode.Should().Be(HttpStatusCode.OK); response.StatusCode.Should().Be(HttpStatusCode.OK);
var message = await response.Content.ReadAsJsonAsync<IEnumerable<TenantViewModel>>(); var message = await response.Content.ReadAsJsonAsync<PagedResult<TenantViewModel>>();
message?.Data.Should().NotBeEmpty(); message?.Data!.Items.Should().NotBeEmpty();
message!.Data.Should().HaveCountGreaterOrEqualTo(2); message!.Data!.Items.Should().HaveCount(1);
message.Data! message.Data!.Items
.FirstOrDefault(x => x.Id == _fixture.CreatedTenantId) .FirstOrDefault(x => x.Id == _fixture.CreatedTenantId)
.Should().NotBeNull(); .Should().NotBeNull();
} }

View File

@ -1,8 +1,8 @@
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Threading.Tasks; using System.Threading.Tasks;
using CleanArchitecture.Application.ViewModels;
using CleanArchitecture.Application.ViewModels.Users; using CleanArchitecture.Application.ViewModels.Users;
using CleanArchitecture.Domain.Constants; using CleanArchitecture.Domain.Constants;
using CleanArchitecture.Domain.Enums; using CleanArchitecture.Domain.Enums;
@ -34,11 +34,11 @@ public sealed class UserControllerTests : IClassFixture<UserTestFixture>
response.StatusCode.Should().Be(HttpStatusCode.OK); response.StatusCode.Should().Be(HttpStatusCode.OK);
var message = await response.Content.ReadAsJsonAsync<IEnumerable<UserViewModel>>(); var message = await response.Content.ReadAsJsonAsync<PagedResult<UserViewModel>>();
message?.Data.Should().NotBeNull(); message?.Data.Should().NotBeNull();
var content = message!.Data!.ToList(); var content = message!.Data!.Items.ToList();
content.Count.Should().Be(2); content.Count.Should().Be(2);