ThreeKingdomsSlingshot/Assets/Tests/PlayMode/BootFlowTests.cs

138 lines
6.4 KiB
C#

using System.Collections;
using NUnit.Framework;
using TKS.OutGame;
using UnityEngine;
using UnityEngine.TestTools;
namespace TKS.Tests
{
/// <summary>
/// 게임 시작 흐름(PD 2026-11-13 「스플래쉬 → 리소스 다운로드가 필요하면 다운로드 화면 → 다 받으면 페이드 → 타이틀」).
/// ① 받을 것 없음 = 그 자리에서 바로 로비(흐름 객체·로딩 화면 없음 = 기존 시작과 같음) ② 받을 것 있음 = 로딩 화면 Download 세트 · 진행률이 오름
/// → 다 받은 뒤 페이드 아웃(로딩 화면 위 캔버스) → 로딩 화면 닫고 타이틀 훅 → 페이드 인 → 페이드 객체 정리 ③ 타이틀 훅이 없으면 페이드 사이에 로비
/// ④ 표 download 줄 공급자 = 표 값대로(C45).
/// </summary>
public class BootFlowTests
{
Camera cam;
// 타이틀 화면이 시작 때 등록한 훅(TitleScreen · RuntimeInitializeOnLoadMethod) — 이 테스트가 바꿨다가 끝나면 되돌림(뒤 테스트 영향 없음)
System.Func<Camera, System.Action, bool> savedTitle;
[SetUp]
public void SetUp()
{
LoadingTable.Reload();
PlayerPrefs.DeleteKey(BootFlow.PreviewKey);
savedTitle = BootFlow.TitleProvider;
BootFlow.OverrideDownloader = null;
BootFlow.TitleProvider = null;
cam = new GameObject("TestCam").AddComponent<Camera>();
cam.orthographic = true;
}
[TearDown]
public void TearDown()
{
BootFlow.OverrideDownloader = null;
BootFlow.TitleProvider = savedTitle;
LoadingScreen.HideCurrent();
if (BootFlow.Current != null) Object.Destroy(BootFlow.Current.gameObject);
foreach (var f in Object.FindObjectsByType<ScreenFader>(FindObjectsSortMode.None)) Object.Destroy(f.gameObject);
if (cam != null) Object.Destroy(cam.gameObject);
}
static IEnumerator Until(System.Func<bool> cond, float timeout, string what)
{
float t0 = Time.realtimeSinceStartup;
while (!cond())
{
if (Time.realtimeSinceStartup - t0 > timeout) Assert.Fail("시간 초과: " + what);
yield return null;
}
}
[Test]
public void NoDownload_GoesStraightToLobby()
{
BootFlow.OverrideDownloader = new NoDownload();
int lobby = 0;
var bf = BootFlow.Begin(cam, () => lobby++);
Assert.IsNull(bf, "받을 것 없음 = 흐름 객체 없음");
Assert.AreEqual(1, lobby, "그 자리에서 로비(기존 시작과 같음)");
Assert.IsNull(LoadingScreen.Current, "다운로드 화면 안 뜸");
}
[UnityTest]
public IEnumerator Download_ThenFade_ThenTitle()
{
BootFlow.OverrideDownloader = new SimulatedDownload(4f, 8f, 0.1f);
int title = 0, lobby = 0;
BootFlow.TitleProvider = (c, toLobby) =>
{
title++;
return true;
};
var bf = BootFlow.Begin(cam, () => lobby++);
Assert.IsNotNull(bf);
yield return Until(() => bf.State == BootFlow.Step.Download, 3f, "받기 단계");
var ls = LoadingScreen.Current;
Assert.IsNotNull(ls, "받기 = 로딩 화면");
Assert.AreEqual(LoadingMode.Download, ls.Mode);
Assert.AreEqual("download", ls.Set);
Assert.AreEqual(bf.Downloader.TotalBytes, ls.TotalBytes, "전체 용량 글자");
Assert.AreEqual(0, title + lobby, "받는 중 = 타이틀·로비 없음");
float p0 = ls.Shown;
yield return new WaitForSecondsRealtime(0.25f);
Assert.Greater(ls.Shown, p0, "진행률이 오름");
yield return Until(() => bf.State == BootFlow.Step.FadeOut, 5f, "페이드 아웃");
Assert.IsNotNull(bf.Fader);
Assert.IsNotNull(LoadingScreen.Current, "페이드 아웃 동안 로딩 화면 유지");
Assert.GreaterOrEqual(ls.Shown, 0.999f, "100 % 를 보인 뒤 페이드");
var fadeRow = LoadingTable.Load(BootFlow.TablePath).Find(r => r.kind == "option" && r.id == "fade");
var canvasRow = LoadingTable.First("option", "canvas");
Assert.AreEqual(fadeRow.size, bf.Fader.Canvas.sortingOrder, "페이드 정렬 순서 = 표");
Assert.Greater(bf.Fader.Canvas.sortingOrder, (int)canvasRow.a, "페이드 = 로딩 화면 위");
Assert.AreEqual(0, title + lobby);
yield return Until(() => bf == null || bf.State >= BootFlow.Step.Switch, 3f, "화면 바꿈");
Assert.IsNull(LoadingScreen.Current, "검정 뒤에서 로딩 화면 닫음");
Assert.AreEqual(1, title, "타이틀 훅 1번");
Assert.AreEqual(0, lobby, "타이틀이 떴으면 로비는 시작 눌림 때");
yield return Until(() => bf == null, 3f, "흐름 끝");
yield return null;
Assert.AreEqual(0, Object.FindObjectsByType<ScreenFader>(FindObjectsSortMode.None).Length, "페이드 객체 정리");
Assert.IsNull(BootFlow.Current);
}
[UnityTest]
public IEnumerator Download_NoTitle_LobbyBehindFade()
{
BootFlow.OverrideDownloader = new SimulatedDownload(2f, 8f, 0f);
int lobby = 0;
float alphaAtLobby = -1f;
BootFlow bf = null;
bf = BootFlow.Begin(cam, () =>
{
lobby++;
if (bf != null && bf.Fader != null) alphaAtLobby = bf.Fader.Alpha;
});
Assert.IsNotNull(bf);
yield return Until(() => bf == null, 8f, "흐름 끝");
Assert.AreEqual(1, lobby, "타이틀 훅 없음 = 로비 1번");
Assert.AreEqual(1f, alphaAtLobby, 0.001f, "로비는 검정으로 덮인 뒤 바뀜");
}
[Test]
public void Table_Provider_FollowsTable()
{
var r = LoadingTable.Load(BootFlow.TablePath).Find(x => x.kind == "option" && x.id == "download");
Assert.IsNotNull(r, "표 download 줄");
var dl = BootFlow.FromTable();
if (r.text.ToLowerInvariant() == "simulate") Assert.IsInstanceOf<SimulatedDownload>(dl);
else Assert.IsInstanceOf<NoDownload>(dl);
}
}
}