From b2a85f15ff30e5612289742d42b66ec91d543636 Mon Sep 17 00:00:00 2001 From: peter-va Date: Wed, 12 Aug 2026 15:10:02 -0700 Subject: [PATCH 1/5] fix some tests --- ...enSearchRequestLoggingInterceptorTest.java | 13 ++++--------- ...ermSuggestionFormControllerEmailTests.java | 15 +++++++++++++++ .../nci/evs/api/model/EmailDetailsTest.java | 2 +- .../TermSuggestionFormServiceTest.java | 19 ++++++++++++++++++- .../formSamples/submissionFormTest-cdisc.json | 2 +- .../formSamples/submissionFormTest-ncit.json | 2 +- 6 files changed, 40 insertions(+), 13 deletions(-) diff --git a/src/test/java/gov/nih/nci/evs/api/configuration/EvsOpenSearchRequestLoggingInterceptorTest.java b/src/test/java/gov/nih/nci/evs/api/configuration/EvsOpenSearchRequestLoggingInterceptorTest.java index 6733a9950..ef604a9fa 100644 --- a/src/test/java/gov/nih/nci/evs/api/configuration/EvsOpenSearchRequestLoggingInterceptorTest.java +++ b/src/test/java/gov/nih/nci/evs/api/configuration/EvsOpenSearchRequestLoggingInterceptorTest.java @@ -118,13 +118,11 @@ void logsSearchRequestDetailsAndPreservesPayload() throws Exception { new EvsOpenSearchRequestLoggingInterceptor().process(request, context); final String logMessage = getLoggedMessage(); - assertTrue(logMessage.contains("method = POST")); assertTrue( logMessage.contains( - "url = http://localhost:9201/my-index-000001/_search?" + "\n POST http://localhost:9201/my-index-000001/_search?" + "typed_keys=true&search_type=query_then_fetch")); - assertTrue(logMessage.contains("parameters = typed_keys=true&search_type=query_then_fetch")); - assertTrue(logMessage.contains("index = my-index-000001")); + assertTrue(logMessage.contains("\n my-index-000001 = ")); assertTrue(logMessage.contains("\"fields\"")); assertTrue(logMessage.contains("\"user.id\"")); assertTrue(logMessage.contains("\"_source\": false")); @@ -248,10 +246,7 @@ void logsRequestsWithoutPayload() throws Exception { new EvsOpenSearchRequestLoggingInterceptor().process(request, context); final String logMessage = getLoggedMessage(); - assertTrue(logMessage.contains("method = GET")); - assertTrue(logMessage.contains("url = http://localhost:9201/_cluster/health")); - assertTrue(logMessage.contains("parameters = ")); - assertTrue(logMessage.contains("index = ")); - assertTrue(logMessage.contains("payload =\n")); + assertTrue(logMessage.contains("\n GET http://localhost:9201/_cluster/health")); + assertTrue(logMessage.contains("\n = ")); } } diff --git a/src/test/java/gov/nih/nci/evs/api/controller/TermSuggestionFormControllerEmailTests.java b/src/test/java/gov/nih/nci/evs/api/controller/TermSuggestionFormControllerEmailTests.java index 5cb5a98f0..796556bd7 100644 --- a/src/test/java/gov/nih/nci/evs/api/controller/TermSuggestionFormControllerEmailTests.java +++ b/src/test/java/gov/nih/nci/evs/api/controller/TermSuggestionFormControllerEmailTests.java @@ -117,6 +117,11 @@ public void integrationTestSubmitForm() throws Exception { final String formPath = "formSamples/submissionFormTest-ncit.json"; JsonNode formData = createForm(formPath); + // Load the form template as the browser flow does, so the service allows this recipient + this.mvc + .perform(MockMvcRequestBuilders.get("/api/v1/form/suggest/ncit-form")) + .andExpect(status().isOk()); + final String requestBody = objectMapper.writeValueAsString(formData); log.info("Form data = {}", formData); @SuppressWarnings("unused") @@ -143,6 +148,11 @@ public void integrationTestSubmitFormWithAttachment() throws Exception { final String formPath = "formSamples/submissionFormTest-cdisc.json"; JsonNode formData = createForm(formPath); + // Load the form template as the browser flow does, so the service allows this recipient + this.mvc + .perform(MockMvcRequestBuilders.get("/api/v1/form/suggest/cdisc-form")) + .andExpect(status().isOk()); + // Prepare multipart file from resources final org.springframework.mock.web.MockMultipartFile attachment; try (final InputStream is = @@ -186,6 +196,11 @@ public void integrationTestSubmitFormWithAttachmentNCIT() throws Exception { final String formPath = "formSamples/testNCIT.json"; JsonNode formData = createForm(formPath); + // Load the form template as the browser flow does, so the service allows this recipient + this.mvc + .perform(MockMvcRequestBuilders.get("/api/v1/form/suggest/ncit-form")) + .andExpect(status().isOk()); + // Prepare NCIT multipart file from resources final org.springframework.mock.web.MockMultipartFile attachment; try (final InputStream is = diff --git a/src/test/java/gov/nih/nci/evs/api/model/EmailDetailsTest.java b/src/test/java/gov/nih/nci/evs/api/model/EmailDetailsTest.java index 1bd18a529..a7b233c87 100644 --- a/src/test/java/gov/nih/nci/evs/api/model/EmailDetailsTest.java +++ b/src/test/java/gov/nih/nci/evs/api/model/EmailDetailsTest.java @@ -64,7 +64,7 @@ public void testGenerateEmailDetailsPasses() throws Exception { // ASSERT assertNotNull(testDetails); assertEquals("NCIT", testDetails.getSource()); - assertEquals("agarcia@westcoastinformatics.com", testDetails.getToEmail()); + assertEquals("ncithesaurus@mail.nih.gov", testDetails.getToEmail()); assertEquals("bcarlsen@westcoastinformatics.com ", testDetails.getFromEmail()); } diff --git a/src/test/java/gov/nih/nci/evs/api/service/TermSuggestionFormServiceTest.java b/src/test/java/gov/nih/nci/evs/api/service/TermSuggestionFormServiceTest.java index 36322e052..b51def71f 100644 --- a/src/test/java/gov/nih/nci/evs/api/service/TermSuggestionFormServiceTest.java +++ b/src/test/java/gov/nih/nci/evs/api/service/TermSuggestionFormServiceTest.java @@ -83,7 +83,7 @@ public class TermSuggestionFormServiceTest { private final String source = "NCIT"; /** The to email. */ - private final String toEmail = "agarcia@westcoastinformatics.com"; + private final String toEmail = "ncithesaurus@mail.nih.gov"; /** The from email. */ private final String fromEmail = "test@example.com"; @@ -269,6 +269,7 @@ public void testGetFormTemplateWhenNotObjectThrowsException() throws Exception { public void testSendEmail() throws Exception { // SET UP testEmailDetails = createEmail(); + populateValidEmails(); when(javaMailSender.createMimeMessage()).thenReturn(mock(MimeMessage.class)); doNothing().when(javaMailSender).send(any(MimeMessage.class)); @@ -288,6 +289,7 @@ public void testSendEmail() throws Exception { public void testSendEmailThrowsException() throws Exception { // SETUP testEmailDetails = createEmail(); + populateValidEmails(); when(javaMailSender.createMimeMessage()).thenReturn(mock(MimeMessage.class)); // ACT @@ -529,4 +531,19 @@ private EmailDetails createEmail() { return testEmailDetails; } + + /** + * Populate the service's valid email set the same way the controller flow does: by loading the + * form template before sending. The remote fetch is mocked so the test stays hermetic. + * + * @throws Exception the exception + */ + private void populateValidEmails() throws Exception { + try (MockedStatic mockedUtils = Mockito.mockStatic(EVSUtils.class)) { + mockedUtils + .when(() -> EVSUtils.getValueFromFile(anyString())) + .thenReturn("{\"recipientEmail\": \"" + toEmail + "\"}"); + termFormService.getFormTemplate("ncit-form"); + } + } } diff --git a/src/test/resources/formSamples/submissionFormTest-cdisc.json b/src/test/resources/formSamples/submissionFormTest-cdisc.json index d2a342b72..e687a1b10 100644 --- a/src/test/resources/formSamples/submissionFormTest-cdisc.json +++ b/src/test/resources/formSamples/submissionFormTest-cdisc.json @@ -1,7 +1,7 @@ { "formName": "CDISC", "formType": "CDISC", - "recipientEmail": "agarcia@westcoastinformatics.com", + "recipientEmail": "NCIEvsCdiscHelp@mail.nih.gov", "businessEmail": "bcarlsen@westcoastinformatics.com ", "subject": "New Terminology Suggestion: TestTermName", "body": {"Contact Information": { "Business Email": "testEmail@email.com", "Other": "Test" }, "Term Information": { "Vocabulary": "NCI Thesaurus", "Term": "C65498", "Synonym(s)": "C431587, C94635", "Nearest Code/CUI": "nearest test", "Definition/Other": "this is definition" }, "Additional Information": { "Project/Product term needed for": "Project Term Form", "Reason for suggestion or any additional information": "random reason" } } diff --git a/src/test/resources/formSamples/submissionFormTest-ncit.json b/src/test/resources/formSamples/submissionFormTest-ncit.json index afbc9cff2..7cbfa59dc 100644 --- a/src/test/resources/formSamples/submissionFormTest-ncit.json +++ b/src/test/resources/formSamples/submissionFormTest-ncit.json @@ -1,7 +1,7 @@ { "formName": "NCIT", "formType": "NCIT", - "recipientEmail": "agarcia@westcoastinformatics.com", + "recipientEmail": "ncithesaurus@mail.nih.gov", "businessEmail": "bcarlsen@westcoastinformatics.com ", "subject": "New Terminology Suggestion: TestTermName", "body": {"Contact Information": { "Business Email": "testEmail@email.com", "Name": "John Doe" }, "Request Type": { "Please select": "Proposed New Concept", "Term": "TestTermName", "Synonym": "TestSynonym1, TestSynonym2", "Definition": "This is a test definition for the new concept" }, "Additional Information": { "Organization": "Test Organization", "Project": "Test Project", "Additional Information": "Additional test notes and context" } } From 92cd527630e03a460d8c2748607a7d3831c31e78 Mon Sep 17 00:00:00 2001 From: peter-va Date: Wed, 12 Aug 2026 17:00:50 -0700 Subject: [PATCH 2/5] edit HL7 tests for mini --- .../evs/api/controller/Hl7v30SampleTest.java | 48 +++++++++---------- 1 file changed, 22 insertions(+), 26 deletions(-) diff --git a/src/test/java/gov/nih/nci/evs/api/controller/Hl7v30SampleTest.java b/src/test/java/gov/nih/nci/evs/api/controller/Hl7v30SampleTest.java index 68e153bfe..f20c7d167 100644 --- a/src/test/java/gov/nih/nci/evs/api/controller/Hl7v30SampleTest.java +++ b/src/test/java/gov/nih/nci/evs/api/controller/Hl7v30SampleTest.java @@ -49,7 +49,7 @@ public static void setupClass() throws Exception { @Test public void testDuplicateCodeDisambiguation() throws Exception { - String url = "/api/v1/concept/search?terminology=hl7v30&term=41&include=parents&pageSize=20"; + String url = "/api/v1/concept/search?terminology=hl7v30&term=21&include=parents&pageSize=20"; log.info("Testing url - " + url); MvcResult result = testMvc.perform(get(url)).andExpect(status().isOk()).andReturn(); String content = result.getResponse().getContentAsString(); @@ -62,46 +62,42 @@ public void testDuplicateCodeDisambiguation() throws Exception { assertThat(list).isNotNull(); assertThat(list.getConcepts()).isNotNull(); assertThat(list.getConcepts().size()).isGreaterThanOrEqualTo(2); - assertThat(list.getConcepts()).extracting(Concept::getCode).contains("41-11255", "41-11672"); + assertThat(list.getConcepts()).extracting(Concept::getCode).contains("21-11260", "21-11652"); - Concept typhoid = + Concept varicella = list.getConcepts().stream() - .filter(concept -> concept.getCode().equals("41-11255")) + .filter(concept -> concept.getCode().equals("21-11260")) .findFirst() .orElseThrow(); Concept tribe = list.getConcepts().stream() - .filter(concept -> concept.getCode().equals("41-11672")) + .filter(concept -> concept.getCode().equals("21-11652")) .findFirst() .orElseThrow(); - assertThat(typhoid.getCode()).isEqualTo("41-11255"); - assertThat(typhoid.getTerminology()).isEqualTo("hl7v30"); - assertThat(typhoid.getName()).isEqualTo("typhoid, parenteral"); - assertThat(typhoid.getParents()).isNotEmpty(); - assertThat(typhoid.getParents().size()).isEqualTo(1); - assertThat(typhoid.getParents().get(0).getCode()).startsWith("VaccineType"); + assertThat(varicella.getCode()).isEqualTo("21-11260"); + assertThat(varicella.getTerminology()).isEqualTo("hl7v30"); + assertThat(varicella.getName()).isEqualTo("varicella"); + assertThat(varicella.getParents()).isNotNull(); - assertThat(tribe.getCode()).isEqualTo("41-11672"); + assertThat(tribe.getCode()).isEqualTo("21-11652"); assertThat(tribe.getTerminology()).isEqualTo("hl7v30"); - assertThat(tribe.getName()).isEqualTo("Cheyenne and Arapaho Tribes, Oklahoma"); - assertThat(tribe.getParents()).isNotEmpty(); - assertThat(tribe.getParents().size()).isEqualTo(1); - assertThat(tribe.getParents().get(0).getCode()).isEqualTo("_NativeEntityContiguous"); + assertThat(tribe.getName()).isEqualTo("Blue Lake Rancheria, California"); + assertThat(tribe.getParents()).isNotNull(); - url = "/api/v1/concept/hl7v30/41"; + url = "/api/v1/concept/hl7v30/21"; log.info("Testing url - " + url); testMvc.perform(get(url)).andExpect(status().isNotFound()); - assertDuplicateCodeMetadata("41-11255"); - assertDuplicateCodeMetadata("41-11672"); + assertDuplicateCodeMetadata("21-11260"); + assertDuplicateCodeMetadata("21-11652"); } @Test public void testSearchByOriginalCode() throws Exception { assertOriginalCodeSearch( - "/api/v1/concept/search?terminology=hl7v30&type=contains&codeList=41" + "/api/v1/concept/search?terminology=hl7v30&type=contains&codeList=21" + "&include=properties&pageSize=20"); } @@ -109,10 +105,10 @@ public void testSearchByOriginalCode() throws Exception { public void testMatchSearchByOriginalCode() throws Exception { assertOriginalCodeSearch( - "/api/v1/concept/search?terminology=hl7v30&type=match&term=41&include=properties" + "/api/v1/concept/search?terminology=hl7v30&type=match&term=21&include=properties" + "&pageSize=20"); assertOriginalCodeSearch( - "/api/v1/concept/search?terminology=hl7v30&type=startsWith&term=41&include=properties" + "/api/v1/concept/search?terminology=hl7v30&type=startsWith&term=21&include=properties" + "&pageSize=20"); } @@ -135,13 +131,13 @@ private void assertOriginalCodeSearch(final String url) throws Exception { assertThat(list).isNotNull(); assertThat(list.getConcepts()).isNotNull(); assertThat(list.getConcepts().size()).isGreaterThanOrEqualTo(2); - assertThat(list.getConcepts()).extracting(Concept::getCode).contains("41-11255", "41-11672"); + assertThat(list.getConcepts()).extracting(Concept::getCode).contains("21-11260", "21-11652"); assertThat( list.getConcepts().stream() .filter( concept -> - concept.getCode().equals("41-11255") - || concept.getCode().equals("41-11672"))) + concept.getCode().equals("21-11260") + || concept.getCode().equals("21-11652"))) .allSatisfy(this::assertOriginalCodeProperty); } @@ -175,7 +171,7 @@ private void assertOriginalCodeProperty(final Concept concept) { .anySatisfy( property -> { assertThat(property.getType()).isEqualTo("Original_Code"); - assertThat(property.getValue()).isEqualTo("41"); + assertThat(property.getValue()).isEqualTo("21"); }); } } From 6081959fb2e53431e169d79653a11203f729beb9 Mon Sep 17 00:00:00 2001 From: peter-va Date: Thu, 13 Aug 2026 18:38:44 -0700 Subject: [PATCH 3/5] fix vuln --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index a4c8aad27..c2a27f70b 100644 --- a/build.gradle +++ b/build.gradle @@ -134,6 +134,7 @@ dependencies { // other explicit vulnerability overrides implementation "org.apache.commons:commons-lang3:3.18.0" + implementation "org.apache.httpcomponents.core5:httpcore5:5.4.3" implementation "org.apache.tomcat.embed:tomcat-embed-core:10.1.55" implementation "org.apache.thrift:libthrift:0.23.0" implementation "org.thymeleaf:thymeleaf:3.1.5.RELEASE" From 036565ef625f63e533213f35c323ba01124bbc89 Mon Sep 17 00:00:00 2001 From: peter-va Date: Thu, 13 Aug 2026 18:47:15 -0700 Subject: [PATCH 4/5] trying again --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index c2a27f70b..b1a01ca69 100644 --- a/build.gradle +++ b/build.gradle @@ -135,6 +135,7 @@ dependencies { // other explicit vulnerability overrides implementation "org.apache.commons:commons-lang3:3.18.0" implementation "org.apache.httpcomponents.core5:httpcore5:5.4.3" + implementation "org.apache.httpcomponents.core5:httpcore5-h2:5.4.3" implementation "org.apache.tomcat.embed:tomcat-embed-core:10.1.55" implementation "org.apache.thrift:libthrift:0.23.0" implementation "org.thymeleaf:thymeleaf:3.1.5.RELEASE" From 4ab098e370e8e1087301017a66749c0e5238245e Mon Sep 17 00:00:00 2001 From: peter-va Date: Thu, 13 Aug 2026 19:05:01 -0700 Subject: [PATCH 5/5] different approach --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index b1a01ca69..c639f79ff 100644 --- a/build.gradle +++ b/build.gradle @@ -45,6 +45,8 @@ repositories { ///ext['commons-lang3.version'] = '3.18.0' // Override Boot BOM Jackson version to fix CVE-2026-54512 / CVE-2026-54513 (HIGH) ///ext['jackson-bom.version'] = '2.21.4' +// Override Boot BOM httpcore5 version to fix CVE-2026-54399 / CVE-2026-54428 (HIGH) +ext['httpcore5.version'] = '5.4.3' // Extra Properties ext { @@ -134,8 +136,6 @@ dependencies { // other explicit vulnerability overrides implementation "org.apache.commons:commons-lang3:3.18.0" - implementation "org.apache.httpcomponents.core5:httpcore5:5.4.3" - implementation "org.apache.httpcomponents.core5:httpcore5-h2:5.4.3" implementation "org.apache.tomcat.embed:tomcat-embed-core:10.1.55" implementation "org.apache.thrift:libthrift:0.23.0" implementation "org.thymeleaf:thymeleaf:3.1.5.RELEASE"