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);
}
}