using XFEEDToolBox.Core.Engineering; using XFEEDToolBox.Core.Models; using XFEEDToolBox.Core.Navigation; using XFEEDToolBox.Core.Outfitting; using XFEEDToolBox.Core.Presentation; using XFEExtension.NetCore.XUnit.Attributes; namespace XFEEDToolBox.Test; [TestFixture] public class InterfaceRefinementTests { private static NavigationLegPreview Leg(int number)=>new(number,number,$"Star {number}","K",20,true,false,number==1,null); [Test] public void RouteHistorySurvivesSuffixUpdatesAndArrivalClearing() { var route=new NavigationItinerary();route.UpdateRoute([Leg(1),Leg(2),Leg(3)]);route.ConfirmPosition(1); route.UpdateRoute([Leg(2) with{Number=1},Leg(3) with{Number=2}]); var rows=route.Present(NavigationRunState.Running,"正在充能","Star 2"); Check.Equal(3,rows.Count);Check.Equal(NavigationLegState.Completed,rows[0].Status); Check.Equal(NavigationLegState.Running,rows[1].Status);Check.Equal("正在充能",rows[1].Message);Check.Equal(2,rows[1].Number); Check.Equal(NavigationLegState.Waiting,rows[2].Status);Check.Equal("",rows[2].Message); route.ConfirmPosition(3);route.UpdateRoute([]);Check.That(route.Present(NavigationRunState.Completed).All(r=>r.Status==NavigationLegState.Completed)); } [Test] public void FailureAndCancellationOnlyMarkThePendingHop() { var route=new NavigationItinerary();route.UpdateRoute([Leg(1),Leg(2),Leg(3)]);route.ConfirmPosition(1); foreach(var (state,expected) in new[]{(NavigationRunState.Failed,NavigationLegState.Error),(NavigationRunState.Stopped,NavigationLegState.Warning)}) { var rows=route.Present(state,"测试状态");Check.Equal(NavigationLegState.Completed,rows[0].Status);Check.Equal(expected,rows[1].Status);Check.Equal(NavigationLegState.Waiting,rows[2].Status); } route.Reset();Check.Equal(0,route.Present(NavigationRunState.Idle).Count); } [Test] public void ChangedGameRouteReplacesTheOldSequence() { var route=new NavigationItinerary();route.UpdateRoute([Leg(1),Leg(2),Leg(3)]); route.UpdateRoute([Leg(5),Leg(6)]);var rows=route.Present(NavigationRunState.Idle); Check.That(rows.Select(r=>r.SystemAddress).SequenceEqual(new long[]{5,6}));Check.That(rows.Select(r=>r.Number).SequenceEqual(new[]{1,2})); } [Test] public void LiveRefitUpdatesDoNotReplaceTheSelectedSlotOrPropertyRows() { var module=new FittedModule{Slot="LargeHardpoint1",Item="hpt_multicannon_gimbal_large",Health=1,Engineering=new(){Level=3,Quality=.65}}; var slot=new RefitSlot{Slot=module.Slot,Module=module,Category="hardpoint",Capacity=3}; var slots=new LiveCollection(s=>s.Slot,s=>new(s));slots.Apply([slot]);var selected=slots.Single(); var events=new List();selected.PropertyChanged+=(_,e)=>events.Add(e.PropertyName!); var delta=slots.Apply([slot with{Module=module with{Health=.8,Engineering=module.Engineering with{Level=4,Quality=.2}}}]); Check.That(ReferenceEquals(selected,slots.Single()));Check.Equal(0,delta.Added+delta.Removed+delta.Moved);Check.Equal("G4",selected.CurrentGrade);Check.That(!events.Contains(nameof(RefitSlotLiveRow.IconItem))); var properties=new LiveCollection(p=>p.OriginalName,p=>new(p)); properties.Apply([new("完整度","Integrity","100%")]);var health=properties.Single(); var change=properties.Apply([new("完整度","Integrity","80%")]);Check.That(ReferenceEquals(health,properties.Single()));Check.Equal("80%",health.Value);Check.Equal(0,change.Added+change.Removed); } [Test] public void ModuleBrowserOnlyOffersCompatibleTypesThenTheirModels() { var catalog=OutfittingCatalog.Default;var doc=ShipRefit.Create(new(){ShipId=1,Type="anaconda",ConfigurationAt=DateTimeOffset.UtcNow,Modules=[]},catalog); var slots=new[]{doc.Slots.Single(s=>s.Slot=="SmallHardpoint1"),doc.Slots.Single(s=>s.Slot=="Slot01_Size7"),doc.Slots.Single(s=>s.Slot=="Military01")}; var choices=ShipRefit.Choices(new(),catalog); foreach(var slot in slots) { var compatible=RefitModuleBrowser.Compatible(doc,slot,choices,catalog);var types=RefitModuleBrowser.Types(compatible); Check.That(compatible.Count>0&&types.Count>0&&compatible.All(c=>ShipRefit.Fits(doc,slot,c.Definition,catalog))); Check.Equal(types.Count,types.Select(t=>t.Key).Distinct().Count()); foreach(var type in types)Check.That(compatible.Any(c=>XFEEDToolBox.Core.Outfitting.RefitModuleBrowser.TypeKey(c.Definition)==type.Key)&&!type.Name.Contains("1A ")); } } [Test] public void CancelledEngineeringCalculationDoesNotReturnAMaterialBudget() { using var stop=new CancellationTokenSource();stop.Cancel(); Check.Throws(()=>EngineeringPlanner.Calculate(EngineeringCatalog.Default,new(){Item="hpt_multicannon_gimbal_large"},"Overcharged Weapon",5,1,null,new(){Rank=5,Progress="Unlocked"},[],token:stop.Token)); } }