using SameBeat.Domain.Encje;
using SameBeat.Domain.Enumy;
using SameBeat.Domain.Wyjatki;
using Xunit;
namespace SameBeat.Tests.Unit;
///
/// Testy "zegara" muzyki (ETAP 4) na encji Wydarzenie -- OdtworzOd/Wstrzymaj/Wznow/Zatrzymaj i
/// walidacja glosnosci. Testy przeliczania pozycji przy pause uzywaja krotkiego Thread.Sleep i
/// tolerancji czasowej -- to prawdziwy zegar (DateTime.UtcNow), nie fejk, wiec sprawdzamy przedzial,
/// nie dokladna wartosc co do milisekundy.
///
public class WydarzenieMuzykaTests
{
[Fact]
public void Utworz_MaDomyslnyStanMuzyki()
{
var wydarzenie = Wydarzenie.Utworz("Test");
Assert.Null(wydarzenie.UtworId);
Assert.Null(wydarzenie.CzasStartuUtc);
Assert.Equal(0, wydarzenie.PozycjaStartowaMs);
Assert.Equal(StanOdtwarzania.Zatrzymana, wydarzenie.StanOdtwarzania);
Assert.Equal(0.9f, wydarzenie.GlosnoscMaster);
}
[Fact]
public void OdtworzOd_UstawiaUtworPozycjeICzasStartu()
{
var wydarzenie = Wydarzenie.Utworz("Test");
var utworId = Guid.NewGuid();
var przed = DateTime.UtcNow;
wydarzenie.OdtworzOd(utworId, 5000);
Assert.Equal(utworId, wydarzenie.UtworId);
Assert.Equal(5000, wydarzenie.PozycjaStartowaMs);
Assert.Equal(StanOdtwarzania.Odtwarzana, wydarzenie.StanOdtwarzania);
Assert.NotNull(wydarzenie.CzasStartuUtc);
Assert.True(wydarzenie.CzasStartuUtc >= przed);
}
[Fact]
public void OdtworzOd_PustyUtworId_Rzuca()
{
var wydarzenie = Wydarzenie.Utworz("Test");
Assert.Throws(() => wydarzenie.OdtworzOd(Guid.Empty, 0));
}
[Fact]
public void OdtworzOd_UjemnaPozycja_Rzuca()
{
var wydarzenie = Wydarzenie.Utworz("Test");
Assert.Throws(() => wydarzenie.OdtworzOd(Guid.NewGuid(), -1));
}
[Fact]
public void Wstrzymaj_PrzeliczaPozycjeNaPodstawieUplynietegoCzasu()
{
var wydarzenie = Wydarzenie.Utworz("Test");
wydarzenie.OdtworzOd(Guid.NewGuid(), 1000);
Thread.Sleep(200); // symulujemy uplyw czasu -- prawdziwy zegar, nie fejk
wydarzenie.Wstrzymaj();
Assert.Equal(StanOdtwarzania.Wstrzymana, wydarzenie.StanOdtwarzania);
Assert.Null(wydarzenie.CzasStartuUtc);
// Zegar sie zgadza: pozycja startowa (1000ms) + realnie uplyniety czas (>=200ms), z hojnym
// gornym marginesem na wolne CI.
Assert.InRange(wydarzenie.PozycjaStartowaMs, 1100, 5000);
}
[Fact]
public void Wstrzymaj_GdyJuzWstrzymana_JestIdempotentneINieRuszaPozycji()
{
var wydarzenie = Wydarzenie.Utworz("Test");
wydarzenie.OdtworzOd(Guid.NewGuid(), 1000);
Thread.Sleep(50);
wydarzenie.Wstrzymaj();
var pozycjaPoPierwszymWstrzymaniu = wydarzenie.PozycjaStartowaMs;
wydarzenie.Wstrzymaj();
Assert.Equal(pozycjaPoPierwszymWstrzymaniu, wydarzenie.PozycjaStartowaMs);
Assert.Equal(StanOdtwarzania.Wstrzymana, wydarzenie.StanOdtwarzania);
}
[Fact]
public void Wznow_KontynuujeOdZapisanejPozycji_ZegarSieZgadza()
{
var wydarzenie = Wydarzenie.Utworz("Test");
wydarzenie.OdtworzOd(Guid.NewGuid(), 1000);
Thread.Sleep(100);
wydarzenie.Wstrzymaj();
var pozycjaWstrzymania = wydarzenie.PozycjaStartowaMs;
var przedWznowieniem = DateTime.UtcNow;
wydarzenie.Wznow();
Assert.Equal(StanOdtwarzania.Odtwarzana, wydarzenie.StanOdtwarzania);
// Wznowienie NIE rusza zapisanej pozycji startowej -- tylko przesuwa CzasStartuUtc na teraz,
// zeby (pozycjaStartowaMs + uplyw od CzasStartuUtc) po stronie klienta dalo dokladnie tam,
// gdzie muzyka zostala wstrzymana.
Assert.Equal(pozycjaWstrzymania, wydarzenie.PozycjaStartowaMs);
Assert.NotNull(wydarzenie.CzasStartuUtc);
Assert.True(wydarzenie.CzasStartuUtc >= przedWznowieniem);
}
[Fact]
public void Zatrzymaj_CzysciUtworICzasIZerujePozycje()
{
var wydarzenie = Wydarzenie.Utworz("Test");
wydarzenie.OdtworzOd(Guid.NewGuid(), 1000);
wydarzenie.Zatrzymaj();
Assert.Null(wydarzenie.UtworId);
Assert.Null(wydarzenie.CzasStartuUtc);
Assert.Equal(0, wydarzenie.PozycjaStartowaMs);
Assert.Equal(StanOdtwarzania.Zatrzymana, wydarzenie.StanOdtwarzania);
}
[Theory]
[InlineData(0.0f)]
[InlineData(1.0f)]
[InlineData(0.5f)]
public void UstawGlosnosc_WZakresie_Ustawia(float wartosc)
{
var wydarzenie = Wydarzenie.Utworz("Test");
wydarzenie.UstawGlosnosc(wartosc);
Assert.Equal(wartosc, wydarzenie.GlosnoscMaster);
}
[Theory]
[InlineData(-0.01f)]
[InlineData(1.01f)]
[InlineData(-5f)]
public void UstawGlosnosc_PozaZakresem_Rzuca(float wartosc)
{
var wydarzenie = Wydarzenie.Utworz("Test");
Assert.Throws(() => wydarzenie.UstawGlosnosc(wartosc));
}
}