Skip to content

Commit

Permalink
Port Tag to new component generation (#307)
Browse files Browse the repository at this point in the history
  • Loading branch information
gunndabad authored Jan 15, 2025
1 parent f5123d0 commit 2a17cdc
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 26 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System;

namespace GovUk.Frontend.AspNetCore.ComponentGeneration;

public partial class DefaultComponentGenerator
{
internal const string TagElement = "strong";

/// <inheritdoc/>
public virtual HtmlTagBuilder GenerateTag(TagOptions options)
{
ArgumentNullException.ThrowIfNull(options);
options.Validate();

return new HtmlTagBuilder(TagElement)
.WithCssClass("govuk-tag")
.WithCssClasses(ExplodeClasses(options.Classes?.ToHtmlString()))
.WithAttributes(options.Attributes)
.WithAppendedHtml(GetEncodedTextOrHtml(options.Text, options.Html)!);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ public interface IComponentGenerator
/// <returns>An <see cref="HtmlTagBuilder"/> with the component's HTML.</returns>
HtmlTagBuilder GenerateCharacterCount(CharacterCountOptions options);

/// <summary>
/// Generates a tag component.
/// </summary>
/// <returns>An <see cref="HtmlTagBuilder"/> with the component's HTML.</returns>
HtmlTagBuilder GenerateTag(TagOptions options);

/// <summary>
/// Generates a textarea component.
/// </summary>
Expand Down
34 changes: 16 additions & 18 deletions src/GovUk.Frontend.AspNetCore/TagHelpers/TagTagHelper.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System.Threading.Tasks;
using GovUk.Frontend.AspNetCore.HtmlGeneration;
using Microsoft.AspNetCore.Mvc.TagHelpers;
using GovUk.Frontend.AspNetCore.ComponentGeneration;
using Microsoft.AspNetCore.Razor.TagHelpers;

namespace GovUk.Frontend.AspNetCore.TagHelpers;
Expand All @@ -9,43 +8,42 @@ namespace GovUk.Frontend.AspNetCore.TagHelpers;
/// Generates a GDS tag component.
/// </summary>
[HtmlTargetElement(TagName)]
[OutputElementHint(ComponentGenerator.TagElement)]
[OutputElementHint(DefaultComponentGenerator.TagElement)]
public class TagTagHelper : TagHelper
{
internal const string TagName = "govuk-tag";

private readonly IGovUkHtmlGenerator _htmlGenerator;
private readonly IComponentGenerator _componentGenerator;

/// <summary>
/// Creates a new <see cref="TagTagHelper"/>.
/// </summary>
public TagTagHelper()
: this(htmlGenerator: null)
public TagTagHelper(IComponentGenerator componentGenerator)
{
}

internal TagTagHelper(IGovUkHtmlGenerator? htmlGenerator = null)
{
_htmlGenerator = htmlGenerator ?? new ComponentGenerator();
_componentGenerator = componentGenerator;
}

/// <inheritdoc/>
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
var childContent = await output.GetChildContentAsync();
var childContent = (await output.GetChildContentAsync()).Snapshot();

if (output.Content.IsModified)
{
childContent = output.Content;
}

var tagBuilder = _htmlGenerator.GenerateTag(childContent, output.Attributes.ToAttributeDictionary());
var attributes = new EncodedAttributesDictionary(output.Attributes);
attributes.Remove("class", out var classes);

output.TagName = tagBuilder.TagName;
output.TagMode = TagMode.StartTagAndEndTag;
var component = _componentGenerator.GenerateTag(new TagOptions()
{
Text = null,
Html = childContent,
Attributes = attributes,
Classes = classes
});

output.Attributes.Clear();
output.MergeAttributes(tagBuilder);
output.Content.SetHtmlContent(tagBuilder.InnerHtml);
component.WriteTo(output);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@ public void CharacterCount(ComponentTestCaseData<CharacterCountOptions> data) =>
data,
(generator, options) => generator.GenerateCharacterCount(options).ToHtmlString());

[Theory]
[ComponentFixtureData("tag", typeof(TagOptions))]
public void Tag(ComponentTestCaseData<TagOptions> data) =>
CheckComponentHtmlMatchesExpectedHtml(
data,
(generator, options) => generator.GenerateTag(options).ToHtmlString());

[Theory]
[ComponentFixtureData("textarea", typeof(TextareaOptions))]
public void Textarea(ComponentTestCaseData<TextareaOptions> data) =>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using GovUk.Frontend.AspNetCore.HtmlGeneration;
using GovUk.Frontend.AspNetCore.ComponentGeneration;
using GovUk.Frontend.AspNetCore.TagHelpers;
using GovUk.Frontend.AspNetCore.TestCommon;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Moq;
using Xunit;

namespace GovUk.Frontend.AspNetCore.Tests.TagHelpers;

public class TagTagHelperTests
{
[Fact]
public async Task ProcessAsync_WithContent_GeneratesExpectedOutput()
public async Task ProcessAsync_InvokesComponentGeneratorWithExpectedOptions()
{
// Arrange
var html = "A tag";

var context = new TagHelperContext(
tagName: "govuk-tag",
allAttributes: new TagHelperAttributeList(),
Expand All @@ -26,18 +28,21 @@ public async Task ProcessAsync_WithContent_GeneratesExpectedOutput()
getChildContentAsync: (useCachedResult, encoder) =>
{
var tagHelperContent = new DefaultTagHelperContent();
tagHelperContent.SetContent("A tag");
tagHelperContent.SetContent(html);
return Task.FromResult<TagHelperContent>(tagHelperContent);
});

var tagHelper = new TagTagHelper(new ComponentGenerator());
var componentGeneratorMock = new Mock<DefaultComponentGenerator>() { CallBase = true };
TagOptions? actualOptions = null;
componentGeneratorMock.Setup(mock => mock.GenerateTag(It.IsAny<TagOptions>())).Callback<TagOptions>(o => actualOptions = o);

var tagHelper = new TagTagHelper(componentGeneratorMock.Object);

// Act
await tagHelper.ProcessAsync(context, output);

// Assert
var expectedHtml = @"<strong class=""govuk-tag"">A tag</strong>";

AssertEx.HtmlEqual(expectedHtml, output.ToHtmlString());
Assert.NotNull(actualOptions);
Assert.Equal(html, actualOptions!.Html?.ToHtmlString());
}
}

0 comments on commit 2a17cdc

Please sign in to comment.