Skip to content

Add comprehensive unit tests for TagHelpers and fix build configuration #75

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 128 additions & 0 deletions Our.Umbraco.TagHelpers.Tests/DictionaryTagHelperTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
using Microsoft.AspNetCore.Razor.TagHelpers;
using Moq;
using NUnit.Framework;
using System.Collections.Generic;
using System.Globalization;
using System.Threading.Tasks;
using Our.Umbraco.TagHelpers.Tests.Helpers;
using Umbraco.Cms.Core.Dictionary;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Services;

namespace Our.Umbraco.TagHelpers.Tests
{
public class DictionaryTagHelperTests
{
private Mock<ILocalizationService> _mockLocalizationService;
private DictionaryTagHelper _tagHelper;

[SetUp]
public void SetUp()
{
_mockLocalizationService = new Mock<ILocalizationService>();
_tagHelper = new DictionaryTagHelper(_mockLocalizationService.Object);
}

[Test]
public async Task Process_WithValidKeyAndTranslation_ReturnsTranslation()
{
// Arrange
var key = "test.key";
var expectedTranslation = "Test Translation";
var culture = new CultureInfo("en-US");
CultureInfo.CurrentCulture = culture;

var mockDictionaryItem = new Mock<IDictionaryItem>();
var mockLanguage = new Mock<ILanguage>();
mockLanguage.Setup(x => x.CultureInfo).Returns(culture);

var mockTranslation = new Mock<IDictionaryTranslation>();
mockTranslation.Setup(x => x.Language).Returns(mockLanguage.Object);
mockTranslation.Setup(x => x.Value).Returns(expectedTranslation);

mockDictionaryItem.Setup(x => x.Translations).Returns(new List<IDictionaryTranslation> { mockTranslation.Object });

_mockLocalizationService.Setup(x => x.GetDictionaryItemByKey(key)).Returns(mockDictionaryItem.Object);

var tagHelperContext = TestContextHelpers.GetTagHelperContext("dict-id");
var tagHelperOutput = TestContextHelpers.GetTagHelperOutput("our-dictionary");

_tagHelper.Key = key;

// Act
await Task.Run(() => _tagHelper.Process(tagHelperContext, tagHelperOutput));

var content = tagHelperOutput.Content.GetContent();

// Assert
Assert.AreEqual("", tagHelperOutput.TagName); // Tag name should be removed
Assert.AreEqual(expectedTranslation, content);
}

[Test]
public async Task Process_WithNullKey_DoesNotModifyContent()
{
// Arrange
var tagHelperContext = TestContextHelpers.GetTagHelperContext("dict-id");
var tagHelperOutput = TestContextHelpers.GetTagHelperOutput("our-dictionary");
var originalContent = "Original content";
tagHelperOutput.Content.SetHtmlContent(originalContent);

_tagHelper.Key = null;

// Act
await Task.Run(() => _tagHelper.Process(tagHelperContext, tagHelperOutput));

var content = tagHelperOutput.Content.GetContent();

// Assert
Assert.AreEqual("", tagHelperOutput.TagName); // Tag name should be removed
Assert.AreEqual(originalContent, content);
}

[Test]
public async Task Process_WithEmptyKey_DoesNotModifyContent()
{
// Arrange
var tagHelperContext = TestContextHelpers.GetTagHelperContext("dict-id");
var tagHelperOutput = TestContextHelpers.GetTagHelperOutput("our-dictionary");
var originalContent = "Original content";
tagHelperOutput.Content.SetHtmlContent(originalContent);

_tagHelper.Key = "";

// Act
await Task.Run(() => _tagHelper.Process(tagHelperContext, tagHelperOutput));

var content = tagHelperOutput.Content.GetContent();

// Assert
Assert.AreEqual("", tagHelperOutput.TagName); // Tag name should be removed
Assert.AreEqual(originalContent, content);
}

[Test]
public async Task Process_WithNonExistentKey_DoesNotModifyContent()
{
// Arrange
var key = "nonexistent.key";
_mockLocalizationService.Setup(x => x.GetDictionaryItemByKey(key)).Returns((IDictionaryItem)null);

var tagHelperContext = TestContextHelpers.GetTagHelperContext("dict-id");
var tagHelperOutput = TestContextHelpers.GetTagHelperOutput("our-dictionary");
var originalContent = "Original content";
tagHelperOutput.Content.SetHtmlContent(originalContent);

_tagHelper.Key = key;

// Act
await Task.Run(() => _tagHelper.Process(tagHelperContext, tagHelperOutput));

var content = tagHelperOutput.Content.GetContent();

// Assert
Assert.AreEqual("", tagHelperOutput.TagName); // Tag name should be removed
Assert.AreEqual(originalContent, content);
}
}
}
71 changes: 71 additions & 0 deletions Our.Umbraco.TagHelpers.Tests/EditLinkTagHelperTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using Microsoft.AspNetCore.Razor.TagHelpers;
using Moq;
using NUnit.Framework;
using System.Threading.Tasks;
using Our.Umbraco.TagHelpers.Tests.Helpers;
using Our.Umbraco.TagHelpers.Services;
using Umbraco.Cms.Core.Web;

