using Morph.AiKit.Media; using Xunit; namespace Morph.AiKit.Tests; /// /// Canarios de . /// /// /// A afirmacao que este arquivo protege nao e "aprovar funciona" — e que /// delega ao em vez de reimplementar /// a regra. Uma segunda copia de "so Approved publica" e exatamente como as duas divergem, e /// e o padrao de falha que esta epic catalogou sete vezes: o teste mede uma COPIA do objeto. /// public sealed class MediaReviewTests { private static readonly DateTimeOffset T0 = new(2026, 9, 8, 12, 0, 0, TimeSpan.Zero); private static MediaDisclosure Label => MediaDisclosure.Create("Imagem gerada por IA", "legenda", T0); private static MediaJob Generated() { var job = MediaJob.Create( new MediaRequest("catalogo", "um sofa verde", MediaPurpose.CatalogPhoto), new MediaIdempotencyKey("chave"), T0).StartGenerating().Value; return job.MarkGenerated( new MediaHash("abc"), "ab/c/abc.png", new MediaProvenance("openai", "gpt-image-2", "p", null, [], "-", null, 0m, T0, true)).Value; } /// O atalho aprova e carimba. [Fact] public void ApproveDelegatesAndStamps() { var result = MediaReview.Approve(Generated(), "lucas", T0, "ok"); Assert.True(result.IsSuccess); Assert.Equal(MediaJobState.Approved, result.Value.State); Assert.Equal("lucas", result.Value.Review!.Reviewer); } /// Rejeitar e terminal e tambem carimba. [Fact] public void RejectDelegatesAndStamps() { var result = MediaReview.Reject(Generated(), "lucas", T0, "cor errada"); Assert.True(result.IsSuccess); Assert.Equal(MediaJobState.Rejected, result.Value.State); Assert.Equal(MediaReviewDecision.Rejected, result.Value.Review!.Decision); } /// /// O atalho de publicar NAO tem uma regra propria: ele recusa exatamente onde /// recusa. Confere-se comparando as DUAS chamadas sobre o /// MESMO job — se MediaReview tivesse copiado a regra, aqui e onde a copia /// divergiria. /// [Fact] public void PublishThroughTheReviewFacadeAgreesWithTheJobItself() { var generated = Generated(); var approved = generated.Approve(MediaReview.ApprovedBy("lucas", T0)).Value; Assert.Equal(generated.Publish(Label, T0).IsSuccess, MediaReview.Publish(generated, Label, T0).IsSuccess); Assert.Equal(approved.Publish(Label, T0).IsSuccess, MediaReview.Publish(approved, Label, T0).IsSuccess); Assert.False(MediaReview.Publish(generated, Label, T0).IsSuccess); Assert.True(MediaReview.Publish(approved, Label, T0).IsSuccess); } /// Job nulo e falha de composicao, nao Result: quem chama errou o codigo. [Fact] public void ANullJobIsAProgrammingError() => Assert.Throws(() => MediaReview.Approve(null!, "lucas", T0)); /// Um juiz LLM cabe na nota, nunca no campo do revisor de uma foto de catalogo. [Fact] public void TheNoteCarriesThePreFilterVerdict() { var review = MediaReview.ApprovedBy("lucas", T0, "juiz LLM: 8/10 em fidelidade de cor"); Assert.Equal("lucas", review.Reviewer); Assert.Contains("juiz LLM", review.Note, StringComparison.Ordinal); } }