Files
ft/CodexOutput/upserver/KVGameLoadTests/OfferSchemaTests.cs

44 lines
2.9 KiB
C#

using game.PlayerDataStorage;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
static partial class Tests
{
static async Task RunOfferSchemaTests()
{
foreach(bool disco in new[] { false,true })
await Run(disco ? "M17-offer-nested-shape-and-enum" : "M16-offer-nested-shape-and-state",() =>
{
var obj=JObject.FromObject(new { FirstOpen=true,EventId=7,StartTime="2026-09-22T00:00:00.0000000Z",EndTime="2026-09-24T00:00:00.0000000Z",
ItemId=-1,LotteryNum=5,Items=new[] { new { Id=1,Item=2,Number=3,Status=2 } },RewardList=new[] { 8,9 },Finished=true,ChestReward=10 });
if (disco) { obj.Remove("Finished"); obj.Remove("ChestReward"); }
string key=disco ? "OfferDiscoPartyManager" : "OfferChainsChestData";
Dictionary<string,string> Raw(JObject value)=>new() { [key]=value.ToString(Formatting.None) };
var state=PlayerKVSaveSchema.DecodeOffer(Raw(obj),disco,SchemaSnapshot(),new());
Check(state.IsPresent && state.FirstOpen && state.EventId==7 && state.StartTime.Day==22 && state.EndTime.Day==24 &&
state.ItemId == -1 && state.LotteryNum==5,"all scalar fields");
Check(state.Items.Count==1 && state.Items[0].Id==1 && state.Items[0].Item==2 && state.Items[0].Number==3 && state.Items[0].Status==2 &&
state.RewardList.SequenceEqual(new[] { 8,9 }),"complete nested collections");
Check(disco || (state.Finished && state.ChestReward==10),"chains only fields");
Check(!PlayerKVSaveSchema.DecodeOffer(new Dictionary<string,string>(),disco,SchemaSnapshot(),new()).IsPresent,"missing explicit");
var paths=obj.Properties().Select(p=>p.Name).Concat(new[] { "Items[0]","Items[0].Id","Items[0].Item","Items[0].Number","Items[0].Status","RewardList[0]" });
foreach(var path in paths)
{
var bad=(JObject)obj.DeepClone(); bad.SelectToken(path).Replace(JValue.CreateNull());
Check(PlayerKVSaveSchema.DecodeOffer(Raw(bad),disco,SchemaSnapshot(),new())==null,"all consumed null fields rejected");
}
foreach(var path in new[] { "EventId","Items[0].Id","Items[0].Status","RewardList[0]" })
{
var bad=(JObject)obj.DeepClone(); bad.SelectToken(path).Replace(new JValue(1.5));
Check(PlayerKVSaveSchema.DecodeOffer(Raw(bad),disco,SchemaSnapshot(),new())==null,"integer coercion rejected");
}
if(disco)
{
var bad=(JObject)obj.DeepClone(); bad["Items"][0]["Status"]=3;
Check(PlayerKVSaveSchema.DecodeOffer(Raw(bad),true,SchemaSnapshot(),new())==null,"undefined enum rejected");
}
return Task.CompletedTask;
});
}
}