using System.Collections; using NUnit.Framework; using TKS.OutGame; using UnityEngine; using UnityEngine.TestTools; namespace TKS.Tests { /// /// 게임 시작 흐름(PD 2026-11-13 「스플래쉬 → 리소스 다운로드가 필요하면 다운로드 화면 → 다 받으면 페이드 → 타이틀」). /// ① 받을 것 없음 = 그 자리에서 바로 로비(흐름 객체·로딩 화면 없음 = 기존 시작과 같음) ② 받을 것 있음 = 로딩 화면 Download 세트 · 진행률이 오름 /// → 다 받은 뒤 페이드 아웃(로딩 화면 위 캔버스) → 로딩 화면 닫고 타이틀 훅 → 페이드 인 → 페이드 객체 정리 ③ 타이틀 훅이 없으면 페이드 사이에 로비 /// ④ 표 download 줄 공급자 = 표 값대로(C45). /// public class BootFlowTests { Camera cam; // 타이틀 화면이 시작 때 등록한 훅(TitleScreen · RuntimeInitializeOnLoadMethod) — 이 테스트가 바꿨다가 끝나면 되돌림(뒤 테스트 영향 없음) System.Func 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(); 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(FindObjectsSortMode.None)) Object.Destroy(f.gameObject); if (cam != null) Object.Destroy(cam.gameObject); } static IEnumerator Until(System.Func 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(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(dl); else Assert.IsInstanceOf(dl); } } }