Skip to content

Commit

Permalink
feat: add IUIComponentLogger dependency to UIComponent
Browse files Browse the repository at this point in the history
  • Loading branch information
jonisavo committed Jun 18, 2022
1 parent b8a089c commit 8e89652
Show file tree
Hide file tree
Showing 10 changed files with 151 additions and 19 deletions.
20 changes: 12 additions & 8 deletions Assets/UIComponents.Tests/QueryAttributeTests.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
using System.Collections.Generic;
using System.Text.RegularExpressions;
using NSubstitute;
using NUnit.Framework;
using UIComponents.Experimental;
using UnityEngine;
using UnityEngine.TestTools;
using UIComponents.Utilities;
using UnityEngine.UIElements;

namespace UIComponents.Tests
Expand Down Expand Up @@ -96,15 +95,20 @@ private class ComponentWithInvalidQueryAttribute : UIComponent
[Test]
public void Should_Log_Error_On_Invalid_Fields()
{
var component = new ComponentWithInvalidQueryAttribute();

var mockLogger = Substitute.For<IUIComponentLogger>();

ComponentWithInvalidQueryAttribute component;

using (new DependencyScope<ComponentWithInvalidQueryAttribute, IUIComponentLogger>(mockLogger))
component = new ComponentWithInvalidQueryAttribute();

Assert.That(component.InvalidField, Is.Null);
Assert.That(component.InvalidArray, Is.Null);
Assert.That(component.InvalidList, Is.Null);

LogAssert.Expect(LogType.Error, "QueryAttribute must be used on a VisualElement field. InvalidField is System.Object");
LogAssert.Expect(LogType.Error, "QueryAttribute must be used on a VisualElement field. InvalidArray is System.Object");
LogAssert.Expect(LogType.Error, new Regex(Regex.Escape("QueryAttribute must be used on a VisualElement field. InvalidList is System.Collections.Generic.List`1[[UnityEngine.UIElements.VisualElement")));
mockLogger.Received().LogError("QueryAttribute must be used on a VisualElement field. InvalidField is System.Object", component);
mockLogger.Received().LogError("QueryAttribute must be used on a VisualElement field. InvalidArray is System.Object", component);
mockLogger.Received().LogError(Arg.Is<string>(s => s.Contains("QueryAttribute must be used on a VisualElement field. InvalidList is System.Collections.Generic.List`1[[UnityEngine.UIElements.VisualElement")), component);
}
}
}
19 changes: 11 additions & 8 deletions Assets/UIComponents.Tests/StylesheetAttributeTests.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
using System.Text.RegularExpressions;
using NSubstitute;
using NSubstitute;
using NSubstitute.ReturnsExtensions;
using NUnit.Framework;
using UIComponents.Tests.Utilities;
using UIComponents.Utilities;
using UnityEngine;
using UnityEngine.TestTools;
using UnityEngine.UIElements;

namespace UIComponents.Tests
Expand Down Expand Up @@ -72,13 +71,17 @@ public void Invalid_Stylesheets_Output_Error_Message()
{
_resolver.LoadAsset<StyleSheet>("Assets/StylesheetOne.uss")
.ReturnsNull();

var mockLogger = Substitute.For<IUIComponentLogger>();

var component = new UIComponentWithTwoStylesheets();

UIComponentWithTwoStylesheets component;

using (new DependencyScope<UIComponentWithTwoStylesheets, IUIComponentLogger>(mockLogger))
component = new UIComponentWithTwoStylesheets();

_resolver.Received().LoadAsset<StyleSheet>("Assets/StylesheetOne.uss");

LogAssert.Expect(LogType.Error, new Regex("Could not find stylesheet"));

mockLogger.Received().LogError("Could not find stylesheet Assets/StylesheetOne.uss", component);

Assert.That(component.styleSheets.count, Is.EqualTo(1));
}
}
Expand Down
47 changes: 47 additions & 0 deletions Assets/UIComponents.Tests/UIComponentDebugLoggerTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;

namespace UIComponents.Tests
{
[TestFixture]
public class UIComponentDebugLoggerTests
{
private class TestComponent : UIComponent {}

private TestComponent _testComponent;

private UIComponentDebugLogger _logger;

[SetUp]
public void SetUp()
{
_testComponent = new TestComponent();
_logger = new UIComponentDebugLogger();
}

[Test]
public void Log_Uses_Debug_Log()
{
_logger.Log("Hello world", _testComponent);

LogAssert.Expect(LogType.Log, "[TestComponent] Hello world");
}

[Test]
public void LogWarning_Uses_Debug_LogWarning()
{
_logger.LogWarning("Hello warning", _testComponent);

LogAssert.Expect(LogType.Warning, "[TestComponent] Hello warning");
}

[Test]
public void LogError_Uses_Debug_LogError()
{
_logger.LogError("Error message", _testComponent);

LogAssert.Expect(LogType.Error, "[TestComponent] Error message");
}
}
}
3 changes: 3 additions & 0 deletions Assets/UIComponents.Tests/UIComponentDebugLoggerTests.cs.meta

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

