using Xunit; using ytLive.Services; namespace ytLive.Tests; /// /// TASK 4 game audio bar: the default detector's provider wiring — it composes /// the full-screen monitor + loopback level into the hysteresis and raises /// IsGameAudioActiveChanged on transitions. The transition math itself lives in /// GameAudioHysteresisTests. /// public class GameAudioDetectorTests { [Fact] public void Poll_RaisesChanged_WhenGameAppearsAndLeaves() { var now = new DateTime(2026, 8, 13, 12, 0, 0); int? monitor = 0; var level = 0f; var detector = new GameAudioDetector(() => monitor, () => level, () => now); var changes = new List(); detector.IsGameAudioActiveChanged += a => changes.Add(a); level = 0.9f; detector.Poll(); Assert.False(detector.IsGameAudioActive); now = now.AddMilliseconds(600); detector.Poll(); Assert.True(detector.IsGameAudioActive); Assert.Equal(new[] { true }, changes); level = 0f; now = now.AddSeconds(2); detector.Poll(); Assert.True(detector.IsGameAudioActive); Assert.Equal(new[] { true }, changes); monitor = null; detector.Poll(); Assert.True(detector.IsGameAudioActive); now = now.AddSeconds(2); detector.Poll(); Assert.False(detector.IsGameAudioActive); Assert.Equal(new[] { true, false }, changes); } [Fact] public void Poll_StaysInactive_WhenNoFullScreenMonitor() { var detector = new GameAudioDetector(() => null, () => 0.9f); var changes = 0; detector.IsGameAudioActiveChanged += _ => changes++; for (var i = 0; i < 5; i++) detector.Poll(); Assert.False(detector.IsGameAudioActive); Assert.Equal(0, changes); } [Fact] public void Poll_StaysInactive_WhileLoopbackSilent() { var detector = new GameAudioDetector(() => 0, () => 0f); var changes = 0; detector.IsGameAudioActiveChanged += _ => changes++; for (var i = 0; i < 5; i++) detector.Poll(); Assert.False(detector.IsGameAudioActive); Assert.Equal(0, changes); } }