您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

158 行
6.5 KiB

using System;
using System.Collections;
using NUnit.Framework;
using Unity.Multiplayer.Samples.BossRoom.Client;
using Unity.Multiplayer.Samples.BossRoom.Visual;
using Unity.Multiplayer.Samples.Utilities;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.TestTools;
using VContainer;
namespace Unity.Multiplayer.Samples.BossRoom.Tests.Runtime
{
public class HostAndDisconnectTest
{
static int[] s_PlayerIndices = new int[] { 0, 1, 2, 3, 4, 5, 6, 7 };
NetworkManager m_NetworkManager;
IEnumerator WaitUntilMainMenuSceneIsLoaded()
{
// load Bootstrap scene
SceneManager.LoadSceneAsync(SceneNames.Startup);
// validate the loading of project's Bootstrap scene
yield return new TestUtilities.WaitForSceneLoad(SceneNames.Startup);
// Bootstrap scene is loaded, containing NetworkManager instance; cache it
m_NetworkManager = NetworkManager.Singleton;
Assert.That(m_NetworkManager != null);
// MainMenu is loaded as soon as Startup scene is launched, validate it is loaded
yield return new TestUtilities.WaitForSceneLoad(SceneNames.MainMenu);
yield return null;
}
IEnumerator WaitUntilCharacterIsSelectedAndReady(int playerIndex)
{
yield return new TestUtilities.WaitForSceneLoad(SceneNames.CharSelect);
yield return null;
// select a Character
var seatObjectName = $"PlayerSeat ({playerIndex})";
var playerSeat = GameObject.Find(seatObjectName);
Assert.That(playerSeat != null, $"{seatObjectName} not found!");
var uiCharSelectPlayerSeat = playerSeat.GetComponent<UICharSelectPlayerSeat>();
Assert.That(uiCharSelectPlayerSeat != null,
$"{nameof(UICharSelectPlayerSeat)} component not found on {playerSeat}!");
uiCharSelectPlayerSeat.OnClicked();
// selecting a class will enable the "Ready" button, next frame it is selectable
yield return null;
// hit ready
ClientCharSelectState.Instance.OnPlayerClickedReady();
}
/// <summary>
/// For now, just tests that the host has entered the BossRoom scene. Can become more complex in the future
/// (eg. testing networked abilities)
/// </summary>
/// <returns></returns>
IEnumerator WaitUntilBossRoomSceneIsLoaded()
{
yield return TestUtilities.AssertIsNetworkSceneLoaded(SceneNames.BossRoom, m_NetworkManager.SceneManager);
}
IEnumerator WaitUntilDisconnectedAndMainMenuSceneIsLoaded()
{
// once loaded into BossRoom scene, disconnect
var uiSettingsCanvas = GameObject.FindObjectOfType<UISettingsCanvas>();
Assert.That(uiSettingsCanvas != null, $"{nameof(UISettingsCanvas)} component not found!");
uiSettingsCanvas.OnClickQuitButton();
yield return new WaitForFixedUpdate();
var uiQuitPanel = GameObject.FindObjectOfType<UIQuitPanel>(true);
Assert.That(uiQuitPanel != null, $"{nameof(UIQuitPanel)} component not found!");
uiQuitPanel.Quit();
// Netcode TODO: OnNetworkDespawn() errors pop up here
// Line below should not be necessary, logged here: https://jira.unity3d.com/browse/MTT-3376
yield return new WaitForSeconds(1f);
// wait until shutdown is complete
yield return new WaitUntil(() => !m_NetworkManager.ShutdownInProgress);
Assert.That(!NetworkManager.Singleton.IsListening, "NetworkManager not fully shut down!");
// MainMenu is loaded as soon as a shutdown is encountered; validate it is loaded
yield return new TestUtilities.WaitForSceneLoad(SceneNames.MainMenu);
}
/// <summary>
/// Smoke test to validating hosting inside Boss Room. The test will load the project's bootstrap scene,
/// Startup, and commence the game IP flow as a host, pick and confirm a parametrized character, and jump into
/// the BossRoom scene, where the test will disconnect the host.
/// </summary>
[UnityTest]
public IEnumerator IP_HostAndDisconnect_Valid([ValueSource(nameof(s_PlayerIndices))] int playerIndex)
{
yield return WaitUntilMainMenuSceneIsLoaded();
var clientMainMenuState = GameObject.FindObjectOfType<ClientMainMenuState>();
Assert.That(clientMainMenuState != null, $"{nameof(clientMainMenuState)} component not found!");
var container = clientMainMenuState.Container;
var ipUIMediator = container.Resolve<IPUIMediator>();
Assert.That(ipUIMediator != null, $"{nameof(IPUIMediator)} component not found!");
var ipHostingUI = ipUIMediator.IPHostingUI;
Assert.That(ipHostingUI != null, $"{nameof(IPHostingUI)} component not found!");
// select "DIRECT IP" button
clientMainMenuState.OnDirectIPClicked();
yield return null;
// select the "HOST" button
ipHostingUI.OnCreateClick();
// confirming hosting will initialize the hosting process; next frame the results will be ready
yield return null;
// verify hosting is successful
Assert.That(m_NetworkManager.IsListening && m_NetworkManager.IsHost);
// CharSelect is loaded as soon as hosting is successful, validate it is loaded
yield return WaitUntilCharacterIsSelectedAndReady(playerIndex);
// selecting ready as host with no other party members will load BossRoom scene; validate it is loaded
yield return WaitUntilBossRoomSceneIsLoaded();
// Netcode TODO: the line below prevents a NullReferenceException on NetworkSceneManager.OnSceneLoaded
// Line below should not be necessary, logged here: https://jira.unity3d.com/browse/MTT-3376
yield return new WaitForSeconds(2f);
yield return WaitUntilDisconnectedAndMainMenuSceneIsLoaded();
}
[UnityTearDown]
public IEnumerator DestroySceneGameObjects()
{
foreach (var sceneGameObject in GameObject.FindObjectsOfType<GameObject>())
{
GameObject.DestroyImmediate(sceneGameObject);
}
yield break;
}
}
}