C#Bot Release


Dockerised Integration Tests

Added support for dockerised tests using the Test Containers library. This allows integration tests such as selenium to run with their own isolated databases.

  • This is implemented using the Testcontainers library.
  • Each test written with this test suite will start their own isolated environment. This environment will contain a Postgres and Redis database as well as a Minio server for file storage.
  • To run these tests, Docker will need to be installed and running on the computer executing the tests, with docker in docker enabled.

Serverside Test Server

Added ability to run fake API tests from the serverside test framework.

Computed GraphQL Query Fields

Added ability to create custom fields on entities that can be filtered and sorted on.

For example, the following code block will add a computed field called fullName on a user that is a concatenation of their first and last names.

// Create a computed field that will concat a users first and last name with a space in the middle
// The first generic argument is the type of the field you want to add a computed function for
// The second generic argument is the type of the computed value.
ReflectionCache.AddComputedFieldMapping<UserEntity, string>("fullName", user => user.FirstName + " " + user.LastName);

If you are feeling masochistic this can be done with expression builder code as well. The follow code block will produce the same results as above.

var stringConcat3 = typeof(string).GetMethod(
    new [] { typeof(string), typeof(string), typeof(string) });

var param = Expression.Parameter(typeof(UserEntity));
var func = Expression.Lambda(
        Expression.PropertyOrField(param, nameof(UserEntity.FirstName)),
        Expression.Constant(" "),
        Expression.PropertyOrField(param, nameof(UserEntity.LastName))),

ReflectionCache.AddComputedFieldMapping("fullName", typeof(UserEntity), func);

This can be used in the where and order by segments of a GraphQL query. It is important to note that if you want to retrieve the computed field, you would need to add a custom field resolver in the appropriate entity type file.

query getUsers {
        where: [{path: "fullName", comparison: equal, "John Smith"}],
        orderBy: [{path: "fullName"}],
        take: 10
    ) {

Bonus Chatter

This feature does not have to only be used on entities, you can make a computed field on any type. For example:

AddComputedFieldMapping<string, string>("uppercase", str => str.ToUpper());

And computed fields can be applied to other computed fields. For example, using both the fields from this example.

[{path: "fullName.uppercase", comparison: equal, "JOHN SMITH"}]


  • Improved SQL query caching for all bot written graphql resolvers.
  • Moved password strength configuration to appsettings.
  • Weather the development clientside is used is now based off of an appsetting instead of being only in development mode.
  • Added ability to filter users via user groups.

Resolved Defects

  • Fixed an issue where reset password tests were generated for non user entities.
  • Fixed an issue where security on has conditions would fail with certain security rules.

Migration Path

Moved Protected Regions

In this release some protected regions have been moved or replaced according to the table below.

FileName: testtarget/Serverside/Helpers/ServerBuilder.cs
Protected Region: Configure Services here
Replacement This protected region has been replaced with several smaller ones inside the same file.

FileName: testtarget/API/Setup/StartupTestFixture.cs
Protected Region: All protected regions in the constructor
Replacement The constructor for this class has been removed and split into several functions. Each of these functions has protected regions surrounding them.

Password configuration

In this release, password strength configuration has been moved. Previously the this was done in Startup.cs in the Configure password requirements here protected region. This configuration has now been moved to appsettings.xml and appsettings.Development.xml.