XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Xml.Linq;
using XFEEDToolBox.Core.Models;
using XFEEDToolBox.Core.Navigation;
using XFEEDToolBox.Core.Notifications;
using XFEExtension.NetCore.XUnit.Attributes;

namespace XFEEDToolBox.Test;

[TestFixture]
public class NavigationArrivalTests
{
    private static readonly DateTimeOffset At=DateTimeOffset.Parse("2026-10-23T04:00:00Z");
    private static PlayerState Player()=>new(){InGame=true,CommanderId="commander",LoadGameAt=At,SystemName="Sol",Navigation=new(){CurrentSystemAddress=42}};
    private static NavigationProgress Progress(NavigationRunState state,string destination="Sol")=>new(state,destination,"已抵达","");
    [Test] public void OnlyConfirmedCompletionNotifiesOnceAndAnotherRunCanNotifyAgain()
    {
        var observer=new NavigationArrivalObserver();var player=Player();
        Check.That(observer.Observe(Progress(NavigationRunState.Completed),player,At) is null);
        Check.That(observer.Observe(Progress(NavigationRunState.Running),player,At) is null);
        var arrival=observer.Observe(Progress(NavigationRunState.Completed),player,At)!;
        Check.Equal(42L,arrival.SystemAddress);Check.Equal("Sol",arrival.Destination);
        Check.That(observer.Observe(Progress(NavigationRunState.Completed),player,At) is null);
        observer.Observe(Progress(NavigationRunState.Running),player,At);
        Check.That(observer.Observe(Progress(NavigationRunState.Completed),player,At) is not null);
    }
    [Test] public void StopsErrorsWrongSystemsAndUnconfirmedJumpsDoNotNotify()
    {
        foreach(var state in new[]{NavigationRunState.Stopped,NavigationRunState.Failed,NavigationRunState.Idle})
        {
            var observer=new NavigationArrivalObserver();observer.Observe(Progress(NavigationRunState.Running),Player(),At);
            Check.That(observer.Observe(Progress(state),Player(),At) is null);
        }
        foreach(var player in new[]{Player() with{InGame=false},Player() with{SystemName="Achenar"},Player() with{Navigation=new(){CurrentSystemAddress=42,JumpInProgress=true}}})
        {
            var observer=new NavigationArrivalObserver();observer.Observe(Progress(NavigationRunState.Running),Player(),At);
            Check.That(observer.Observe(Progress(NavigationRunState.Completed),player,At) is null);
        }
    }
    [Test] public void StationArrivalRequiresTheConfirmedRequestedDockingPort()
    {
        var target=new SystemNavigationTarget(42,99,"Galileo",SystemTargetKind.Station,500);
        foreach(var player in new[]{Player(),Player() with{Docked=true,MarketId=600}})
        {
            var observer=new NavigationArrivalObserver();observer.Observe(new SystemNavigationProgress(NavigationRunState.Running,target,SystemNavigationPhase.NormalApproach,""),player,At);
            Check.That(observer.Observe(new SystemNavigationProgress(NavigationRunState.Completed,target,SystemNavigationPhase.Completed,""),player,At) is null);
        }
        var docked=Player() with{Docked=true,MarketId=500};var success=new NavigationArrivalObserver();
        success.Observe(new SystemNavigationProgress(NavigationRunState.Running,target,SystemNavigationPhase.NativeLanding,""),docked,At);
        var arrival=success.Observe(new SystemNavigationProgress(NavigationRunState.Completed,target,SystemNavigationPhase.Completed,""),docked,At)!;
        Check.Equal("Galileo",arrival.Destination);Check.Equal("current-system",arrival.Page);Check.That(arrival.Docked);
    }
    [Test] public void ScreenshotSceneIsBoundToTheCommanderSessionAndSystem()
    {
        var player=Player();var observer=new NavigationArrivalObserver();observer.Observe(Progress(NavigationRunState.Running),player,At);
        var arrival=observer.Observe(Progress(NavigationRunState.Completed),player,At)!;
        Check.That(arrival.SameScene(player));Check.That(!arrival.SameScene(player with{CommanderId="other"}));
        Check.That(!arrival.SameScene(player with{LoadGameAt=At.AddHours(1)}));
        Check.That(!arrival.SameScene(player with{Navigation=new(){CurrentSystemAddress=99}}));
    }
    [Test] public void ACompletionFromAnOlderCommanderOrSessionCannotNotifyTheNewSession()
    {
        foreach(var changed in new[]{Player() with{CommanderId="other"},Player() with{LoadGameAt=At.AddHours(1)}})
        {
            var observer=new NavigationArrivalObserver();observer.Observe(Progress(NavigationRunState.Running),Player(),At);
            Check.That(observer.Observe(Progress(NavigationRunState.Completed),changed,At) is null);
        }
    }
    [Test] public void NativeToastEscapesTextAndUsesTheLocalFullWidthHeroAndClickArguments()
    {
        var arrival=new NavigationArrival("id",42,"A & B","<Galileo>",false,false,"",At,At);
        var image=Path.GetFullPath("arrival with space & name.png");var xml=ArrivalToastContent.Build(arrival,image);var toast=XElement.Parse(xml);
        Check.Equal("已抵达 <Galileo>",toast.Descendants("text").First().Value);
        Check.Equal("hero",toast.Descendants("image").Single().Attribute("placement")!.Value);
        Check.Equal(new Uri(image).AbsoluteUri,toast.Descendants("image").Single().Attribute("src")!.Value);
        Check.Equal("action=arrival&page=navigation&system=42",toast.Attribute("launch")!.Value);
        Check.That(!XElement.Parse(ArrivalToastContent.Build(arrival)).Descendants("image").Any());
    }
    [Test] public void BrightWarmAndBlueStellarDiscsAreRecognized()
    {
        foreach(var colour in new[]{(R:(byte)255,G:(byte)130,B:(byte)30),(R:(byte)150,G:(byte)185,B:(byte)255)})
        {
            var pixels=Frame((x,y)=>(x-160)*(x-160)+(y-55)*(y-55)<18*18?colour:((byte)2,(byte)3,(byte)8));
            Check.That(StarFrameCandidate.HasStar(320,180,pixels));
        }
    }
    [Test] public void BlankTransitionAndBottomHudFramesCannotBeUsedAsStarPictures()
    {
        foreach(var pixels in new[]{Frame((_,_)=>(0,0,0)),Frame((_,_)=>(255,255,255)),Frame((x,y)=>y>160&&x is >40 and <280?((byte)255,(byte)180,(byte)20):((byte)2,(byte)3,(byte)8))})
            Check.That(!StarFrameCandidate.HasStar(320,180,pixels));
    }
    [Test] public void InvalidScreenshotDimensionsAreRejected()
    {
        Check.That(!StarFrameCandidate.HasStar(1,1,new byte[4]));Check.That(!StarFrameCandidate.HasStar(320,180,new byte[8]));
    }
    private static byte[] Frame(Func<int,int,(byte R,byte G,byte B)> pixel)
    {
        var pixels=new byte[320*180*4];
        for(var y=0;y<180;y++)for(var x=0;x<320;x++){var (r,g,b)=pixel(x,y);var p=(y*320+x)*4;pixels[p]=b;pixels[p+1]=g;pixels[p+2]=r;pixels[p+3]=255;}
        return pixels;
    }
}