namespace Our.Umbraco.TagHelpers.Tests
{
public class EditLinkTagHelperTests
{
[Test]
public void Constructor_WithValidParameters_InitializesProperties()
{
// Arrange
var mockBackofficeUserAccessor = new Mock<IBackofficeUserAccessor>();
var mockUmbracoContextAccessor = new Mock<IUmbracoContextAccessor>();

// Act
var tagHelper = new EditLinkTagHelper(mockBackofficeUserAccessor.Object, mockUmbracoContextAccessor.Object);

// Assert
Assert.IsNotNull(tagHelper);
Assert.AreEqual("/umbraco#/content/content/edit/", tagHelper.EditUrl);
Assert.IsFalse(tagHelper.UseDefaultStyles);
Assert.AreEqual(int.MinValue, tagHelper.ContentId);
}

[Test]
public void Properties_CanBeSetAndRetrieved()
{
// Arrange
var mockBackofficeUserAccessor = new Mock<IBackofficeUserAccessor>();
var mockUmbracoContextAccessor = new Mock<IUmbracoContextAccessor>();
var tagHelper = new EditLinkTagHelper(mockBackofficeUserAccessor.Object, mockUmbracoContextAccessor.Object);

// Act
tagHelper.ContentId = 1234;
tagHelper.EditUrl = "/custom/edit/url/";
tagHelper.UseDefaultStyles = true;

// Assert
Assert.AreEqual(1234, tagHelper.ContentId);
Assert.AreEqual("/custom/edit/url/", tagHelper.EditUrl);
Assert.IsTrue(tagHelper.UseDefaultStyles);
}

[Test]
public void Process_WithNoBackofficeUser_SuppressesOutput()
{
// Arrange
var mockBackofficeUserAccessor = new Mock<IBackofficeUserAccessor>();
var mockUmbracoContextAccessor = new Mock<IUmbracoContextAccessor>();

// Setup: No backoffice user (null)
mockBackofficeUserAccessor.Setup(x => x.BackofficeUser).Returns((System.Security.Claims.ClaimsIdentity)null);

var tagHelper = new EditLinkTagHelper(mockBackofficeUserAccessor.Object, mockUmbracoContextAccessor.Object);
var tagHelperContext = TestContextHelpers.GetTagHelperContext("edit-link-id");
var tagHelperOutput = TestContextHelpers.GetTagHelperOutput("our-edit-link");

// Act
tagHelper.Process(tagHelperContext, tagHelperOutput);

// Assert - When no backoffice user, output should be suppressed (no tag name)
// The EditLinkTagHelper should suppress output when no backoffice user is found
Assert.IsNull(tagHelperOutput.TagName);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net8.0</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Moq;
using NUnit.Framework;
using Our.Umbraco.TagHelpers.Tests.Helpers;
using System;
using System.Collections.Generic;

namespace Our.Umbraco.TagHelpers.Tests
{
public class SurfaceControllerFormTagHelperTests
{
[Test]
public void Constructor_WithValidParameters_InitializesProperties()
{
// Arrange
var mockDataProtectionProvider = new Mock<IDataProtectionProvider>();

// Act
var tagHelper = new SurfaceControllerFormTagHelper(mockDataProtectionProvider.Object);

// Assert
Assert.IsNotNull(tagHelper);
Assert.AreEqual("", tagHelper.Area);
Assert.IsNull(tagHelper.ControllerAction);
Assert.IsNull(tagHelper.ControllerName);
Assert.IsNotNull(tagHelper.RouteValues);
}

[Test]
public void Properties_CanBeSetAndRetrieved()
{
// Arrange
var mockDataProtectionProvider = new Mock<IDataProtectionProvider>();
var tagHelper = new SurfaceControllerFormTagHelper(mockDataProtectionProvider.Object);

// Act
tagHelper.ControllerAction = "TestAction";
tagHelper.ControllerName = "TestController";
tagHelper.Area = "TestArea";

var routeValues = new Dictionary<string, string> { { "id", "123" } };
tagHelper.RouteValues = routeValues;

// Assert
Assert.AreEqual("TestAction", tagHelper.ControllerAction);
Assert.AreEqual("TestController", tagHelper.ControllerName);
Assert.AreEqual("TestArea", tagHelper.Area);
Assert.AreEqual(routeValues, tagHelper.RouteValues);
}

[Test]
public void Process_WithNullContext_ThrowsArgumentNullException()
{
// Arrange
var mockDataProtectionProvider = new Mock<IDataProtectionProvider>();
var tagHelper = new SurfaceControllerFormTagHelper(mockDataProtectionProvider.Object);
var tagHelperOutput = TestContextHelpers.GetTagHelperOutput("form");

// Act & Assert
Assert.Throws<ArgumentNullException>(() => tagHelper.Process(null, tagHelperOutput));
}

[Test]
public void Process_WithNullOutput_ThrowsArgumentNullException()
{
// Arrange
var mockDataProtectionProvider = new Mock<IDataProtectionProvider>();
var tagHelper = new SurfaceControllerFormTagHelper(mockDataProtectionProvider.Object);
var tagHelperContext = TestContextHelpers.GetTagHelperContext("form-id");

// Act & Assert
Assert.Throws<ArgumentNullException>(() => tagHelper.Process(tagHelperContext, null));
}

[Test]
public void Process_WithEmptyControllerName_ReturnsEarly()
{
// Arrange
var mockDataProtectionProvider = new Mock<IDataProtectionProvider>();
var tagHelper = new SurfaceControllerFormTagHelper(mockDataProtectionProvider.Object);
var tagHelperContext = TestContextHelpers.GetTagHelperContext("form-id");
var tagHelperOutput = TestContextHelpers.GetTagHelperOutput("form");

tagHelper.ControllerName = "";
tagHelper.ControllerAction = "TestAction";

// Act - Should return early without doing anything
tagHelper.Process(tagHelperContext, tagHelperOutput);

// Assert - Since it returns early, PostContent should not be modified
// This is a basic test to ensure the method doesn't throw
Assert.DoesNotThrow(() => tagHelper.Process(tagHelperContext, tagHelperOutput));
}
}
}
70 changes: 70 additions & 0 deletions Our.Umbraco.TagHelpers.Tests/VersionTagHelperTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using Microsoft.AspNetCore.Razor.TagHelpers;
using NUnit.Framework;
using System.Threading.Tasks;
using Our.Umbraco.TagHelpers.Tests.Helpers;

namespace Our.Umbraco.TagHelpers.Tests
{
public class VersionTagHelperTests
{
[Test]
public async Task Process_WithNoAssemblyName_ReturnsEntryAssemblyVersion()
{
// Arrange
var id = "version-id";
var tagHelperContext = TestContextHelpers.GetTagHelperContext(id);
var tagHelperOutput = TestContextHelpers.GetTagHelperOutput("our-version");

var tagHelper = new VersionTagHelper();

// Act
await Task.Run(() => tagHelper.Process(tagHelperContext, tagHelperOutput));

var content = tagHelperOutput.Content.GetContent();

// Assert
Assert.AreEqual("", tagHelperOutput.TagName); // Tag name should be removed
Assert.IsNotNull(content);
Assert.IsNotEmpty(content);
}

[Test]
public async Task Process_WithValidAssemblyName_ReturnsAssemblyVersion()
{
// Arrange
var id = "version-id";
var tagHelperContext = TestContextHelpers.GetTagHelperContext(id);
var tagHelperOutput = TestContextHelpers.GetTagHelperOutput("our-version");

var tagHelper = new VersionTagHelper { AssemblyName = "System.Private.CoreLib" };

// Act
await Task.Run(() => tagHelper.Process(tagHelperContext, tagHelperOutput));

var content = tagHelperOutput.Content.GetContent();

// Assert
Assert.AreEqual("", tagHelperOutput.TagName); // Tag name should be removed
Assert.IsNotNull(content);
Assert.IsNotEmpty(content);
}

[Test]
public async Task Process_WithNonExistentAssemblyName_SuppressesOutput()
{
// Arrange
var id = "version-id";
var tagHelperContext = TestContextHelpers.GetTagHelperContext(id);
var tagHelperOutput = TestContextHelpers.GetTagHelperOutput("our-version");

var tagHelper = new VersionTagHelper { AssemblyName = "NonExistentAssembly" };

// Act
await Task.Run(() => tagHelper.Process(tagHelperContext, tagHelperOutput));

// Assert - Should suppress output and have empty content
var content = tagHelperOutput.Content.GetContent();
Assert.IsTrue(string.IsNullOrEmpty(content));
}
}
}
2 changes: 1 addition & 1 deletion Our.Umbraco.TagHelpers/Our.Umbraco.TagHelpers.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
<PackageReference Include="Umbraco.Cms.Web.Common" Version="9.1.0" />

<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
<PackageReference Include="GitVersion.MsBuild" Version="5.8.1" PrivateAssets="All" />
<!-- <PackageReference Include="GitVersion.MsBuild" Version="5.8.1" PrivateAssets="All" /> -->
</ItemGroup>

<ItemGroup>
Expand Down
Loading