using System.Collections;
using System.Linq;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.TestTools;
namespace NightclubArcadia.PlayMode.Tests
{
///
/// The level must survive being loaded BEFORE the systems it depends on.
///
/// BootstrapTests only covers the happy order — Bootstrap loads Systems, then the
/// level, so by the time an NPC awakes the dialogue runner is already there. The
/// Editor does not guarantee that. Open the level on its own, or open scenes in a
/// different order, press Play, and NPCStandIn.Awake runs with no Systems scene in
/// sight. That produced:
///
/// [SceneServices] Bartender: could not resolve dialogueRunner
///
/// Resolving a cross-scene dependency in Awake is a race by construction. The fix
/// is to resolve at the point of use instead, so any load order works — and this is
/// the test that holds that property.
///
public class SceneOrderTests
{
const string Systems = "Systems";
const string Level = "SC101_ConferenceHall";
[UnityTearDown]
public IEnumerator TearDown()
{
yield return SceneManager.LoadSceneAsync("Bootstrap", LoadSceneMode.Single);
}
[UnityTest]
public IEnumerator LevelLoadedBeforeSystems_NpcsStillResolveTheirRunner()
{
// deliberately the wrong way round
yield return SceneManager.LoadSceneAsync(Level, LoadSceneMode.Single);
yield return SceneManager.LoadSceneAsync(Systems, LoadSceneMode.Additive);
for (var i = 0; i < 3; i++)
{
yield return null;
}
var npcs = Object.FindObjectsByType(
FindObjectsInactive.Include, FindObjectsSortMode.None);
Assert.IsNotEmpty(npcs, "Expected NPCs in the level scene");
// Read the serialized field BEFORE touching the lazy property, which caches
// into it. If this is null, Awake really did run with no Systems scene — i.e.
// the race this test exists for is genuinely reproduced here, and the
// assertion below is not passing for free.
var eager = npcs.Count(n => n.dialogueRunner == null);
Debug.Log($"[Order] NPCs whose Awake-time resolution failed: {eager}/{npcs.Length}");
Assert.Greater(eager, 0,
"Awake-time resolution succeeded, so this test is not reproducing the race " +
"it was written for. Rewrite it before trusting it.");
foreach (var npc in npcs)
{
Assert.IsNotNull(npc.ResolvedDialogueRunner,
$"'{npc.name}' could not reach the DialogueRunner when the level loaded " +
"before Systems. Cross-scene resolution must not depend on load order.");
}
}
}
}