using BigRegister.Api.Data; using BigRegister.Api.Zgw; using BigRegister.Domain.Authorization; namespace BigRegister.Tests; /// /// Exercises the OpenZaak document source against a stub HttpMessageHandler (WP-51): an /// upload registers a DRC enkelvoudiginformatieobject, and linking to a zaak POSTs a /// zaakinformatieobject per document once a zaak URL is known. /// public class OpenZaakDocumentSourceTests { private const string DrcBase = "https://oz.example/documenten/api/v1"; private const string ZrcBase = "https://oz.example/zaken/api/v1"; private const string ZaaktypeUrl = "https://oz.example/catalogi/api/v1/zaaktypen/zt-registratie"; private const string InformatieobjecttypeUrl = "https://oz.example/catalogi/api/v1/informatieobjecttypen/iot-identiteit"; private static ZgwOptions Options() => new() { DrcBaseUrl = DrcBase, ZrcBaseUrl = ZrcBase, ClientId = "c", Secret = "s", Bronorganisatie = "123443210", UserRepresentation = "BIG-register BFF", InformatieobjecttypeUrls = new() { ["identiteit"] = InformatieobjecttypeUrl }, }; private static readonly CallerIdentity Caller = new("111222333", "Dr. Test", PrincipalRole.Drafter); [Fact] public void Upload_registers_an_eio_in_drc_and_persists_its_url_locally() { var options = Options(); var handler = new ZgwStubHandler(url => url switch { _ when url == $"{DrcBase}/enkelvoudiginformatieobjecten" => """{ "url": "https://oz.example/documenten/api/v1/enkelvoudiginformatieobjecten/eio-1" }""", _ => throw new InvalidOperationException($"unexpected ZGW call {url}"), }); var source = new OpenZaakDocumentSource(new HttpClient(handler), new ZgwTokenProvider(options), options); var response = source.Upload("local-1", "identiteit", "registratie", "paspoort.pdf", "application/pdf", "%PDF-1.4 fake"u8.ToArray(), Caller); Assert.Equal("local-1", response.LocalId); Assert.NotEmpty(response.DocumentId); // Registered locally too (dual-write, same reasoning as CreateZaak/WP-50) — content // preview/download keeps working regardless of Zgw:Enabled. var stored = DocumentStore.Get(response.DocumentId); Assert.NotNull(stored); Assert.Equal("https://oz.example/documenten/api/v1/enkelvoudiginformatieobjecten/eio-1", stored!.DrcUrl); var body = handler.BodyOf($"{DrcBase}/enkelvoudiginformatieobjecten"); Assert.Contains(InformatieobjecttypeUrl, body); Assert.Contains("123443210", body); // bronorganisatie Assert.Contains("paspoort.pdf", body); Assert.Contains(Convert.ToBase64String("%PDF-1.4 fake"u8.ToArray()), body); // inhoud // WP-59: "identiteit" is mapped to "vertrouwelijk" in the confidentialiteit stamdata. Assert.Contains("\"vertrouwelijkheidaanduiding\":\"vertrouwelijk\"", body); } [Fact] public void Upload_falls_back_to_openbaar_for_a_category_absent_from_the_confidentialiteit_table() { var options = Options(); options.InformatieobjecttypeUrls["org-logo"] = InformatieobjecttypeUrl; var handler = new ZgwStubHandler(url => """{ "url": "https://oz.example/documenten/api/v1/enkelvoudiginformatieobjecten/eio-2" }"""); var source = new OpenZaakDocumentSource(new HttpClient(handler), new ZgwTokenProvider(options), options); source.Upload("local-2", "org-logo", "org-template", "logo.png", "image/png", [1, 2, 3], Caller); var body = handler.BodyOf($"{DrcBase}/enkelvoudiginformatieobjecten"); Assert.Contains("\"vertrouwelijkheidaanduiding\":\"openbaar\"", body); } [Fact] public void Upload_throws_when_the_category_has_no_configured_informatieobjecttype() { var options = Options(); var handler = new ZgwStubHandler(url => throw new InvalidOperationException($"no HTTP call expected, got {url}")); var source = new OpenZaakDocumentSource(new HttpClient(handler), new ZgwTokenProvider(options), options); Assert.Throws(() => source.Upload("local-1", "unknown-category", "registratie", "f.pdf", "application/pdf", [1, 2, 3], Caller)); } [Fact] public void LinkToZaak_posts_a_zaakinformatieobject_per_document_once_a_zaak_exists() { var options = Options(); var uploadHandler = new ZgwStubHandler(url => """{ "url": "https://oz.example/documenten/api/v1/enkelvoudiginformatieobjecten/eio-1" }"""); var uploader = new OpenZaakDocumentSource(new HttpClient(uploadHandler), new ZgwTokenProvider(options), options); var doc = uploader.Upload("local-1", "identiteit", "registratie", "paspoort.pdf", "application/pdf", [1, 2, 3], Caller); var linkHandler = new ZgwStubHandler(url => url switch { _ when url == $"{ZrcBase}/zaakinformatieobjecten" => "{}", _ => throw new InvalidOperationException($"unexpected ZGW call {url}"), }); var linker = new OpenZaakDocumentSource(new HttpClient(linkHandler), new ZgwTokenProvider(options), options); linker.LinkToZaak([doc.DocumentId], $"{ZrcBase}/zaken/uuid-1", Caller); var body = linkHandler.BodyOf($"{ZrcBase}/zaakinformatieobjecten"); Assert.Contains($"{ZrcBase}/zaken/uuid-1", body); Assert.Contains("eio-1", body); // Local link also happened (dual-write) — the document is now Linked (delete blocked). Assert.Equal(DocumentStore.DeleteResult.Linked, DocumentStore.DeleteOwned(doc.DocumentId, Caller.Bsn)); } [Fact] public void LinkToZaak_makes_no_zgw_call_when_the_local_source_created_no_zaak() { var options = Options(); var handler = new ZgwStubHandler(url => throw new InvalidOperationException($"no HTTP call expected, got {url}")); var source = new OpenZaakDocumentSource(new HttpClient(handler), new ZgwTokenProvider(options), options); source.LinkToZaak(["some-document-id"], zaakUrl: null, Caller); Assert.Empty(handler.Requests); } }