Init
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
using Prefab.Catalog.Domain.Entities;
|
||||
using Prefab.Catalog.Domain.Services;
|
||||
using Shouldly;
|
||||
|
||||
namespace Prefab.Tests.Unit.Modules.Catalog.Domain.Services;
|
||||
|
||||
[Trait(TraitName.Category, TraitCategory.Unit)]
|
||||
public sealed class VariantResolverShould
|
||||
{
|
||||
private readonly StubUniqueChecker _checker = new();
|
||||
|
||||
[Fact]
|
||||
public async Task ResolveVariantFromAxisSelections()
|
||||
{
|
||||
var context = await BuildModelWithVariantsAsync();
|
||||
var resolver = new VariantResolver();
|
||||
|
||||
var selections = new[]
|
||||
{
|
||||
new OptionSelection(context.ColorOption.Id, context.RedValue.Id, null),
|
||||
new OptionSelection(context.DepthOption.Id, context.Depth24Value.Id, null)
|
||||
};
|
||||
|
||||
var result = resolver.Resolve(context.Model, selections);
|
||||
|
||||
result.IsSuccess.ShouldBeTrue();
|
||||
result.Variant.ShouldBe(context.Red24Variant);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReturnErrorWhenAxisSelectionMissing()
|
||||
{
|
||||
var context = await BuildModelWithVariantsAsync();
|
||||
var resolver = new VariantResolver();
|
||||
|
||||
var selections = new[]
|
||||
{
|
||||
new OptionSelection(context.ColorOption.Id, context.RedValue.Id, null)
|
||||
};
|
||||
|
||||
var result = resolver.Resolve(context.Model, selections);
|
||||
|
||||
result.IsSuccess.ShouldBeFalse();
|
||||
result.Errors.ShouldContain(e => e.Contains("axis", StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ResolveBySkuWhenProvided()
|
||||
{
|
||||
var context = await BuildModelWithVariantsAsync();
|
||||
var resolver = new VariantResolver();
|
||||
|
||||
var result = resolver.Resolve(context.Model, Array.Empty<OptionSelection>(), context.Blue34Variant.Sku);
|
||||
|
||||
result.IsSuccess.ShouldBeTrue();
|
||||
result.Variant.ShouldBe(context.Blue34Variant);
|
||||
}
|
||||
|
||||
private async Task<ModelContext> BuildModelWithVariantsAsync()
|
||||
{
|
||||
var model = await Product.CreateModel($"variant-model-{Guid.NewGuid():N}", $"variant-model-{Guid.NewGuid():N}", null, _checker);
|
||||
|
||||
var colorOption = await OptionDefinition.CreateChoice(model, "color", "Color", _checker, isVariantAxis: true);
|
||||
var redValue = colorOption.AddValue("red", "Red", 0m, PriceDeltaKind.Absolute);
|
||||
var blueValue = colorOption.AddValue("blue", "Blue", 0m, PriceDeltaKind.Absolute);
|
||||
|
||||
var depthOption = await OptionDefinition.CreateChoice(model, "depth", "Depth", _checker, isVariantAxis: true);
|
||||
var depth24Value = depthOption.AddValue("depth_24", "24\"", 0m, PriceDeltaKind.Absolute);
|
||||
var depth34Value = depthOption.AddValue("depth_34", "34\"", 0m, PriceDeltaKind.Absolute);
|
||||
|
||||
var red24Variant = await Product.CreateVariant(model.Id, $"SKU-{Guid.NewGuid():N}", "Red 24", 20m, _checker);
|
||||
red24Variant.AxisValues.Add(new VariantAxisValue
|
||||
{
|
||||
ProductVariant = red24Variant,
|
||||
ProductVariantId = red24Variant.Id,
|
||||
OptionDefinition = colorOption,
|
||||
OptionDefinitionId = colorOption.Id,
|
||||
OptionValue = redValue,
|
||||
OptionValueId = redValue.Id
|
||||
});
|
||||
red24Variant.AxisValues.Add(new VariantAxisValue
|
||||
{
|
||||
ProductVariant = red24Variant,
|
||||
ProductVariantId = red24Variant.Id,
|
||||
OptionDefinition = depthOption,
|
||||
OptionDefinitionId = depthOption.Id,
|
||||
OptionValue = depth24Value,
|
||||
OptionValueId = depth24Value.Id
|
||||
});
|
||||
|
||||
var blue34Variant = await Product.CreateVariant(model.Id, $"SKU-{Guid.NewGuid():N}", "Blue 34", 22m, _checker);
|
||||
blue34Variant.AxisValues.Add(new VariantAxisValue
|
||||
{
|
||||
ProductVariant = blue34Variant,
|
||||
ProductVariantId = blue34Variant.Id,
|
||||
OptionDefinition = colorOption,
|
||||
OptionDefinitionId = colorOption.Id,
|
||||
OptionValue = blueValue,
|
||||
OptionValueId = blueValue.Id
|
||||
});
|
||||
blue34Variant.AxisValues.Add(new VariantAxisValue
|
||||
{
|
||||
ProductVariant = blue34Variant,
|
||||
ProductVariantId = blue34Variant.Id,
|
||||
OptionDefinition = depthOption,
|
||||
OptionDefinitionId = depthOption.Id,
|
||||
OptionValue = depth34Value,
|
||||
OptionValueId = depth34Value.Id
|
||||
});
|
||||
|
||||
model.AttachVariant(red24Variant);
|
||||
model.AttachVariant(blue34Variant);
|
||||
|
||||
return new ModelContext(
|
||||
model,
|
||||
colorOption,
|
||||
depthOption,
|
||||
redValue,
|
||||
depth24Value,
|
||||
blue34Variant,
|
||||
red24Variant,
|
||||
depth34Value);
|
||||
}
|
||||
|
||||
private sealed record ModelContext(
|
||||
Product Model,
|
||||
OptionDefinition ColorOption,
|
||||
OptionDefinition DepthOption,
|
||||
OptionValue RedValue,
|
||||
OptionValue Depth24Value,
|
||||
Product Blue34Variant,
|
||||
Product Red24Variant,
|
||||
OptionValue Depth34Value);
|
||||
|
||||
private sealed class StubUniqueChecker : IUniqueChecker
|
||||
{
|
||||
public Task<bool> CategoryNameIsUnique(string name, CancellationToken cancellationToken = default) => Task.FromResult(true);
|
||||
|
||||
public Task<bool> ProductModelNameIsUnique(string name, CancellationToken cancellationToken = default) => Task.FromResult(true);
|
||||
|
||||
public Task<bool> ProductSlugIsUnique(string? slug, CancellationToken cancellationToken = default) => Task.FromResult(true);
|
||||
|
||||
public Task<bool> ProductSkuIsUnique(string sku, CancellationToken cancellationToken = default) => Task.FromResult(true);
|
||||
|
||||
public Task<bool> OptionCodeIsUniqueForProduct(Guid productId, string code, CancellationToken cancellationToken = default) => Task.FromResult(true);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user