From af061aa856cb6985d3ae6a12784287040ec1d079 Mon Sep 17 00:00:00 2001
From: Lucas <29230467+Somfic@users.noreply.github.com>
Date: Mon, 7 Aug 2023 17:18:26 +0200
Subject: [PATCH] Improved test suite
---
EliteAPI.Abstractions/Events/IEvents.cs | 2 +-
EliteAPI.Tests/Conventions.cs | 114 ++++++++++++++++++++++++
EliteAPI.Tests/JournalManual.cs | 17 +++-
EliteAPI.Tests/Schemas.cs | 5 +-
EliteAPI/EliteAPI.xml | 3 +
EliteAPI/Events/Events.cs | 2 +-
6 files changed, 136 insertions(+), 7 deletions(-)
create mode 100644 EliteAPI.Tests/Conventions.cs
diff --git a/EliteAPI.Abstractions/Events/IEvents.cs b/EliteAPI.Abstractions/Events/IEvents.cs
index b84df3d3..4f9df52c 100644
--- a/EliteAPI.Abstractions/Events/IEvents.cs
+++ b/EliteAPI.Abstractions/Events/IEvents.cs
@@ -9,7 +9,7 @@ public interface IEvents
IReadOnlyCollection<(IEvent @event, EventContext context)> Backlog { get; }
/// All event types that have been registered.
- IEnumerable EventTypes { get; }
+ IReadOnlyCollection EventTypes { get; }
/// A collection of previous events since the API was started.
IReadOnlyCollection<(IEvent @event, EventContext context)> PreviousEvents { get; }
diff --git a/EliteAPI.Tests/Conventions.cs b/EliteAPI.Tests/Conventions.cs
new file mode 100644
index 00000000..d40c56f9
--- /dev/null
+++ b/EliteAPI.Tests/Conventions.cs
@@ -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 GetProperties()
+ {
+ var eventParser = new EventParser(Mock.Of());
+ eventParser.Use();;
+ var events = new Events.Events(Mock.Of>(), eventParser);
+ events.Register();
+
+ var properties = new List();
+
+ if(events == null)
+ throw new Exception("Events not initialized");
+
+ foreach (var eventType in events.EventTypes)
+ {
+ properties.AddRange(eventType.GetProperties());
+ }
+
+ return properties.ToImmutableList();
+ }
+
+ static IImmutableList GetTypes()
+ {
+ var eventParser = new EventParser(Mock.Of());
+ eventParser.Use();
+ ;
+ var events = new Events.Events(Mock.Of>(), eventParser);
+ events.Register();
+
+ if (events == null)
+ throw new Exception("Events not initialized");
+
+ return events.EventTypes.ToImmutableList();
+ }
+}
\ No newline at end of file
diff --git a/EliteAPI.Tests/JournalManual.cs b/EliteAPI.Tests/JournalManual.cs
index f6cc2a91..054806cc 100644
--- a/EliteAPI.Tests/JournalManual.cs
+++ b/EliteAPI.Tests/JournalManual.cs
@@ -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]
@@ -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")]
diff --git a/EliteAPI.Tests/Schemas.cs b/EliteAPI.Tests/Schemas.cs
index b36cb169..76723b2b 100644
--- a/EliteAPI.Tests/Schemas.cs
+++ b/EliteAPI.Tests/Schemas.cs
@@ -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";
@@ -58,7 +59,7 @@ public void Properties((string name, string type) schemaInfo)
.Where(x => x.GetCustomAttributes().Any());
var jsonProperty =
- properties.FirstOrDefault(x => x.GetCustomAttribute()!.PropertyName == name);
+ properties.FirstOrDefault(x => string.Equals(x.GetCustomAttribute()!.PropertyName, name, StringComparison.InvariantCultureIgnoreCase));
Assert.That(jsonProperty, Is.Not.Null, $"Property {name} not found on event {eventName}");
var jsonPropertyType = jsonProperty!.PropertyType;
@@ -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("..", ".");
diff --git a/EliteAPI/EliteAPI.xml b/EliteAPI/EliteAPI.xml
index 9b8dad0f..c08500ca 100644
--- a/EliteAPI/EliteAPI.xml
+++ b/EliteAPI/EliteAPI.xml
@@ -223,6 +223,9 @@
+
+
+
diff --git a/EliteAPI/Events/Events.cs b/EliteAPI/Events/Events.cs
index 7cc8dd64..02e1515a 100644
--- a/EliteAPI/Events/Events.cs
+++ b/EliteAPI/Events/Events.cs
@@ -36,7 +36,7 @@ public Events(ILogger? log, IEventParser eventParser)
}
///
- public IEnumerable EventTypes => _eventHandlers.Keys;
+ public IReadOnlyCollection EventTypes => _eventHandlers.Keys;
///
public IReadOnlyCollection<(IEvent @event, EventContext context)> PreviousEvents => _previousEvents.AsReadOnly();