mirror of
https://github.com/JogmansonReal/Radicade.git
synced 2026-10-25 15:09:26 -07:00
147 lines
6.0 KiB
C#
147 lines
6.0 KiB
C#
using System.Security.Claims;
|
|
using System.Text.Json;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.Data.Sqlite;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using RadicadeServer.API.Compatibility;
|
|
using RadicadeServer.API.Config;
|
|
using RadicadeServer.API.Storefront;
|
|
using RadicadeServer.DB;
|
|
using RadicadeServer.RecNet.Accounts;
|
|
using RadicadeServer.RecNet.Avatar;
|
|
using RadicadeServer.RecNet.Enums;
|
|
using RadicadeServer.RecNet.Enums.Store;
|
|
using RadicadeServer.RecNet.Store;
|
|
using Xunit;
|
|
|
|
namespace RadicadeServer.Tests;
|
|
|
|
/// <summary>
|
|
/// The free-gift button and the "Star Boxes" in the Rec Center storefront.
|
|
///
|
|
/// Three separate causes sat behind the gift complaints: the free-gift button config answered
|
|
/// <c>false</c> (the client's "this feature has been temporarily disabled" screen), sendmultiple
|
|
/// answered an empty array where the client reads a two-field result (so a 200 still surfaced as
|
|
/// "Failed to SendFreeGift"), and a star box - a drop that names a rarity instead of an item - was
|
|
/// granted empty, so buying the 2/3/4-star box did nothing at all.
|
|
/// </summary>
|
|
public class GiftClusterTests
|
|
{
|
|
private const long BuyerId = 55;
|
|
|
|
private static DbContextOptions<RecDBContext> MemoryOptions() =>
|
|
TestDbOptions.Create()
|
|
.UseInMemoryDatabase(Guid.NewGuid().ToString())
|
|
.Options;
|
|
|
|
/// <summary>
|
|
/// The purchase path opens its own transaction, which the in-memory provider refuses, so this
|
|
/// suite uses SQLite - the same reason the registration tests do.
|
|
/// </summary>
|
|
/// <summary>
|
|
/// The star boxes are resolved from the avatar catalogue the server ships, so the test loads the
|
|
/// same files the server does. Without it the catalogue is the one-item starter fallback and no
|
|
/// box could resolve anything, which would make the assertion below pass for the wrong reason.
|
|
/// </summary>
|
|
private static void LoadShippedCatalog() => DBConfig.LoadFiles();
|
|
|
|
private static async Task<(SqliteConnection Connection, RecDBContext Db)> OpenDbAsync()
|
|
{
|
|
var connection = new SqliteConnection("DataSource=:memory:");
|
|
await connection.OpenAsync();
|
|
var options = TestDbOptions.Create().UseSqlite(connection).Options;
|
|
var db = new RecDBContext(options);
|
|
await db.Database.EnsureCreatedAsync();
|
|
return (connection, db);
|
|
}
|
|
|
|
[Fact]
|
|
public void TheFreeGiftButtonIsReportedAsEnabled()
|
|
{
|
|
using var db = new RecDBContext(MemoryOptions());
|
|
|
|
var result = Assert.IsType<OkObjectResult>(new ConfigAPI(db).GetFreeGiftButtonConfig());
|
|
|
|
Assert.Equal(true, result.Value);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task SendMultipleAnswersTheClientsTwoFieldResult()
|
|
{
|
|
// The response DTO (RecNet.OMJLLFDFEJL) is a success flag and an error string, so even a
|
|
// refusal has to come back in that shape - the empty array this route once answered could
|
|
// not be read into it and surfaced as "Failed to SendFreeGift" against a 200. The send
|
|
// itself (boxes, items, the daily cooldown) is covered by FriendotronTests.
|
|
using var db = new RecDBContext(MemoryOptions());
|
|
var api = new CompatibilityAPI(db);
|
|
|
|
var identity = new ClaimsIdentity("TestAuth");
|
|
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, BuyerId.ToString()));
|
|
api.ControllerContext = new ControllerContext
|
|
{
|
|
HttpContext = new DefaultHttpContext { User = new ClaimsPrincipal(identity) }
|
|
};
|
|
|
|
var result = Assert.IsType<OkObjectResult>(await api.SendFreeGifts());
|
|
using var document = JsonDocument.Parse(JsonSerializer.Serialize(result.Value));
|
|
|
|
Assert.False(document.RootElement.GetProperty("ALOCDGMHFKA").GetBoolean());
|
|
Assert.Equal("No recipients were given.", document.RootElement.GetProperty("FBILGKFKFJE").GetString());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task SendMultipleRefusesACallWithNoResolvedAccount()
|
|
{
|
|
using var db = new RecDBContext(MemoryOptions());
|
|
var api = new CompatibilityAPI(db)
|
|
{
|
|
ControllerContext = new ControllerContext
|
|
{
|
|
HttpContext = new DefaultHttpContext { User = new ClaimsPrincipal(new ClaimsIdentity()) }
|
|
}
|
|
};
|
|
|
|
Assert.IsType<UnauthorizedResult>(await api.SendFreeGifts());
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(541, 10)]
|
|
[InlineData(538, 20)]
|
|
[InlineData(539, 30)]
|
|
public async Task AStarBoxGrantsARandomCatalogueItemOfThatRarity(int purchasableItemId, int expectedRarity)
|
|
{
|
|
LoadShippedCatalog();
|
|
|
|
var (connection, db) = await OpenDbAsync();
|
|
await using var disposeConnection = connection;
|
|
await using var disposeDb = db;
|
|
|
|
db.Currency.Add(new Currency { AccountId = BuyerId, RecTokens = 100_000 });
|
|
await db.SaveChangesAsync();
|
|
|
|
var outcome = await StorefrontShared.ExecutePurchaseAsync(
|
|
db, BuyerId, StorefrontTypes.RecCenter, purchasableItemId,
|
|
CurrencyType.RecCenterTokens, null, null);
|
|
|
|
Assert.True(outcome.Success, outcome.ErrorDetail);
|
|
var update = Assert.Single(outcome.Response!.BalanceUpdates);
|
|
Assert.Equal(UpdateResponseTypes.OK, update.UpdateResponse);
|
|
|
|
var gifted = Assert.Single(update.Data);
|
|
Assert.False(gifted.IsQuery);
|
|
Assert.False(string.IsNullOrWhiteSpace(gifted.FriendlyName));
|
|
Assert.Equal(expectedRarity, (int)gifted.Rarity);
|
|
Assert.False(string.IsNullOrWhiteSpace(gifted.AvatarItemDesc));
|
|
|
|
// The box must hand over a real catalogued item of that rarity - not an empty drop.
|
|
var catalogueItem = AvatarUnlockCatalog.FindItem(gifted.AvatarItemDesc);
|
|
Assert.NotNull(catalogueItem);
|
|
Assert.Equal(expectedRarity, catalogueItem!.Rarity);
|
|
|
|
var row = await db.Gifts.AsNoTracking().SingleAsync(x => x.AccountId == BuyerId);
|
|
Assert.Contains(StorefrontShared.ParseGiftList(row.Data),
|
|
pending => pending.AvatarItemDesc == gifted.AvatarItemDesc);
|
|
}
|
|
}
|