您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
158 行
6.5 KiB
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;
|
|
}
|
|
}
|
|
}
|