Skip to content

Commit

Permalink
Improved test suite
Browse files Browse the repository at this point in the history
  • Loading branch information
Somfic committed Aug 7, 2023
1 parent a7bcce9 commit af061aa
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 7 deletions.
2 changes: 1 addition & 1 deletion EliteAPI.Abstractions/Events/IEvents.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public interface IEvents
IReadOnlyCollection<(IEvent @event, EventContext context)> Backlog { get; }

/// <summary>All event types that have been registered.</summary>
IEnumerable<Type> EventTypes { get; }
IReadOnlyCollection<Type> EventTypes { get; }

/// <summary>A collection of previous events since the API was started.</summary>
IReadOnlyCollection<(IEvent @event, EventContext context)> PreviousEvents { get; }
Expand Down
114 changes: 114 additions & 0 deletions EliteAPI.Tests/Conventions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
using System.Collections.Immutable;
using System.Diagnostics;
using System.Reflection;
using System.Xml;
using EliteAPI.Abstractions.Bindings;
using EliteAPI.Abstractions.Bindings.Models;
using EliteAPI.Abstractions.Events;
using EliteAPI.Bindings;
using EliteAPI.Events;
using Microsoft.Extensions.Logging;
using Moq;

namespace EliteAPI.Tests;

[TestFixture]
public class Convetions
{
[Test(Description = "Event types")]
[TestCaseSource(nameof(GetTypes))]
public void Events(Type type)
{
// Namespace should be EliteAPI.Events
Assert.That(type.Namespace!.StartsWith("EliteAPI.Events"),
$"Type {type.Name} should be in namespace EliteAPI.Events");

// Name should not have underscores
Assert.That(!type.Name.Contains("_"),
$"Type {type.Name} should not contain underscores");

// Name should be PascalCase
Assert.That(char.IsUpper(type.Name[0]),
$"Type {type.Name} should start with a capital letter");

// Should be a struct
Assert.That(type.IsValueType,
$"Type {type.Name} should be a struct");

// Should implement IEvent
Assert.That(type.GetInterfaces().Contains(typeof(IEvent)),
$"Type {type.Name} should implement IEvent");
}

[Test(Description = "Properties")]
[TestCaseSource(nameof(GetProperties))]
public void Properties(PropertyInfo property)
{
var name = property.DeclaringType!.Name + "." + property.Name;

// Namespace should be EliteAPI.Events
Assert.That(property.DeclaringType!.Namespace!.StartsWith("EliteAPI.Events"),
$"Property {name} should be in namespace EliteAPI.Events");

// Name should not have underscores
Assert.That(!property.Name.Contains("_"),
$"Property {name} should not contain underscores");

// Name should be PascalCase
Assert.That(char.IsUpper(property.Name[0]),
$"Property {name} should start with a capital letter");

// Name should not be too long
Assert.That(property.Name.Length <= 32,
$"Property {name} should not be longer than 32 characters");

if (property.PropertyType == typeof(float) || property.PropertyType == typeof(decimal))
{
// Property should be of type double
Assert.That(property.PropertyType == typeof(double),
$"Property {name} should be of type double");
}

if (property.PropertyType == typeof(bool) && !property.DeclaringType.Namespace.StartsWith("EliteAPI.Events.Status"))
{
// Property should be named IsX or HasX or WasX
var prefixes = new[] {"Is", "Has", "Was", "Allows", "Can", "Should"};
Assert.That(prefixes.Any(x => property.Name.StartsWith(x)),
$"Property {name} should start with {string.Join(" or ", prefixes)}");
}
}

static IImmutableList<PropertyInfo> GetProperties()
{
var eventParser = new EventParser(Mock.Of<IServiceProvider>());
eventParser.Use<LocalisedConverter>();;
var events = new Events.Events(Mock.Of<ILogger<Events.Events>>(), eventParser);
events.Register();

var properties = new List<PropertyInfo>();

if(events == null)
throw new Exception("Events not initialized");

foreach (var eventType in events.EventTypes)
{
properties.AddRange(eventType.GetProperties());
}

return properties.ToImmutableList();
}

static IImmutableList<Type> GetTypes()
{
var eventParser = new EventParser(Mock.Of<IServiceProvider>());
eventParser.Use<LocalisedConverter>();
;
var events = new Events.Events(Mock.Of<ILogger<Events.Events>>(), eventParser);
events.Register();

if (events == null)
throw new Exception("Events not initialized");

return events.EventTypes.ToImmutableList();
}
}
17 changes: 14 additions & 3 deletions EliteAPI.Tests/JournalManual.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@ namespace EliteAPI.Tests;
public class JournalManual
{
private static IEvents _events;
private static string[] _legacyEvents = { "BackpackMaterials", "BuyMicroResources", "ShipTargetted" };
private static string[] _legacyEvents = { "BackpackMaterials", "BuyMicroResources", "ShipTargetted", "CarrierNameChanged" };
private static string[] _legacyExamples =
{
"\"timestamp\":\"2020-04-27T08:02:52Z\", \"event\":\"Route\"",
"\"timestamp\":\"2020-04-27T08:02:52Z\", \"event\":\"Route\""
"\"timestamp\":\"2020-04-27T08:02:52Z\", \"event\":\"Route\"",
"\"timestamp\":\"2020-10-07T14:01:08Z\", \"event\":\"BuyMicroResource\"",
};

[OneTimeSetUp]
Expand Down Expand Up @@ -66,7 +67,17 @@ public void Json(string json)
return;
}

