mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-08-11 13:48:37 +02:00
tests
This commit is contained in:
parent
979f302277
commit
4ff940c229
@ -0,0 +1,17 @@
|
||||
package stirling.software.common.configuration.interfaces;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class ShowAdminInterfaceTest {
|
||||
|
||||
// Create a simple implementation for testing
|
||||
static class TestImpl implements ShowAdminInterface {}
|
||||
|
||||
@Test
|
||||
void getShowUpdateOnlyAdmins_returnsTrueByDefault() {
|
||||
ShowAdminInterface instance = new TestImpl();
|
||||
assertTrue(instance.getShowUpdateOnlyAdmins(), "Default should return true");
|
||||
}
|
||||
}
|
@ -18,7 +18,6 @@ class ApplicationPropertiesDynamicYamlPropertySourceTest {
|
||||
|
||||
@Test
|
||||
void loads_yaml_into_environment() throws Exception {
|
||||
// YAML-Config in Temp-Datei schreiben
|
||||
String yaml =
|
||||
""
|
||||
+ "ui:\n"
|
||||
@ -28,7 +27,6 @@ class ApplicationPropertiesDynamicYamlPropertySourceTest {
|
||||
Path tmp = Files.createTempFile("spdf-settings-", ".yml");
|
||||
Files.writeString(tmp, yaml);
|
||||
|
||||
// Pfad per statischem Mock liefern
|
||||
try (MockedStatic<InstallationPathConfig> mocked =
|
||||
Mockito.mockStatic(InstallationPathConfig.class)) {
|
||||
mocked.when(InstallationPathConfig::getSettingsPath).thenReturn(tmp.toString());
|
||||
@ -36,7 +34,7 @@ class ApplicationPropertiesDynamicYamlPropertySourceTest {
|
||||
ConfigurableEnvironment env = new StandardEnvironment();
|
||||
ApplicationProperties props = new ApplicationProperties();
|
||||
|
||||
props.dynamicYamlPropertySource(env); // fügt PropertySource an erster Stelle ein
|
||||
props.dynamicYamlPropertySource(env);
|
||||
|
||||
assertEquals("My App", env.getProperty("ui.appName"));
|
||||
assertEquals("true", env.getProperty("system.enableAnalytics"));
|
||||
|
@ -1,27 +1,32 @@
|
||||
package stirling.software.common.util;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.RenderedImage;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.pdfbox.cos.COSName;
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.apache.pdfbox.pdmodel.PDPage;
|
||||
import org.apache.pdfbox.pdmodel.PDPageContentStream;
|
||||
import org.apache.pdfbox.pdmodel.PDPageContentStream.AppendMode;
|
||||
import org.apache.pdfbox.pdmodel.PDResources;
|
||||
import org.apache.pdfbox.pdmodel.common.PDRectangle;
|
||||
import org.apache.pdfbox.pdmodel.graphics.PDXObject;
|
||||
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
|
||||
import org.apache.pdfbox.pdmodel.graphics.image.LosslessFactory;
|
||||
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import stirling.software.common.model.ApplicationProperties;
|
||||
import stirling.software.common.service.CustomPDFDocumentFactory;
|
||||
@ -31,32 +36,87 @@ public class PdfUtilsTest {
|
||||
|
||||
@Test
|
||||
void testTextToPageSize() {
|
||||
assertEquals(PDRectangle.A0, PdfUtils.textToPageSize("A0"));
|
||||
assertEquals(PDRectangle.A1, PdfUtils.textToPageSize("A1"));
|
||||
assertEquals(PDRectangle.A2, PdfUtils.textToPageSize("A2"));
|
||||
assertEquals(PDRectangle.A3, PdfUtils.textToPageSize("A3"));
|
||||
assertEquals(PDRectangle.A4, PdfUtils.textToPageSize("A4"));
|
||||
assertEquals(PDRectangle.A5, PdfUtils.textToPageSize("A5"));
|
||||
assertEquals(PDRectangle.A6, PdfUtils.textToPageSize("A6"));
|
||||
assertEquals(PDRectangle.LETTER, PdfUtils.textToPageSize("LETTER"));
|
||||
assertEquals(PDRectangle.LEGAL, PdfUtils.textToPageSize("LEGAL"));
|
||||
assertThrows(IllegalArgumentException.class, () -> PdfUtils.textToPageSize("INVALID"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHasImagesOnPage() throws IOException {
|
||||
// Mock a PDPage and its resources
|
||||
PDPage page = Mockito.mock(PDPage.class);
|
||||
PDResources resources = Mockito.mock(PDResources.class);
|
||||
Mockito.when(page.getResources()).thenReturn(resources);
|
||||
void testGetAllImages() throws Exception {
|
||||
// Root resources
|
||||
PDResources root = mock(PDResources.class);
|
||||
|
||||
// Case 1: No images in resources
|
||||
Mockito.when(resources.getXObjectNames()).thenReturn(Collections.emptySet());
|
||||
assertFalse(PdfUtils.hasImagesOnPage(page));
|
||||
COSName im1 = COSName.getPDFName("Im1");
|
||||
COSName form1 = COSName.getPDFName("Form1");
|
||||
COSName other1 = COSName.getPDFName("Other1");
|
||||
when(root.getXObjectNames()).thenReturn(Arrays.asList(im1, form1, other1));
|
||||
|
||||
// Case 2: Resources with an image
|
||||
Set<COSName> xObjectNames = new HashSet<>();
|
||||
COSName cosName = Mockito.mock(COSName.class);
|
||||
xObjectNames.add(cosName);
|
||||
// Direct image at root
|
||||
PDImageXObject imgXObj1 = mock(PDImageXObject.class);
|
||||
BufferedImage img1 = new BufferedImage(2, 2, BufferedImage.TYPE_INT_ARGB);
|
||||
when(imgXObj1.getImage()).thenReturn(img1);
|
||||
when(root.getXObject(im1)).thenReturn(imgXObj1);
|
||||
|
||||
PDImageXObject imageXObject = Mockito.mock(PDImageXObject.class);
|
||||
Mockito.when(resources.getXObjectNames()).thenReturn(xObjectNames);
|
||||
Mockito.when(resources.getXObject(cosName)).thenReturn(imageXObject);
|
||||
// "Other" XObject that should be ignored
|
||||
PDXObject otherXObj = mock(PDXObject.class);
|
||||
when(root.getXObject(other1)).thenReturn(otherXObj);
|
||||
|
||||
assertTrue(PdfUtils.hasImagesOnPage(page));
|
||||
// Form XObject with its own resources
|
||||
PDFormXObject formXObj = mock(PDFormXObject.class);
|
||||
PDResources formRes = mock(PDResources.class);
|
||||
when(formXObj.getResources()).thenReturn(formRes);
|
||||
when(root.getXObject(form1)).thenReturn(formXObj);
|
||||
|
||||
// Inside the form: one image and a nested form
|
||||
COSName im2 = COSName.getPDFName("Im2");
|
||||
COSName nestedForm = COSName.getPDFName("NestedForm");
|
||||
when(formRes.getXObjectNames()).thenReturn(Arrays.asList(im2, nestedForm));
|
||||
|
||||
PDImageXObject imgXObj2 = mock(PDImageXObject.class);
|
||||
BufferedImage img2 = new BufferedImage(3, 3, BufferedImage.TYPE_INT_RGB);
|
||||
when(imgXObj2.getImage()).thenReturn(img2);
|
||||
when(formRes.getXObject(im2)).thenReturn(imgXObj2);
|
||||
|
||||
PDFormXObject nestedFormXObj = mock(PDFormXObject.class);
|
||||
PDResources nestedRes = mock(PDResources.class);
|
||||
when(nestedFormXObj.getResources()).thenReturn(nestedRes);
|
||||
when(formRes.getXObject(nestedForm)).thenReturn(nestedFormXObj);
|
||||
|
||||
// Deep nest: another image
|
||||
COSName im3 = COSName.getPDFName("Im3");
|
||||
when(nestedRes.getXObjectNames()).thenReturn(List.of(im3));
|
||||
|
||||
PDImageXObject imgXObj3 = mock(PDImageXObject.class);
|
||||
BufferedImage img3 = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
|
||||
when(imgXObj3.getImage()).thenReturn(img3);
|
||||
when(nestedRes.getXObject(im3)).thenReturn(imgXObj3);
|
||||
|
||||
// Act
|
||||
List<RenderedImage> result = PdfUtils.getAllImages(root);
|
||||
|
||||
// Assert
|
||||
assertEquals(
|
||||
3, result.size(), "It should find exactly 3 images (root + form + nested form).");
|
||||
assertTrue(
|
||||
result.containsAll(List.of(img1, img2, img3)),
|
||||
"All expected images must be present.");
|
||||
}
|
||||
|
||||
// Helper method to draw a tiny image on a PDF page
|
||||
private static void drawTinyImage(PDDocument doc, PDPage page) throws IOException {
|
||||
BufferedImage bi = new BufferedImage(2, 2, BufferedImage.TYPE_INT_RGB);
|
||||
PDImageXObject ximg = LosslessFactory.createFromImage(doc, bi);
|
||||
try (PDPageContentStream cs =
|
||||
new PDPageContentStream(doc, page, AppendMode.APPEND, true, true)) {
|
||||
cs.drawImage(ximg, 10, 10, 10, 10);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -200,7 +200,7 @@ public class SPDFApplication {
|
||||
log.info("Navigate to {}", url);
|
||||
}
|
||||
|
||||
private static String[] getActiveProfile(String[] args) {
|
||||
protected static String[] getActiveProfile(String[] args) {
|
||||
// 1. Check for explicitly passed profiles
|
||||
if (args != null) {
|
||||
for (String arg : args) {
|
||||
@ -224,7 +224,7 @@ public class SPDFApplication {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isClassPresent(String className) {
|
||||
protected static boolean isClassPresent(String className) {
|
||||
try {
|
||||
Class.forName(className, false, SPDFApplication.class.getClassLoader());
|
||||
return true;
|
||||
|
@ -1,15 +1,18 @@
|
||||
package stirling.software.SPDF;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
import stirling.software.common.configuration.AppConfig;
|
||||
import stirling.software.common.model.ApplicationProperties;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@ -21,6 +24,8 @@ public class SPDFApplicationTest {
|
||||
|
||||
@InjectMocks private SPDFApplication sPDFApplication;
|
||||
|
||||
@Mock private AppConfig appConfig;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
SPDFApplication.setServerPortStatic("8080");
|
||||
@ -36,4 +41,49 @@ public class SPDFApplicationTest {
|
||||
public void testGetStaticPort() {
|
||||
assertEquals("8080", SPDFApplication.getStaticPort());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetServerPortStaticAuto() {
|
||||
SPDFApplication.setServerPortStatic("auto");
|
||||
assertEquals("0", SPDFApplication.getStaticPort());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInit() {
|
||||
when(appConfig.getBaseUrl()).thenReturn("http://localhost");
|
||||
when(appConfig.getContextPath()).thenReturn("/app");
|
||||
when(appConfig.getServerPort()).thenReturn("8080");
|
||||
|
||||
sPDFApplication.init();
|
||||
|
||||
assertEquals("http://localhost", SPDFApplication.getStaticBaseUrl());
|
||||
assertEquals("/app", SPDFApplication.getStaticContextPath());
|
||||
assertEquals("8080", SPDFApplication.getStaticPort());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetActiveProfileWithArgs() {
|
||||
String[] args = {"--spring.profiles.active=security"};
|
||||
String[] profiles = SPDFApplication.getActiveProfile(args);
|
||||
assertEquals(1, profiles.length);
|
||||
assertEquals("security", profiles[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnabledIfEnvironmentVariable(named = "DISABLE_ADDITIONAL_FEATURES", matches = "true")
|
||||
public void testGetActiveProfileWithoutArgsAdditionalEnabled() {
|
||||
String[] args = {};
|
||||
String[] profiles = SPDFApplication.getActiveProfile(args);
|
||||
assertEquals(1, profiles.length);
|
||||
assertEquals("default", profiles[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnabledIfEnvironmentVariable(named = "DISABLE_ADDITIONAL_FEATURES", matches = "false")
|
||||
public void testGetActiveProfileWithoutArgsAdditionalDisabled() {
|
||||
String[] args = {};
|
||||
String[] profiles = SPDFApplication.getActiveProfile(args);
|
||||
assertEquals(1, profiles.length);
|
||||
assertEquals("default", profiles[0]);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,59 @@
|
||||
package stirling.software.SPDF.controller.api;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
|
||||
import stirling.software.SPDF.service.LanguageService;
|
||||
|
||||
class AdditionalLanguageJsControllerTest {
|
||||
|
||||
@Test
|
||||
void returns_js_with_supported_languages_and_function() throws Exception {
|
||||
LanguageService lang = mock(LanguageService.class);
|
||||
// LinkedHashSet für deterministische Reihenfolge im Array
|
||||
when(lang.getSupportedLanguages())
|
||||
.thenReturn(new LinkedHashSet<>(List.of("de_DE", "en_GB")));
|
||||
|
||||
MockMvc mvc =
|
||||
MockMvcBuilders.standaloneSetup(new AdditionalLanguageJsController(lang)).build();
|
||||
|
||||
mvc.perform(get("/js/additionalLanguageCode.js"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(new MediaType("application", "javascript")))
|
||||
.andExpect(
|
||||
content()
|
||||
.string(
|
||||
containsString(
|
||||
"const supportedLanguages ="
|
||||
+ " [\"de_DE\",\"en_GB\"];")))
|
||||
.andExpect(content().string(containsString("function getDetailedLanguageCode()")))
|
||||
.andExpect(content().string(containsString("return \"en_GB\";")));
|
||||
|
||||
verify(lang, times(1)).getSupportedLanguages();
|
||||
}
|
||||
|
||||
@Test
|
||||
void empty_supported_languages_yields_empty_array() throws Exception {
|
||||
LanguageService lang = mock(LanguageService.class);
|
||||
when(lang.getSupportedLanguages()).thenReturn(Set.of());
|
||||
|
||||
MockMvc mvc =
|
||||
MockMvcBuilders.standaloneSetup(new AdditionalLanguageJsController(lang)).build();
|
||||
|
||||
mvc.perform(get("/js/additionalLanguageCode.js"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(new MediaType("application", "javascript")))
|
||||
.andExpect(content().string(containsString("const supportedLanguages = [];")));
|
||||
}
|
||||
}
|
@ -0,0 +1,99 @@
|
||||
package stirling.software.SPDF.controller.api;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
|
||||
import stirling.software.SPDF.config.EndpointConfiguration;
|
||||
import stirling.software.common.configuration.InstallationPathConfig;
|
||||
import stirling.software.common.model.ApplicationProperties;
|
||||
import stirling.software.common.util.GeneralUtils;
|
||||
|
||||
class SettingsControllerTest {
|
||||
|
||||
private MockMvc mockMvc(ApplicationProperties props, EndpointConfiguration endpoints) {
|
||||
SettingsController controller = new SettingsController(props, endpoints);
|
||||
return MockMvcBuilders.standaloneSetup(controller).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
void update_enable_analytics_returns_208_when_already_set() throws Exception {
|
||||
ApplicationProperties props = new ApplicationProperties();
|
||||
props.getSystem().setEnableAnalytics(Boolean.FALSE);
|
||||
|
||||
EndpointConfiguration endpoints = mock(EndpointConfiguration.class);
|
||||
|
||||
try (MockedStatic<InstallationPathConfig> install =
|
||||
Mockito.mockStatic(InstallationPathConfig.class);
|
||||
MockedStatic<GeneralUtils> gen = Mockito.mockStatic(GeneralUtils.class)) {
|
||||
|
||||
install.when(InstallationPathConfig::getSettingsPath)
|
||||
.thenReturn("/etc/spdf/settings.yml");
|
||||
|
||||
MockMvc mvc = mockMvc(props, endpoints);
|
||||
|
||||
// Act + Assert
|
||||
mvc.perform(
|
||||
post("/api/v1/settings/update-enable-analytics")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("true"))
|
||||
.andExpect(status().isAlreadyReported())
|
||||
.andExpect(content().string(containsString("Setting has already been set")))
|
||||
.andExpect(content().string(containsString("/etc/spdf/settings.yml")));
|
||||
|
||||
gen.verifyNoInteractions();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void update_enable_analytics_sets_value_and_saves_when_not_set() throws Exception {
|
||||
ApplicationProperties props = new ApplicationProperties();
|
||||
props.getSystem().setEnableAnalytics(null);
|
||||
|
||||
EndpointConfiguration endpoints = mock(EndpointConfiguration.class);
|
||||
|
||||
try (MockedStatic<GeneralUtils> gen = Mockito.mockStatic(GeneralUtils.class)) {
|
||||
MockMvc mvc = mockMvc(props, endpoints);
|
||||
|
||||
// Act + Assert
|
||||
mvc.perform(
|
||||
post("/api/v1/settings/update-enable-analytics")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("true"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("Updated"));
|
||||
|
||||
gen.verify(
|
||||
() -> GeneralUtils.saveKeyToSettings(eq("system.enableAnalytics"), eq(true)));
|
||||
|
||||
assertEquals(Boolean.TRUE, props.getSystem().getEnableAnalytics());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void get_endpoints_status_returns_map() throws Exception {
|
||||
ApplicationProperties props = new ApplicationProperties();
|
||||
EndpointConfiguration endpoints = mock(EndpointConfiguration.class);
|
||||
when(endpoints.getEndpointStatuses())
|
||||
.thenReturn(Map.of("convert.pdf.markdown", true, "merge", false));
|
||||
|
||||
MockMvc mvc = mockMvc(props, endpoints);
|
||||
|
||||
mvc.perform(get("/api/v1/settings/get-endpoints-status"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.['convert.pdf.markdown']").value(true))
|
||||
.andExpect(jsonPath("$.merge").value(false));
|
||||
}
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
package stirling.software.SPDF.model;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
|
||||
class ApiEndpointTest {
|
||||
|
||||
private final ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
private JsonNode postNodeWithParams(String description, String... names) {
|
||||
ObjectNode post = mapper.createObjectNode();
|
||||
post.put("description", description);
|
||||
ArrayNode params = mapper.createArrayNode();
|
||||
for (String n : names) {
|
||||
ObjectNode p = mapper.createObjectNode();
|
||||
if (n != null) {
|
||||
p.put("name", n);
|
||||
}
|
||||
params.add(p);
|
||||
}
|
||||
post.set("parameters", params);
|
||||
return post;
|
||||
}
|
||||
|
||||
@Test
|
||||
void parses_description_and_validates_required_parameters() {
|
||||
JsonNode post = postNodeWithParams("Convert PDF to Markdown", "file", "mode");
|
||||
ApiEndpoint endpoint = new ApiEndpoint("pdfToMd", post);
|
||||
|
||||
assertEquals("Convert PDF to Markdown", endpoint.getDescription());
|
||||
|
||||
Map<String, Object> provided = new HashMap<>();
|
||||
provided.put("file", new byte[] {1});
|
||||
provided.put("mode", "fast");
|
||||
|
||||
assertTrue(
|
||||
endpoint.areParametersValid(provided), "All required keys present should be valid");
|
||||
}
|
||||
|
||||
@Test
|
||||
void missing_any_required_parameter_returns_false() {
|
||||
JsonNode post = postNodeWithParams("desc", "file", "mode");
|
||||
ApiEndpoint endpoint = new ApiEndpoint("pdfToMd", post);
|
||||
|
||||
Map<String, Object> provided = new HashMap<>();
|
||||
provided.put("file", new byte[] {1});
|
||||
|
||||
assertFalse(endpoint.areParametersValid(provided));
|
||||
}
|
||||
|
||||
@Test
|
||||
void extra_parameters_are_ignored_if_required_are_present() {
|
||||
JsonNode post = postNodeWithParams("desc", "file");
|
||||
ApiEndpoint endpoint = new ApiEndpoint("x", post);
|
||||
|
||||
Map<String, Object> provided = new HashMap<>();
|
||||
provided.put("file", new byte[] {1});
|
||||
provided.put("extra", 123);
|
||||
|
||||
assertTrue(endpoint.areParametersValid(provided));
|
||||
}
|
||||
|
||||
@Test
|
||||
void no_parameters_defined_accepts_empty_input() {
|
||||
JsonNode postEmptyArray = postNodeWithParams("desc" /* no names */);
|
||||
ApiEndpoint endpointA = new ApiEndpoint("a", postEmptyArray);
|
||||
assertTrue(endpointA.areParametersValid(Map.of()));
|
||||
|
||||
ObjectNode postNoField = mapper.createObjectNode();
|
||||
postNoField.put("description", "desc");
|
||||
ApiEndpoint endpointB = new ApiEndpoint("b", postNoField);
|
||||
assertTrue(endpointB.areParametersValid(Map.of()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void parameter_without_name_creates_empty_required_key() {
|
||||
JsonNode post = postNodeWithParams("desc", (String) null);
|
||||
ApiEndpoint endpoint = new ApiEndpoint("y", post);
|
||||
|
||||
assertFalse(endpoint.areParametersValid(Map.of()));
|
||||
|
||||
assertTrue(endpoint.areParametersValid(Map.of("", 42)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void toString_contains_name_and_parameter_names() {
|
||||
JsonNode post = postNodeWithParams("desc", "file", "mode");
|
||||
ApiEndpoint endpoint = new ApiEndpoint("pdfToMd", post);
|
||||
|
||||
String s = endpoint.toString();
|
||||
assertTrue(s.contains("pdfToMd"));
|
||||
assertTrue(s.contains("file"));
|
||||
assertTrue(s.contains("mode"));
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package stirling.software.SPDF.model;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.EnumSource;
|
||||
|
||||
class SortTypesTest {
|
||||
|
||||
private static final Set<String> EXPECTED =
|
||||
Set.of(
|
||||
"CUSTOM",
|
||||
"REVERSE_ORDER",
|
||||
"DUPLEX_SORT",
|
||||
"BOOKLET_SORT",
|
||||
"SIDE_STITCH_BOOKLET_SORT",
|
||||
"ODD_EVEN_SPLIT",
|
||||
"ODD_EVEN_MERGE",
|
||||
"REMOVE_FIRST",
|
||||
"REMOVE_LAST",
|
||||
"REMOVE_FIRST_AND_LAST",
|
||||
"DUPLICATE");
|
||||
|
||||
@Test
|
||||
void contains_exactly_expected_constants() {
|
||||
Set<String> actual =
|
||||
Arrays.stream(SortTypes.values()).map(Enum::name).collect(Collectors.toSet());
|
||||
|
||||
assertEquals(
|
||||
EXPECTED,
|
||||
actual,
|
||||
() -> "Enum constants mismatch.\nExpected: " + EXPECTED + "\nActual: " + actual);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@EnumSource(SortTypes.class)
|
||||
void valueOf_roundtrip(SortTypes type) {
|
||||
assertEquals(type, SortTypes.valueOf(type.name()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void names_are_unique_and_uppercase() {
|
||||
String[] names = Arrays.stream(SortTypes.values()).map(Enum::name).toArray(String[]::new);
|
||||
assertEquals(names.length, Set.of(names).size(), "Duplicate enum names?");
|
||||
for (String n : names) {
|
||||
assertEquals(n, n.toUpperCase(), "Enum name not uppercase: " + n);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
package stirling.software.SPDF.model.api;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class PDFWithPageNumsTest {
|
||||
|
||||
private PDFWithPageNums pdfWithPageNums;
|
||||
private PDDocument mockDocument;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
pdfWithPageNums = new PDFWithPageNums();
|
||||
mockDocument = mock(PDDocument.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetPageNumbersList_AllPages() {
|
||||
pdfWithPageNums.setPageNumbers("all");
|
||||
when(mockDocument.getNumberOfPages()).thenReturn(10);
|
||||
|
||||
List<Integer> result = pdfWithPageNums.getPageNumbersList(mockDocument, true);
|
||||
|
||||
assertEquals(List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetPageNumbersList_135_7Pages() {
|
||||
pdfWithPageNums.setPageNumbers("1,3,5-7");
|
||||
when(mockDocument.getNumberOfPages()).thenReturn(10);
|
||||
|
||||
List<Integer> result = pdfWithPageNums.getPageNumbersList(mockDocument, true);
|
||||
|
||||
assertEquals(List.of(1, 3, 5, 6, 7), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetPageNumbersList_2nPlus1Pages() {
|
||||
pdfWithPageNums.setPageNumbers("2n+1");
|
||||
when(mockDocument.getNumberOfPages()).thenReturn(10);
|
||||
|
||||
List<Integer> result = pdfWithPageNums.getPageNumbersList(mockDocument, true);
|
||||
|
||||
assertEquals(List.of(3, 5, 7, 9), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetPageNumbersList_3nPages() {
|
||||
pdfWithPageNums.setPageNumbers("3n");
|
||||
when(mockDocument.getNumberOfPages()).thenReturn(10);
|
||||
|
||||
List<Integer> result = pdfWithPageNums.getPageNumbersList(mockDocument, true);
|
||||
|
||||
assertEquals(List.of(3, 6, 9), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetPageNumbersList_EmptyInput() {
|
||||
pdfWithPageNums.setPageNumbers("");
|
||||
when(mockDocument.getNumberOfPages()).thenReturn(10);
|
||||
|
||||
List<Integer> result = pdfWithPageNums.getPageNumbersList(mockDocument, true);
|
||||
|
||||
assertTrue(result.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetPageNumbersList_InvalidInput() {
|
||||
pdfWithPageNums.setPageNumbers("invalid");
|
||||
when(mockDocument.getNumberOfPages()).thenReturn(10);
|
||||
|
||||
assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> {
|
||||
pdfWithPageNums.getPageNumbersList(mockDocument, true);
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,170 @@
|
||||
package stirling.software.SPDF.model.api.misc;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
|
||||
import jakarta.validation.ConstraintViolation;
|
||||
import jakarta.validation.Validation;
|
||||
import jakarta.validation.Validator;
|
||||
import jakarta.validation.ValidatorFactory;
|
||||
|
||||
class ScannerEffectRequestTest {
|
||||
|
||||
private static Validator validator;
|
||||
|
||||
@BeforeAll
|
||||
static void setUpValidator() {
|
||||
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
|
||||
validator = factory.getValidator();
|
||||
}
|
||||
|
||||
@Test
|
||||
void defaults_are_set_correctly() {
|
||||
ScannerEffectRequest req = new ScannerEffectRequest();
|
||||
|
||||
assertNull(req.getFileInput());
|
||||
assertEquals(ScannerEffectRequest.Quality.high, req.getQuality());
|
||||
assertEquals(ScannerEffectRequest.Rotation.slight, req.getRotation());
|
||||
assertEquals(ScannerEffectRequest.Colorspace.grayscale, req.getColorspace());
|
||||
|
||||
assertEquals(20, req.getBorder());
|
||||
assertEquals(0, req.getRotate());
|
||||
assertEquals(2, req.getRotateVariance());
|
||||
|
||||
assertEquals(1.0f, req.getBrightness(), 0.0001);
|
||||
assertEquals(1.0f, req.getContrast(), 0.0001);
|
||||
assertEquals(1.0f, req.getBlur(), 0.0001);
|
||||
assertEquals(8.0f, req.getNoise(), 0.0001);
|
||||
|
||||
assertFalse(req.isYellowish());
|
||||
assertEquals(300, req.getResolution());
|
||||
assertFalse(req.isAdvancedEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
void bean_validation_detects_missing_required_fields() {
|
||||
ScannerEffectRequest req = new ScannerEffectRequest();
|
||||
// Defaults: fileInput=null, quality != null, rotation != null
|
||||
Set<ConstraintViolation<ScannerEffectRequest>> violations = validator.validate(req);
|
||||
assertTrue(
|
||||
violations.stream().anyMatch(v -> "File input is required".equals(v.getMessage())),
|
||||
"Expected violation for missing fileInput");
|
||||
|
||||
// Make also quality and rotation invalid
|
||||
req.setQuality(null);
|
||||
req.setRotation(null);
|
||||
violations = validator.validate(req);
|
||||
|
||||
assertTrue(
|
||||
violations.stream().anyMatch(v -> "File input is required".equals(v.getMessage())));
|
||||
assertTrue(violations.stream().anyMatch(v -> "Quality is required".equals(v.getMessage())));
|
||||
assertTrue(
|
||||
violations.stream().anyMatch(v -> "Rotation is required".equals(v.getMessage())));
|
||||
}
|
||||
|
||||
@Test
|
||||
void quality_value_mapping_is_correct() {
|
||||
ScannerEffectRequest req = new ScannerEffectRequest();
|
||||
|
||||
req.setQuality(ScannerEffectRequest.Quality.low);
|
||||
assertEquals(30, req.getQualityValue());
|
||||
|
||||
req.setQuality(ScannerEffectRequest.Quality.medium);
|
||||
assertEquals(60, req.getQualityValue());
|
||||
|
||||
req.setQuality(ScannerEffectRequest.Quality.high);
|
||||
assertEquals(100, req.getQualityValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void rotation_value_mapping_is_correct() {
|
||||
ScannerEffectRequest req = new ScannerEffectRequest();
|
||||
|
||||
req.setRotation(ScannerEffectRequest.Rotation.none);
|
||||
assertEquals(0, req.getRotationValue());
|
||||
|
||||
req.setRotation(ScannerEffectRequest.Rotation.slight);
|
||||
assertEquals(2, req.getRotationValue());
|
||||
|
||||
req.setRotation(ScannerEffectRequest.Rotation.moderate);
|
||||
assertEquals(5, req.getRotationValue());
|
||||
|
||||
req.setRotation(ScannerEffectRequest.Rotation.severe);
|
||||
assertEquals(8, req.getRotationValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
void high_quality_preset_applies_expected_values() {
|
||||
ScannerEffectRequest req = new ScannerEffectRequest();
|
||||
req.applyHighQualityPreset();
|
||||
|
||||
assertEquals(0.1f, req.getBlur(), 0.0001);
|
||||
assertEquals(1.0f, req.getNoise(), 0.0001);
|
||||
assertEquals(1.02f, req.getBrightness(), 0.0001);
|
||||
assertEquals(1.05f, req.getContrast(), 0.0001);
|
||||
assertEquals(600, req.getResolution());
|
||||
}
|
||||
|
||||
@Test
|
||||
void medium_quality_preset_applies_expected_values() {
|
||||
ScannerEffectRequest req = new ScannerEffectRequest();
|
||||
req.applyMediumQualityPreset();
|
||||
|
||||
assertEquals(0.5f, req.getBlur(), 0.0001);
|
||||
assertEquals(3.0f, req.getNoise(), 0.0001);
|
||||
assertEquals(1.05f, req.getBrightness(), 0.0001);
|
||||
assertEquals(1.1f, req.getContrast(), 0.0001);
|
||||
assertEquals(300, req.getResolution());
|
||||
}
|
||||
|
||||
@Test
|
||||
void low_quality_preset_applies_expected_values() {
|
||||
ScannerEffectRequest req = new ScannerEffectRequest();
|
||||
req.applyLowQualityPreset();
|
||||
|
||||
assertEquals(1.0f, req.getBlur(), 0.0001);
|
||||
assertEquals(5.0f, req.getNoise(), 0.0001);
|
||||
assertEquals(1.1f, req.getBrightness(), 0.0001);
|
||||
assertEquals(1.2f, req.getContrast(), 0.0001);
|
||||
assertEquals(150, req.getResolution());
|
||||
}
|
||||
|
||||
@Test
|
||||
void equals_and_hashCode_consider_fileInput() {
|
||||
ScannerEffectRequest a = new ScannerEffectRequest();
|
||||
ScannerEffectRequest b = new ScannerEffectRequest();
|
||||
|
||||
// same defaults -> equal
|
||||
assertEquals(a, b);
|
||||
assertEquals(a.hashCode(), b.hashCode());
|
||||
|
||||
// set file only on one -> not equal
|
||||
MockMultipartFile file =
|
||||
new MockMultipartFile(
|
||||
"fileInput", "x.pdf", "application/pdf", new byte[] {1, 2, 3});
|
||||
a.setFileInput(file);
|
||||
|
||||
assertNotEquals(a, b);
|
||||
assertNotEquals(a.hashCode(), b.hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
void advancedEnabled_flag_roundtrip() {
|
||||
ScannerEffectRequest req = new ScannerEffectRequest();
|
||||
assertFalse(req.isAdvancedEnabled());
|
||||
req.setAdvancedEnabled(true);
|
||||
assertTrue(req.isAdvancedEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
void colorspace_roundtrip() {
|
||||
ScannerEffectRequest req = new ScannerEffectRequest();
|
||||
req.setColorspace(ScannerEffectRequest.Colorspace.color);
|
||||
assertEquals(ScannerEffectRequest.Colorspace.color, req.getColorspace());
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package stirling.software.SPDF.pdf;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
import org.apache.commons.csv.CSVFormat;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class FlexibleCSVWriterTest {
|
||||
|
||||
@Test
|
||||
void testDefaultConstructor() {
|
||||
FlexibleCSVWriter writer = new FlexibleCSVWriter();
|
||||
assertNotNull(writer, "The FlexibleCSVWriter instance should not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testConstructorWithCSVFormat() {
|
||||
CSVFormat csvFormat = CSVFormat.DEFAULT;
|
||||
FlexibleCSVWriter writer = new FlexibleCSVWriter(csvFormat);
|
||||
assertNotNull(
|
||||
writer,
|
||||
"The FlexibleCSVWriter instance should not be null when initialized with"
|
||||
+ " CSVFormat");
|
||||
}
|
||||
}
|
@ -0,0 +1,124 @@
|
||||
package stirling.software.SPDF.service;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import jakarta.servlet.ServletContext;
|
||||
|
||||
import stirling.software.SPDF.model.ApiEndpoint;
|
||||
import stirling.software.common.service.UserServiceInterface;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class ApiDocServiceTest {
|
||||
|
||||
@Mock ServletContext servletContext;
|
||||
@Mock UserServiceInterface userService;
|
||||
|
||||
ApiDocService apiDocService;
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
apiDocService = new ApiDocService(servletContext, userService);
|
||||
}
|
||||
|
||||
private void setApiDocumentation(Map<String, ApiEndpoint> docs) throws Exception {
|
||||
Field field = ApiDocService.class.getDeclaredField("apiDocumentation");
|
||||
field.setAccessible(true);
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, ApiEndpoint> map = (Map<String, ApiEndpoint>) field.get(apiDocService);
|
||||
map.clear();
|
||||
map.putAll(docs);
|
||||
}
|
||||
|
||||
private void setApiDocsJsonRootNode() throws Exception {
|
||||
Field field = ApiDocService.class.getDeclaredField("apiDocsJsonRootNode");
|
||||
field.setAccessible(true);
|
||||
field.set(apiDocService, mapper.createObjectNode());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getExtensionTypesReturnsExpectedList() throws Exception {
|
||||
String json = "{\"description\": \"Output:PDF\"}";
|
||||
JsonNode postNode = mapper.readTree(json);
|
||||
ApiEndpoint endpoint = new ApiEndpoint("/test", postNode);
|
||||
|
||||
setApiDocumentation(Map.of("/test", endpoint));
|
||||
setApiDocsJsonRootNode();
|
||||
|
||||
List<String> extensions = apiDocService.getExtensionTypes(true, "/test");
|
||||
assertEquals(List.of("pdf"), extensions);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getExtensionTypesHandlesUnknownOperation() throws Exception {
|
||||
setApiDocumentation(Map.of());
|
||||
|
||||
List<String> extensions = apiDocService.getExtensionTypes(true, "/unknown");
|
||||
assertNull(extensions);
|
||||
}
|
||||
|
||||
@Test
|
||||
void isValidOperationChecksRequiredParameters() throws Exception {
|
||||
String json =
|
||||
"{\"description\": \"desc\", \"parameters\": [{\"name\":\"param1\"}, {\"name\":\"param2\"}]}";
|
||||
JsonNode postNode = mapper.readTree(json);
|
||||
ApiEndpoint endpoint = new ApiEndpoint("/op", postNode);
|
||||
|
||||
setApiDocumentation(Map.of("/op", endpoint));
|
||||
setApiDocsJsonRootNode();
|
||||
|
||||
assertTrue(apiDocService.isValidOperation("/op", Map.of("param1", "a", "param2", "b")));
|
||||
assertFalse(apiDocService.isValidOperation("/op", Map.of("param1", "a")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isValidOperationHandlesUnknownOperation() throws Exception {
|
||||
setApiDocumentation(Map.of());
|
||||
|
||||
assertFalse(apiDocService.isValidOperation("/unknown", Map.of("param1", "a")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isMultiInputDetectsTypeMI() throws Exception {
|
||||
String json = "{\"description\": \"Type:MI\"}";
|
||||
JsonNode postNode = mapper.readTree(json);
|
||||
ApiEndpoint endpoint = new ApiEndpoint("/multi", postNode);
|
||||
|
||||
setApiDocumentation(Map.of("/multi", endpoint));
|
||||
setApiDocsJsonRootNode();
|
||||
|
||||
assertTrue(apiDocService.isMultiInput("/multi"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isMultiInputDetectsUnknownOperation() throws Exception {
|
||||
setApiDocumentation(Map.of());
|
||||
|
||||
assertFalse(apiDocService.isMultiInput("/unknown"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isMultiInputHandlesNoDescription() throws Exception {
|
||||
String json = "{\"parameters\": [{\"name\":\"param1\"}, {\"name\":\"param2\"}]}";
|
||||
JsonNode postNode = mapper.readTree(json);
|
||||
ApiEndpoint endpoint = new ApiEndpoint("/multi", postNode);
|
||||
|
||||
setApiDocumentation(Map.of("/multi", endpoint));
|
||||
setApiDocsJsonRootNode();
|
||||
|
||||
assertFalse(apiDocService.isMultiInput("/multi"));
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package stirling.software.SPDF.service;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
@ -77,6 +78,9 @@ class CertificateValidationServiceTest {
|
||||
|
||||
// Then validation should succeed
|
||||
assertTrue(result, "Certificate with matching issuer and subject should validate");
|
||||
|
||||
// Ensure no exceptions are thrown during validation
|
||||
assertDoesNotThrow(() -> validationService.validateTrustWithCustomCert(null, issuingCert));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -1,9 +1,12 @@
|
||||
package stirling.software.SPDF.service;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -16,6 +19,7 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
|
||||
import stirling.software.common.model.ApplicationProperties;
|
||||
import stirling.software.common.model.ApplicationProperties.Ui;
|
||||
@ -145,6 +149,45 @@ class LanguageServiceTest {
|
||||
return mockResource;
|
||||
}
|
||||
|
||||
@Test
|
||||
void delegatesToResolverAndReturnsResources() throws IOException {
|
||||
LanguageService service = new LanguageService(applicationProperties);
|
||||
PathMatchingResourcePatternResolver resolver =
|
||||
mock(PathMatchingResourcePatternResolver.class);
|
||||
Resource r1 = mock(Resource.class);
|
||||
Resource r2 = mock(Resource.class);
|
||||
String pattern = "classpath*:messages_*.properties";
|
||||
|
||||
when(resolver.getResources(pattern)).thenReturn(new Resource[] {r1, r2});
|
||||
|
||||
// Inject the mocked resolver into the private final field
|
||||
ReflectionTestUtils.setField(service, "resourcePatternResolver", resolver);
|
||||
|
||||
Resource[] result = service.getResourcesFromPattern(pattern);
|
||||
|
||||
assertArrayEquals(
|
||||
new Resource[] {r1, r2}, result, "Should return exactly what the resolver returns");
|
||||
verify(resolver).getResources(pattern);
|
||||
}
|
||||
|
||||
@Test
|
||||
void propagatesIOExceptionFromResolver() throws IOException {
|
||||
LanguageService service = new LanguageService(applicationProperties);
|
||||
PathMatchingResourcePatternResolver resolver =
|
||||
mock(PathMatchingResourcePatternResolver.class);
|
||||
String pattern = "classpath*:does-not-matter";
|
||||
|
||||
when(resolver.getResources(pattern)).thenThrow(new IOException("boom"));
|
||||
|
||||
// Inject the mocked resolver into the private final field
|
||||
ReflectionTestUtils.setField(service, "resourcePatternResolver", resolver);
|
||||
|
||||
assertThrows(
|
||||
IOException.class,
|
||||
() -> service.getResourcesFromPattern(pattern),
|
||||
"IOException from resolver should propagate");
|
||||
}
|
||||
|
||||
// Test subclass that allows us to control the resource resolver
|
||||
private static class LanguageServiceForTest extends LanguageService {
|
||||
private Resource[] mockResources;
|
||||
|
@ -0,0 +1,75 @@
|
||||
package stirling.software.SPDF.service;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
|
||||
import io.micrometer.core.instrument.Counter;
|
||||
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
|
||||
|
||||
import stirling.software.SPDF.config.EndpointInspector;
|
||||
import stirling.software.common.service.PostHogService;
|
||||
|
||||
class MetricsAggregatorServiceTest {
|
||||
|
||||
private SimpleMeterRegistry meterRegistry;
|
||||
private PostHogService postHogService;
|
||||
private EndpointInspector endpointInspector;
|
||||
private MetricsAggregatorService metricsAggregatorService;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
meterRegistry = new SimpleMeterRegistry();
|
||||
postHogService = mock(PostHogService.class);
|
||||
endpointInspector = mock(EndpointInspector.class);
|
||||
when(endpointInspector.getValidGetEndpoints()).thenReturn(Set.of("/getEndpoint"));
|
||||
when(endpointInspector.isValidGetEndpoint("/getEndpoint")).thenReturn(true);
|
||||
metricsAggregatorService =
|
||||
new MetricsAggregatorService(meterRegistry, postHogService, endpointInspector);
|
||||
}
|
||||
|
||||
@Captor private ArgumentCaptor<Map<String, Object>> captor;
|
||||
|
||||
@Test
|
||||
void testAggregateAndSendMetrics() {
|
||||
meterRegistry.counter("http.requests", "method", "GET", "uri", "/getEndpoint").increment(3);
|
||||
meterRegistry.counter("http.requests", "method", "POST", "uri", "/api/v1/do").increment(2);
|
||||
|
||||
metricsAggregatorService.aggregateAndSendMetrics();
|
||||
|
||||
ArgumentCaptor<Map<String, Object>> captor = ArgumentCaptor.forClass(Map.class);
|
||||
verify(postHogService).captureEvent(eq("aggregated_metrics"), captor.capture());
|
||||
Map<String, Object> metrics = captor.getValue();
|
||||
|
||||
assertEquals(2, metrics.size());
|
||||
assertEquals(3.0, (Double) metrics.get("http_requests_GET__getEndpoint"));
|
||||
assertEquals(2.0, (Double) metrics.get("http_requests_POST__api_v1_do"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAggregateAndSendMetricsSendsOnlyDifferences() {
|
||||
Counter counter =
|
||||
meterRegistry.counter("http.requests", "method", "GET", "uri", "/getEndpoint");
|
||||
counter.increment(5);
|
||||
metricsAggregatorService.aggregateAndSendMetrics();
|
||||
reset(postHogService);
|
||||
|
||||
counter.increment(2);
|
||||
metricsAggregatorService.aggregateAndSendMetrics();
|
||||
|
||||
ArgumentCaptor<Map<String, Object>> captor = ArgumentCaptor.forClass(Map.class);
|
||||
verify(postHogService).captureEvent(eq("aggregated_metrics"), captor.capture());
|
||||
Map<String, Object> metrics = captor.getValue();
|
||||
|
||||
assertEquals(1, metrics.size());
|
||||
assertEquals(2.0, (Double) metrics.get("http_requests_GET__getEndpoint"));
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package stirling.software.SPDF.service.misc;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.springframework.core.io.InputStreamResource;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import stirling.software.SPDF.Factories.ReplaceAndInvertColorFactory;
|
||||
import stirling.software.common.model.api.misc.HighContrastColorCombination;
|
||||
import stirling.software.common.model.api.misc.ReplaceAndInvert;
|
||||
import stirling.software.common.util.misc.ReplaceAndInvertColorStrategy;
|
||||
|
||||
class ReplaceAndInvertColorServiceTest {
|
||||
|
||||
@Mock private ReplaceAndInvertColorFactory replaceAndInvertColorFactory;
|
||||
|
||||
@Mock private MultipartFile file;
|
||||
|
||||
@Mock private ReplaceAndInvertColorStrategy replaceAndInvertColorStrategy;
|
||||
|
||||
@InjectMocks private ReplaceAndInvertColorService replaceAndInvertColorService;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testReplaceAndInvertColor() throws IOException {
|
||||
// Arrange
|
||||
ReplaceAndInvert replaceAndInvertOption = mock(ReplaceAndInvert.class);
|
||||
HighContrastColorCombination highContrastColorCombination =
|
||||
mock(HighContrastColorCombination.class);
|
||||
String backGroundColor = "#FFFFFF";
|
||||
String textColor = "#000000";
|
||||
|
||||
when(replaceAndInvertColorFactory.replaceAndInvert(
|
||||
file,
|
||||
replaceAndInvertOption,
|
||||
highContrastColorCombination,
|
||||
backGroundColor,
|
||||
textColor))
|
||||
.thenReturn(replaceAndInvertColorStrategy);
|
||||
|
||||
InputStreamResource expectedResource = mock(InputStreamResource.class);
|
||||
when(replaceAndInvertColorStrategy.replace()).thenReturn(expectedResource);
|
||||
|
||||
// Act
|
||||
InputStreamResource result =
|
||||
replaceAndInvertColorService.replaceAndInvertColor(
|
||||
file,
|
||||
replaceAndInvertOption,
|
||||
highContrastColorCombination,
|
||||
backGroundColor,
|
||||
textColor);
|
||||
|
||||
// Assert
|
||||
assertNotNull(result);
|
||||
assertEquals(expectedResource, result);
|
||||
verify(replaceAndInvertColorFactory, times(1))
|
||||
.replaceAndInvert(
|
||||
file,
|
||||
replaceAndInvertOption,
|
||||
highContrastColorCombination,
|
||||
backGroundColor,
|
||||
textColor);
|
||||
verify(replaceAndInvertColorStrategy, times(1)).replace();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user