Files
SVSimServer/SVSim.UnitTests/Services/CurrencySpendServiceTests.cs

92 lines
3.6 KiB
C#

using SVSim.Database.Enums;
using SVSim.Database.Models;
using SVSim.Database.Services;
namespace SVSim.UnitTests.Services;
public class CurrencySpendServiceTests
{
private sealed class FakeEntitlements : IViewerEntitlements
{
public bool IsFreeplay { get; init; }
public long FreeplayAmount { get; init; } = 99999;
public long EffectiveBalance(Viewer viewer, SpendCurrency currency)
{
if (IsFreeplay && currency != SpendCurrency.SpotPoint) return FreeplayAmount;
return currency switch
{
SpendCurrency.Crystal => (long)viewer.Currency.Crystals,
SpendCurrency.Rupee => (long)viewer.Currency.Rupees,
SpendCurrency.RedEther => (long)viewer.Currency.RedEther,
SpendCurrency.SpotPoint => (long)viewer.Currency.SpotPoints,
_ => 0,
};
}
public bool OwnsCard(Viewer viewer, long cardId) => IsFreeplay;
public bool OwnsCosmetic(Viewer viewer, CosmeticType type, int id) => IsFreeplay;
public Task<IReadOnlyList<OwnedCardEntry>> EffectiveOwnedCardsAsync(Viewer viewer, CancellationToken ct = default)
=> Task.FromResult<IReadOnlyList<OwnedCardEntry>>(new List<OwnedCardEntry>());
public Task<EffectiveCosmetics> EffectiveCosmeticsAsync(Viewer viewer, CancellationToken ct = default)
=> throw new NotSupportedException();
}
private static Viewer NewViewer() => new() { Currency = new ViewerCurrency() };
[Test]
public async Task Normal_deducts_and_returns_post_state()
{
var v = NewViewer();
v.Currency.Crystals = 250;
var svc = new CurrencySpendService(new FakeEntitlements { IsFreeplay = false });
var r = await svc.TrySpendAsync(v, SpendCurrency.Crystal, 100);
Assert.That(r.Success, Is.True);
Assert.That(r.PostStateTotal, Is.EqualTo(150));
Assert.That(v.Currency.Crystals, Is.EqualTo(150UL));
}
[Test]
public async Task Normal_insufficient_does_not_deduct()
{
var v = NewViewer();
v.Currency.Rupees = 50;
var svc = new CurrencySpendService(new FakeEntitlements { IsFreeplay = false });
var r = await svc.TrySpendAsync(v, SpendCurrency.Rupee, 100);
Assert.That(r.Success, Is.False);
Assert.That(r.Outcome, Is.EqualTo(SpendOutcome.Insufficient));
Assert.That(v.Currency.Rupees, Is.EqualTo(50UL), "no deduction on insufficient funds");
}
[Test]
public async Task Freeplay_main_currency_succeeds_without_deducting()
{
var v = NewViewer();
v.Currency.Crystals = 10;
var svc = new CurrencySpendService(new FakeEntitlements { IsFreeplay = true });
var r = await svc.TrySpendAsync(v, SpendCurrency.Crystal, 100000);
Assert.That(r.Success, Is.True, "freeplay never blocks on affordability");
Assert.That(r.PostStateTotal, Is.EqualTo(99999), "post-state shows the freeplay balance");
Assert.That(v.Currency.Crystals, Is.EqualTo(10UL), "DB balance untouched in freeplay");
}
[Test]
public async Task Freeplay_spot_points_still_deduct()
{
var v = NewViewer();
v.Currency.SpotPoints = 300;
var svc = new CurrencySpendService(new FakeEntitlements { IsFreeplay = true });
var r = await svc.TrySpendAsync(v, SpendCurrency.SpotPoint, 100);
Assert.That(r.Success, Is.True);
Assert.That(r.PostStateTotal, Is.EqualTo(200));
Assert.That(v.Currency.SpotPoints, Is.EqualTo(200UL), "spot points are real even in freeplay");
}
}