// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
using System;
using System.Collections.Generic;
using System.Linq;
using Amazon.Runtime.Internal;
using AWS.Deploy.CLI.Common.UnitTests.IO;
using AWS.Deploy.Common.Data;
using AWS.Deploy.Common.IO;
using AWS.Deploy.Common.Recipes;
using AWS.Deploy.Common.Recipes.Validation;
using Moq;
using Newtonsoft.Json;
using Should;
using Xunit;
// Justification: False Positives with assertions, also test class
// ReSharper disable PossibleNullReferenceException
namespace AWS.Deploy.CLI.Common.UnitTests.Recipes.Validation
{
///
/// Tests for
///
public class ValidatorFactoryTests
{
private readonly IOptionSettingHandler _optionSettingHandler;
private readonly IServiceProvider _serviceProvider;
private readonly IValidatorFactory _validatorFactory;
private readonly Mock _awsResourceQueryer;
public ValidatorFactoryTests()
{
_awsResourceQueryer = new Mock();
_optionSettingHandler = new Mock().Object;
var mockServiceProvider = new Mock();
mockServiceProvider.Setup(x => x.GetService(typeof(IOptionSettingHandler))).Returns(_optionSettingHandler);
mockServiceProvider.Setup(x => x.GetService(typeof(IDirectoryManager))).Returns(new TestDirectoryManager());
mockServiceProvider.Setup(x => x.GetService(typeof(IFileManager))).Returns(new TestFileManager());
_serviceProvider = mockServiceProvider.Object;
mockServiceProvider
.Setup(x => x.GetService(typeof(IAWSResourceQueryer)))
.Returns(_awsResourceQueryer.Object);
_validatorFactory = new ValidatorFactory(_serviceProvider);
mockServiceProvider
.Setup(x => x.GetService(typeof(IValidatorFactory)))
.Returns(_validatorFactory);
}
[Fact]
public void HasABindingForAllOptionSettingItemValidators()
{
// ARRANGE
var allValidators = Enum.GetValues(typeof(OptionSettingItemValidatorList));
var optionSettingItem = new OptionSettingItem("id", "fullyQualifiedId", "name", "description")
{
Validators =
allValidators
.Cast()
.Select(validatorType =>
new OptionSettingItemValidatorConfig
{
ValidatorType = validatorType
}
)
.ToList()
};
// ACT
var validators = _validatorFactory.BuildValidators(optionSettingItem);
// ASSERT
validators.Length.ShouldEqual(allValidators.Length);
}
[Fact]
public void HasABindingForAllRecipeValidators()
{
// ARRANGE
var allValidators = Enum.GetValues(typeof(RecipeValidatorList));
var recipeDefinition = new RecipeDefinition("id", "version", "name",
DeploymentTypes.CdkProject, DeploymentBundleTypes.Container, "template", "templateId", "description", "shortDescription", "targetService")
{
Validators =
allValidators
.Cast()
.Select(validatorType =>
new RecipeValidatorConfig
{
ValidatorType = validatorType
}
)
.ToList()
};
// ACT
var validators = _validatorFactory.BuildValidators(recipeDefinition);
// ASSERT
validators.Length.ShouldEqual(allValidators.Length);
}
///
/// Make sure we build correctly when coming from json
///
[Fact]
public void CanBuildRehydratedOptionSettingsItem()
{
// ARRANGE
var expectedValidator = new RequiredValidator
{
ValidationFailedMessage = "Custom Test Message"
};
var optionSettingItem = new OptionSettingItem("id", "fullyQualifiedId", "name", "description")
{
Name = "Test Item",
Validators = new List
{
new OptionSettingItemValidatorConfig
{
ValidatorType = OptionSettingItemValidatorList.Required,
Configuration = expectedValidator
}
}
};
var json = JsonConvert.SerializeObject(optionSettingItem, Formatting.Indented);
var deserialized = JsonConvert.DeserializeObject(json);
// ACT
var validators = _validatorFactory.BuildValidators(deserialized);
// ASSERT
validators.Length.ShouldEqual(1);
validators.First().ShouldBeType(expectedValidator.GetType());
validators.OfType().First().ValidationFailedMessage.ShouldEqual(expectedValidator.ValidationFailedMessage);
}
///
/// This tests captures the behavior of the system. Requirements for this area are a little unclear
/// and can be adjusted as needed. This test is not meant to show 'ideal' behavior; only 'current'
/// behavior.
///
/// This test behavior is dependent on using intermediary json. If you just
/// used a fully populated , this test would behave differently.
/// Coming from json, wins,
/// coming from object model wins.
///
[Fact]
public void WhenValidatorTypeAndConfigurationHaveAMismatchThenValidatorTypeWins()
{
// ARRANGE
var optionSettingItem = new OptionSettingItem("id", "fullyQualifiedId", "name", "description")
{
Name = "Test Item",
Validators = new List
{
new OptionSettingItemValidatorConfig
{
ValidatorType = OptionSettingItemValidatorList.Regex,
// Required can only map to RequiredValidator, this setup doesn't make sense:
Configuration = new RangeValidator
{
Min = 1
}
}
}
};
var json = JsonConvert.SerializeObject(optionSettingItem, Formatting.Indented);
var deserialized = JsonConvert.DeserializeObject(json);
Exception exception = null;
IOptionSettingItemValidator[] validators = null;
// ACT
try
{
validators = _validatorFactory.BuildValidators(deserialized);
}
catch (Exception e)
{
exception = e;
}
// ASSERT
exception.ShouldBeNull();
// we have our built validator
validators.ShouldNotBeNull();
validators.Length.ShouldEqual(1);
// things get a little odd, the type is correct,
// but the output messages is going to be from the RangeValidator.
validators.First().ShouldBeType();
validators.OfType().First().ValidationFailedMessage.ShouldEqual(
new RangeValidator().ValidationFailedMessage);
}
}
}