Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.11" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageReference Include="Testcontainers.MsSql" Version="4.14.0" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\AccountOwnerServer\AccountOwnerServer.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using Entities.Helpers;
using Entities.Models;
using System.Linq;
using Xunit;

namespace AccountOwnerServer.Tests;

public class DataShaperTests
{
private static readonly DataShaper<Owner> Shaper = new();

[Fact]
public void GivenNoFields_WhenWeShape_ThenEveryPropertyIsKept()
{
var shaped = Shaper.ShapeData(SqlServerSample.Owners().First(), null);

Assert.Equal(4, shaped.Count);
Assert.True(shaped.ContainsKey(nameof(Owner.Address)));
}

[Fact]
public void GivenASubsetOfFields_WhenWeShape_ThenOnlyThoseComeBack()
{
var shaped = Shaper.ShapeData(SqlServerSample.Owners().First(), "name,dateOfBirth");

Assert.Equal(2, shaped.Count);
Assert.True(shaped.ContainsKey(nameof(Owner.Name)));
Assert.False(shaped.ContainsKey(nameof(Owner.Address)));
}

[Fact]
public void GivenAFieldInAnyCasing_WhenWeShape_ThenItStillMatchesThePropertyName()
{
var shaped = Shaper.ShapeData(SqlServerSample.Owners().First(), "NAME");

Assert.True(shaped.ContainsKey(nameof(Owner.Name)));
}

[Fact]
public void GivenAnUnknownField_WhenWeShape_ThenItIsIgnored()
{
var shaped = Shaper.ShapeData(SqlServerSample.Owners().First(), "name,age");

Assert.Single(shaped);
Assert.True(shaped.ContainsKey(nameof(Owner.Name)));
}

[Fact]
public void GivenACollection_WhenWeShape_ThenEveryEntityIsShaped()
{
var shaped = Shaper.ShapeData(SqlServerSample.Owners(), "name").ToList();

Assert.Equal(5, shaped.Count);
Assert.All(shaped, s => Assert.Single(s));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using Entities.Models;
using Xunit;

namespace AccountOwnerServer.Tests;

public class OwnerParametersTests
{
[Fact]
public void GivenTheSameMinAndMaxYear_WhenTheRangeIsValidated_ThenItIsAccepted()
{
var parameters = new OwnerParameters { MinYearOfBirth = 1990, MaxYearOfBirth = 1990 };

Assert.True(parameters.ValidYearRange);
}

[Fact]
public void GivenAMaxYearBelowTheMinYear_WhenTheRangeIsValidated_ThenItIsRejected()
{
var parameters = new OwnerParameters { MinYearOfBirth = 1975, MaxYearOfBirth = 1974 };

Assert.False(parameters.ValidYearRange);
}

[Fact]
public void GivenNoYearsAtAll_WhenTheRangeIsValidated_ThenItIsAccepted()
{
var parameters = new OwnerParameters();

Assert.Null(parameters.MinYearOfBirth);
Assert.Null(parameters.MaxYearOfBirth);
Assert.True(parameters.ValidYearRange);
}

[Fact]
public void GivenOnlyAMinYear_WhenTheRangeIsValidated_ThenItIsAccepted()
{
var parameters = new OwnerParameters { MinYearOfBirth = 1975 };

Assert.True(parameters.ValidYearRange);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
using Entities.Helpers;
using Entities.Models;
using Repository;
using System;
using System.Linq;
using System.Threading.Tasks;
using Xunit;

namespace AccountOwnerServer.Tests;

/// <summary>
/// These run against a real SQL Server started by Testcontainers. They are skipped unless
/// CODEMAZE_SQLSERVER_TESTS=1 is set, because the SQL Server image is not guaranteed to be
/// available on every machine or CI runner.
/// </summary>
public class OwnerRepositorySqlServerTests
{
[SqlServerFact]
public async Task GivenAPageSizeOfTwo_WhenWeAskForTheSecondPage_ThenWeGetTwoOwnersAndTheRightMetadata()
{
await using var sample = await SqlServerSample.StartAsync();
await using var context = sample.CreateContext();

var repository = new OwnerRepository(context, new SortHelper<Owner>(), new DataShaper<Owner>());

var owners = await repository.GetOwners(new OwnerParameters { PageNumber = 2, PageSize = 2 });

Assert.Equal(2, owners.Count);
Assert.Equal(5, owners.TotalCount);
Assert.Equal(3, owners.TotalPages);
Assert.True(owners.HasPrevious);
Assert.True(owners.HasNext);
}

[SqlServerFact]
public async Task GivenTheSameMinAndMaxYear_WhenWeFilter_ThenTheOwnerBornInThatYearComesBack()
{
await using var sample = await SqlServerSample.StartAsync();
await using var context = sample.CreateContext();

var repository = new OwnerRepository(context, new SortHelper<Owner>(), new DataShaper<Owner>());

var owners = await repository.GetOwners(new OwnerParameters
{
MinYearOfBirth = 1990,
MaxYearOfBirth = 1990
});

Assert.Equal(1, owners.TotalCount);
Assert.Equal("Sam Query", NameOf(owners.Single()));
}

[SqlServerFact]
public async Task GivenOnlyAMinimumYear_WhenWeFilter_ThenTheUpperBoundIsOpen()
{
await using var sample = await SqlServerSample.StartAsync();
await using var context = sample.CreateContext();

var repository = new OwnerRepository(context, new SortHelper<Owner>(), new DataShaper<Owner>());

var owners = await repository.GetOwners(new OwnerParameters { MinYearOfBirth = 1990 });

Assert.Equal(2, owners.TotalCount);
}

[SqlServerFact]
public async Task GivenALowerCaseSearchTerm_WhenWeSearch_ThenTheDefaultCollationStillMatches()
{
await using var sample = await SqlServerSample.StartAsync();
await using var context = sample.CreateContext();

var repository = new OwnerRepository(context, new SortHelper<Owner>(), new DataShaper<Owner>());

var owners = await repository.GetOwners(new OwnerParameters { SearchTerm = "anna" });

Assert.Equal(1, owners.TotalCount);
Assert.Equal("Anna Bosh", NameOf(owners.Single()));
}

[SqlServerFact]
public async Task GivenAnUnknownOrderByField_WhenWeQuery_ThenThePageIsStillOrderedRatherThanFailing()
{
await using var sample = await SqlServerSample.StartAsync();
await using var context = sample.CreateContext();

var repository = new OwnerRepository(context, new SortHelper<Owner>(), new DataShaper<Owner>());

var owners = await repository.GetOwners(new OwnerParameters { OrderBy = "age" });

Assert.Equal(5, owners.TotalCount);
Assert.Equal("Anna Bosh", NameOf(owners.First()));
}

[SqlServerFact]
public async Task GivenAnUpperCaseDescToken_WhenWeQuery_ThenTheOrderIsDescending()
{
await using var sample = await SqlServerSample.StartAsync();
await using var context = sample.CreateContext();

var repository = new OwnerRepository(context, new SortHelper<Owner>(), new DataShaper<Owner>());

var owners = await repository.GetOwners(new OwnerParameters { OrderBy = "name DESC" });

Assert.Equal("Sam Query", NameOf(owners.First()));
}

[SqlServerFact]
public async Task GivenFieldsAndAPageSize_WhenWeQuery_ThenOnlyThePageIsShapedAndTheMetadataComesFromTheQuery()
{
await using var sample = await SqlServerSample.StartAsync();
await using var context = sample.CreateContext();

var repository = new OwnerRepository(context, new SortHelper<Owner>(), new DataShaper<Owner>());

var owners = await repository.GetOwners(new OwnerParameters
{
Fields = "name",
PageSize = 2,
PageNumber = 1
});

Assert.Equal(2, owners.Count);
Assert.Equal(5, owners.TotalCount);
Assert.Equal(3, owners.TotalPages);
}

private static string NameOf(Entity owner) => owner[nameof(Owner.Name)].ToString()!;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using Entities.Models;
using Xunit;

namespace AccountOwnerServer.Tests;

public class QueryStringParametersTests
{
[Theory]
[InlineData(0, 1)]
[InlineData(-3, 1)]
[InlineData(2, 2)]
public void GivenAPageNumber_WhenItIsSet_ThenItNeverDropsBelowOne(int requested, int expected)
{
var parameters = new OwnerParameters { PageNumber = requested };

Assert.Equal(expected, parameters.PageNumber);
}

[Theory]
[InlineData(0, 1)]
[InlineData(-10, 1)]
[InlineData(7, 7)]
[InlineData(500, 50)]
public void GivenAPageSize_WhenItIsSet_ThenItIsClampedBetweenOneAndFifty(int requested, int expected)
{
var parameters = new OwnerParameters { PageSize = requested };

Assert.Equal(expected, parameters.PageSize);
}

[Fact]
public void GivenNoQueryString_WhenParametersAreCreated_ThenTheDefaultsAreOneAndTen()
{
var parameters = new OwnerParameters();

Assert.Equal(1, parameters.PageNumber);
Assert.Equal(10, parameters.PageSize);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
using Entities.Models;
using Repository.Extensions;
using System.Linq;
using Xunit;

namespace AccountOwnerServer.Tests;

public class SearchExtensionTests
{
private static IQueryable<Owner> Owners() => SqlServerSample.Owners().AsQueryable();

[Fact]
public void GivenABlankSearchTerm_WhenWeSearch_ThenTheQueryIsReturnedUntouched()
{
var owners = Owners();

Assert.Same(owners, owners.Search(null));
Assert.Same(owners, owners.Search(string.Empty));
Assert.Same(owners, owners.Search(" "));
}

[Fact]
public void GivenANameFragment_WhenWeSearch_ThenTheMatchingOwnerComesBack()
{
var result = Owners().Search("Anna").ToList();

Assert.Single(result);
Assert.Equal("Anna Bosh", result[0].Name);
}

[Fact]
public void GivenAnAddressFragment_WhenWeSearch_ThenTheColumnIsSearchedToo()
{
var result = Owners().Search("Wellfield").ToList();

Assert.Single(result);
Assert.Equal("John Keen", result[0].Name);
}

[Fact]
public void GivenAPaddedSearchTerm_WhenWeSearch_ThenItIsTrimmedBeforeMatching()
{
var result = Owners().Search(" Somion ").ToList();

Assert.Single(result);
Assert.Equal("Nick Somion", result[0].Name);
}
}
Loading
Loading