11 changes: 11 additions & 0 deletions Assets/UIComponents/Core/IUIComponentLogger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace UIComponents
{
public interface IUIComponentLogger
{
void Log(string message, UIComponent component);

void LogWarning(string message, UIComponent component);

void LogError(string message, UIComponent component);
}
}
3 changes: 3 additions & 0 deletions Assets/UIComponents/Core/IUIComponentLogger.cs.meta

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

14 changes: 11 additions & 3 deletions Assets/UIComponents/Core/UIComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using UIComponents.Cache;
using UIComponents.Internal;
using Unity.Profiling;
using UnityEngine;
using UnityEngine.UIElements;

namespace UIComponents
Expand All @@ -19,7 +18,9 @@ namespace UIComponents
/// <seealso cref="StylesheetAttribute"/>
/// <seealso cref="DependencyAttribute"/>
/// <seealso cref="ResourcesAssetResolver"/>
/// <seealso cref="UIComponentDebugLogger"/>
[Dependency(typeof(IAssetResolver), provide: typeof(ResourcesAssetResolver))]
[Dependency(typeof(IUIComponentLogger), provide: typeof(UIComponentDebugLogger))]
public abstract class UIComponent : VisualElement
{
private static readonly Dictionary<Type, UIComponentCache> CacheDictionary =
Expand All @@ -45,6 +46,12 @@ internal static bool TryGetCache<TComponent>(out UIComponentCache cache) where T
/// </summary>
public readonly IAssetResolver AssetResolver;

/// <summary>
/// The IUIComponentLogger used by this UIComponent.
/// Defaults to <see cref="UIComponentDebugLogger"/>.
/// </summary>
protected readonly IUIComponentLogger Logger;

private readonly DependencyInjector _dependencyInjector;

private readonly Type _componentType;
Expand All @@ -70,6 +77,7 @@ protected UIComponent()
DependencySetupProfilerMarker.End();

AssetResolver = _dependencyInjector.Provide<IAssetResolver>();
Logger = _dependencyInjector.Provide<IUIComponentLogger>();

CacheSetupProfilerMarker.Begin();
if (!CacheDictionary.ContainsKey(_componentType))
Expand Down Expand Up @@ -184,7 +192,7 @@ private StyleSheet[] GetStyleSheets()

if (styleSheet == null)
{
Debug.LogError($"Could not find stylesheet {assetPath} for {_componentType.Name}");
Logger.LogError($"Could not find stylesheet {assetPath}", this);
continue;
}

Expand Down Expand Up @@ -232,7 +240,7 @@ private void PopulateQueryFields()

if (!VisualElementType.IsAssignableFrom(concreteType))
{
Debug.LogError($"QueryAttribute must be used on a VisualElement field. {fieldInfo.Name} is {concreteType.FullName}");
Logger.LogError($"QueryAttribute must be used on a VisualElement field. {fieldInfo.Name} is {concreteType.FullName}", this);
continue;
}

Expand Down
22 changes: 22 additions & 0 deletions Assets/UIComponents/Core/UIComponentDebugLogger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using UnityEngine;

namespace UIComponents
{
public class UIComponentDebugLogger : IUIComponentLogger
{
public void Log(string message, UIComponent component)
{
Debug.LogFormat("[{0}] {1}", component.GetTypeName(), message);
}

public void LogWarning(string message, UIComponent component)
{
Debug.LogWarningFormat("[{0}] {1}", component.GetTypeName(), message);
}

public void LogError(string message, UIComponent component)
{
Debug.LogErrorFormat("[{0}] {1}", component.GetTypeName(), message);
}
}
}
3 changes: 3 additions & 0 deletions Assets/UIComponents/Core/UIComponentDebugLogger.cs.meta

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

28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -485,3 +485,31 @@ public class FirstComponent : BaseComponent {}
public class SecondComponent : BaseComponent {}
```

## Logging

By default, UIComponents use `Debug.Log` to log messages. This can be changed by overriding the
`IUIComponentLogger` dependency.

```c#
public class MyLogger : IUIComponentLogger
{
public void Log(string message, UIComponent component)
{
// Do something with the message
}

public void LogWarning(string message, UIComponent component)
{
// Do something with the message
}

public void LogError(string message, UIComponent component)
{
// Do something with the message
}
}

[Dependency(typeof(IUIComponentLogger), provide: typeof(MyLogger))]
public class MyComponent : UIComponent {}
```

0 comments on commit 8e89652

Please sign in to comment.