Localize the email property editor validation and add tests (#18461)

* Localize the email property editor validation and add tests.

* Reverted trim to ensure behaviour for whitespace is unchanged.
This commit is contained in:
Andy Butland
2025-03-03 13:13:50 +01:00
committed by GitHub
parent 2ebc6badd7
commit f6b4ddf598
3 changed files with 107 additions and 15 deletions

View File

@@ -1,24 +1,45 @@
using System.ComponentModel.DataAnnotations;
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Models.Validation;
using Umbraco.Cms.Core.Services;
using Umbraco.Extensions;
namespace Umbraco.Cms.Core.PropertyEditors.Validators;
/// <summary>
/// A validator that validates an email address
/// A validator that validates an email address.
/// </summary>
public sealed class EmailValidator : IValueValidator
{
private readonly ILocalizedTextService _localizedTextService;
/// <summary>
/// Initializes a new instance of the <see cref="EmailValidator"/> class.
/// </summary>
[Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 17.")]
public EmailValidator()
: this(StaticServiceProvider.Instance.GetRequiredService<ILocalizedTextService>())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="EmailValidator"/> class.
/// </summary>
public EmailValidator(ILocalizedTextService localizedTextService) => _localizedTextService = localizedTextService;
/// <inheritdoc />
public IEnumerable<ValidationResult> Validate(object? value, string? valueType, object? dataTypeConfiguration, PropertyValidationContext validationContext)
{
var asString = value == null ? string.Empty : value.ToString();
var valueAsString = value?.ToString() ?? string.Empty;
var emailVal = new EmailAddressAttribute();
var emailAddressAttribute = new EmailAddressAttribute();
if (asString != string.Empty && emailVal.IsValid(asString) == false)
if (valueAsString != string.Empty && emailAddressAttribute.IsValid(valueAsString) == false)
{
// TODO: localize these!
yield return new ValidationResult("Email is invalid", new[] { "value" });
yield return new ValidationResult(
_localizedTextService.Localize("validation", "invalidEmail", [valueAsString]),
["value"]);
}
}
}

View File

@@ -1,29 +1,50 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using Microsoft.Extensions.DependencyInjection;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.PropertyEditors.Validators;
using Umbraco.Cms.Core.Services;
namespace Umbraco.Cms.Core.PropertyEditors;
/// <summary>
/// Defines an email address property editor.
/// </summary>
[DataEditor(
Constants.PropertyEditors.Aliases.EmailAddress,
ValueEditorIsReusable = true)]
public class EmailAddressPropertyEditor : DataEditor
{
/// <summary>
/// The constructor will setup the property editor based on the attribute if one is found
/// </summary>
public EmailAddressPropertyEditor(IDataValueEditorFactory dataValueEditorFactory)
: base(dataValueEditorFactory)
=> SupportsReadOnly = true;
private readonly ILocalizedTextService _localizedTextService;
/// <summary>
/// Initializes a new instance of the <see cref="EmailAddressPropertyEditor"/> class.
/// </summary>
[Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 17.")]
public EmailAddressPropertyEditor(IDataValueEditorFactory dataValueEditorFactory)
: this(
dataValueEditorFactory,
StaticServiceProvider.Instance.GetRequiredService<ILocalizedTextService>())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="EmailAddressPropertyEditor"/> class.
/// </summary>
public EmailAddressPropertyEditor(IDataValueEditorFactory dataValueEditorFactory, ILocalizedTextService localizedTextService)
: base(dataValueEditorFactory)
{
SupportsReadOnly = true;
_localizedTextService = localizedTextService;
}
/// <inheritdoc/>
protected override IDataValueEditor CreateValueEditor()
{
IDataValueEditor editor = base.CreateValueEditor();
// add an email address validator
editor.Validators.Add(new EmailValidator());
editor.Validators.Add(new EmailValidator(_localizedTextService));
return editor;
}
}

View File

@@ -0,0 +1,50 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using System.Globalization;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core.Models.Validation;
using Umbraco.Cms.Core.PropertyEditors;
using Umbraco.Cms.Core.PropertyEditors.Validators;
using Umbraco.Cms.Core.Services;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.PropertyEditors.Validators;
[TestFixture]
public class EmailValidatorTests
{
[TestCase(null, true)]
[TestCase("", true)]
[TestCase(" ", false)]
[TestCase("test@test.com", true)]
[TestCase("invalid", false)]
public void Validates_Email_Address(object? email, bool expectedSuccess)
{
var validator = CreateValidator();
var result = validator.Validate(email, ValueTypes.String, null, PropertyValidationContext.Empty());
if (expectedSuccess)
{
Assert.IsEmpty(result);
}
else
{
Assert.AreEqual(1, result.Count());
var validationResult = result.First();
Assert.AreEqual("validation_invalidEmail", validationResult.ErrorMessage);
}
}
private static EmailValidator CreateValidator()
{
var localizedTextServiceMock = new Mock<ILocalizedTextService>();
localizedTextServiceMock.Setup(x => x.Localize(
It.IsAny<string>(),
It.IsAny<string>(),
It.IsAny<CultureInfo>(),
It.IsAny<IDictionary<string, string>>()))
.Returns((string key, string alias, CultureInfo culture, IDictionary<string, string> args) => $"{key}_{alias}");
return new EmailValidator(localizedTextServiceMock.Object);
}
}