_events.Invoke(json, new EventContext());
var invokedEvent = _events.Invoke(json, new EventContext());

Assert.That(invokedEvent, Is.Not.Null, $"Event is null");

// Check if the event is the correct type
var eventType = invokedEvent.GetType();
var eventName = eventType.Name;
if (eventName.EndsWith("Event"))
eventName = eventName.Substring(0, eventName.Length - 5);

Assert.That(string.Equals(eventName, invokedEvent.Event, StringComparison.CurrentCultureIgnoreCase), $"Event is not of type {eventName} but {invokedEvent.Event}");
}

[Test(Description = "Properties")]
Expand Down
5 changes: 3 additions & 2 deletions EliteAPI.Tests/Schemas.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public void Setup()

[Test(Description = "Properties")]
[TestCaseSource(nameof(GetProperties))]
[Ignore("Tests are being worked on")]
public void Properties((string name, string type) schemaInfo)
{
var eventName = schemaInfo.name.Split('.')[0] + "Event";
Expand Down Expand Up @@ -58,7 +59,7 @@ public void Properties((string name, string type) schemaInfo)
.Where(x => x.GetCustomAttributes<JsonPropertyAttribute>().Any());

var jsonProperty =
properties.FirstOrDefault(x => x.GetCustomAttribute<JsonPropertyAttribute>()!.PropertyName == name);
properties.FirstOrDefault(x => string.Equals(x.GetCustomAttribute<JsonPropertyAttribute>()!.PropertyName, name, StringComparison.InvariantCultureIgnoreCase));
Assert.That(jsonProperty, Is.Not.Null, $"Property {name} not found on event {eventName}");

var jsonPropertyType = jsonProperty!.PropertyType;
Expand Down Expand Up @@ -115,7 +116,7 @@ public void Event((string name, string schema) schemaInfo)
if(name.EndsWith("_Localised"))
continue;

if(name.EndsWith("ID") || name.EndsWith("Address"))
if(name.EndsWith("ID") || name.EndsWith("Address") || name.EndsWith("Market"))
type = "string";

var propertyName = (namePrefix + "." + name).TrimStart('.').TrimEnd('.').Replace("..", ".");
Expand Down
3 changes: 3 additions & 0 deletions EliteAPI/EliteAPI.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion EliteAPI/Events/Events.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public Events(ILogger<Events>? log, IEventParser eventParser)
}

/// <inheritdoc />
public IEnumerable<Type> EventTypes => _eventHandlers.Keys;
public IReadOnlyCollection<Type> EventTypes => _eventHandlers.Keys;

/// <inheritdoc />
public IReadOnlyCollection<(IEvent @event, EventContext context)> PreviousEvents => _previousEvents.AsReadOnly();
Expand Down

0 comments on commit af061aa

Please sign in to comment.